diff options
author | Carlos Martín Nieto <cmn@dwim.me> | 2016-04-27 12:00:31 +0200 |
---|---|---|
committer | Carlos Martín Nieto <cmn@dwim.me> | 2016-05-02 17:37:26 +0200 |
commit | a97b769a0ef7fe8b301c07280c9b80233bb77643 (patch) | |
tree | b7689ab05499e22ca4b9787f12a30a437b7e9547 /src/delta-apply.c | |
parent | 88284dfb7905c5990babb4238b7cd30bdf823500 (diff) | |
download | libgit2-cmn/faster-header.tar.gz |
odb: avoid inflating the full delta to read the headercmn/faster-header
When we read the header, we want to know the size and type of the
object. We're currently inflating the full delta in order to read the
first few bytes. This can mean hundreds of kB needlessly inflated for
large objects.
Instead use a packfile stream to read just enough so we can read the two
varints in the header and avoid inflating most of the delta.
Diffstat (limited to 'src/delta-apply.c')
-rw-r--r-- | src/delta-apply.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/src/delta-apply.c b/src/delta-apply.c index 89745faa0..6e86a81db 100644 --- a/src/delta-apply.c +++ b/src/delta-apply.c @@ -49,6 +49,37 @@ int git__delta_read_header( return 0; } +#define DELTA_HEADER_BUFFER_LEN 16 +int git__delta_read_header_fromstream(size_t *base_sz, size_t *res_sz, git_packfile_stream *stream) +{ + static const size_t buffer_len = DELTA_HEADER_BUFFER_LEN; + unsigned char buffer[DELTA_HEADER_BUFFER_LEN]; + const unsigned char *delta, *delta_end; + size_t len; + ssize_t read; + + len = read = 0; + while (len < buffer_len) { + read = git_packfile_stream_read(stream, &buffer[len], buffer_len - len); + + if (read == 0) + break; + + if (read == GIT_EBUFS) + continue; + + len += read; + } + + delta = buffer; + delta_end = delta + len; + if ((hdr_sz(base_sz, &delta, delta_end) < 0) || + (hdr_sz(res_sz, &delta, delta_end) < 0)) + return -1; + + return 0; +} + int git__delta_apply( git_rawobj *out, const unsigned char *base, |