Skip to content

Commit 776ea37

Browse files
npitregitster
authored andcommitted
index-pack: smarter memory usage when resolving deltas
In the same spirit as commit 9892beb, let's avoid allocating the full buffer for the deflated data in get_data_from_pack() in order to inflate it. Let's read and inflate the data in chunks instead to reduce memory usage. Signed-off-by: Nicolas Pitre <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 748af44 commit 776ea37

File tree

1 file changed

+25
-21
lines changed

1 file changed

+25
-21
lines changed

builtin-index-pack.c

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -359,34 +359,38 @@ static void *get_data_from_pack(struct object_entry *obj)
359359
{
360360
off_t from = obj[0].idx.offset + obj[0].hdr_size;
361361
unsigned long len = obj[1].idx.offset - from;
362-
unsigned long rdy = 0;
363-
unsigned char *src, *data;
362+
unsigned char *data, *inbuf;
364363
z_stream stream;
365-
int st;
364+
int status;
366365

367-
src = xmalloc(len);
368-
data = src;
369-
do {
370-
ssize_t n = pread(pack_fd, data + rdy, len - rdy, from + rdy);
371-
if (n < 0)
372-
die_errno("cannot pread pack file");
373-
if (!n)
374-
die("premature end of pack file, %lu bytes missing",
375-
len - rdy);
376-
rdy += n;
377-
} while (rdy < len);
378366
data = xmalloc(obj->size);
367+
inbuf = xmalloc((len < 64*1024) ? len : 64*1024);
368+
379369
memset(&stream, 0, sizeof(stream));
370+
git_inflate_init(&stream);
380371
stream.next_out = data;
381372
stream.avail_out = obj->size;
382-
stream.next_in = src;
383-
stream.avail_in = len;
384-
git_inflate_init(&stream);
385-
while ((st = git_inflate(&stream, Z_FINISH)) == Z_OK);
386-
git_inflate_end(&stream);
387-
if (st != Z_STREAM_END || stream.total_out != obj->size)
373+
374+
do {
375+
ssize_t n = (len < 64*1024) ? len : 64*1024;
376+
n = pread(pack_fd, inbuf, n, from);
377+
if (n < 0)
378+
die_errno("cannot pread pack file");
379+
if (!n)
380+
die("premature end of pack file, %lu bytes missing", len);
381+
from += n;
382+
len -= n;
383+
stream.next_in = inbuf;
384+
stream.avail_in = n;
385+
status = git_inflate(&stream, 0);
386+
} while (len && status == Z_OK && !stream.avail_in);
387+
388+
/* This has been inflated OK when first encountered, so... */
389+
if (status != Z_STREAM_END || stream.total_out != obj->size)
388390
die("serious inflate inconsistency");
389-
free(src);
391+
392+
git_inflate_end(&stream);
393+
free(inbuf);
390394
return data;
391395
}
392396

0 commit comments

Comments
 (0)