Skip to content

Commit e43e48c

Browse files
committed
Merge branch 'np/index-pack-memsave'
* np/index-pack-memsave: index-pack: smarter memory usage when appending objects index-pack: rationalize unpack_entry_data() index-pack: smarter memory usage when resolving deltas
2 parents edea184 + 7734d7f commit e43e48c

File tree

1 file changed

+45
-44
lines changed

1 file changed

+45
-44
lines changed

builtin/index-pack.c

Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -266,26 +266,23 @@ static void unlink_base_data(struct base_data *c)
266266

267267
static void *unpack_entry_data(unsigned long offset, unsigned long size)
268268
{
269+
int status;
269270
z_stream stream;
270271
void *buf = xmalloc(size);
271272

272273
memset(&stream, 0, sizeof(stream));
274+
git_inflate_init(&stream);
273275
stream.next_out = buf;
274276
stream.avail_out = size;
275-
stream.next_in = fill(1);
276-
stream.avail_in = input_len;
277-
git_inflate_init(&stream);
278277

279-
for (;;) {
280-
int ret = git_inflate(&stream, 0);
281-
use(input_len - stream.avail_in);
282-
if (stream.total_out == size && ret == Z_STREAM_END)
283-
break;
284-
if (ret != Z_OK)
285-
bad_object(offset, "inflate returned %d", ret);
278+
do {
286279
stream.next_in = fill(1);
287280
stream.avail_in = input_len;
288-
}
281+
status = git_inflate(&stream, 0);
282+
use(input_len - stream.avail_in);
283+
} while (status == Z_OK);
284+
if (stream.total_out != size || status != Z_STREAM_END)
285+
bad_object(offset, "inflate returned %d", status);
289286
git_inflate_end(&stream);
290287
return buf;
291288
}
@@ -359,34 +356,38 @@ static void *get_data_from_pack(struct object_entry *obj)
359356
{
360357
off_t from = obj[0].idx.offset + obj[0].hdr_size;
361358
unsigned long len = obj[1].idx.offset - from;
362-
unsigned long rdy = 0;
363-
unsigned char *src, *data;
359+
unsigned char *data, *inbuf;
364360
z_stream stream;
365-
int st;
361+
int status;
366362

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);
378363
data = xmalloc(obj->size);
364+
inbuf = xmalloc((len < 64*1024) ? len : 64*1024);
365+
379366
memset(&stream, 0, sizeof(stream));
367+
git_inflate_init(&stream);
380368
stream.next_out = data;
381369
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)
370+
371+
do {
372+
ssize_t n = (len < 64*1024) ? len : 64*1024;
373+
n = pread(pack_fd, inbuf, n, from);
374+
if (n < 0)
375+
die_errno("cannot pread pack file");
376+
if (!n)
377+
die("premature end of pack file, %lu bytes missing", len);
378+
from += n;
379+
len -= n;
380+
stream.next_in = inbuf;
381+
stream.avail_in = n;
382+
status = git_inflate(&stream, 0);
383+
} while (len && status == Z_OK && !stream.avail_in);
384+
385+
/* This has been inflated OK when first encountered, so... */
386+
if (status != Z_STREAM_END || stream.total_out != obj->size)
388387
die("serious inflate inconsistency");
389-
free(src);
388+
389+
git_inflate_end(&stream);
390+
free(inbuf);
390391
return data;
391392
}
392393

@@ -668,25 +669,25 @@ static void parse_pack_objects(unsigned char *sha1)
668669
static int write_compressed(struct sha1file *f, void *in, unsigned int size)
669670
{
670671
z_stream stream;
671-
unsigned long maxsize;
672-
void *out;
672+
int status;
673+
unsigned char outbuf[4096];
673674

674675
memset(&stream, 0, sizeof(stream));
675676
deflateInit(&stream, zlib_compression_level);
676-
maxsize = deflateBound(&stream, size);
677-
out = xmalloc(maxsize);
678-
679-
/* Compress it */
680677
stream.next_in = in;
681678
stream.avail_in = size;
682-
stream.next_out = out;
683-
stream.avail_out = maxsize;
684-
while (deflate(&stream, Z_FINISH) == Z_OK);
685-
deflateEnd(&stream);
686679

680+
do {
681+
stream.next_out = outbuf;
682+
stream.avail_out = sizeof(outbuf);
683+
status = deflate(&stream, Z_FINISH);
684+
sha1write(f, outbuf, sizeof(outbuf) - stream.avail_out);
685+
} while (status == Z_OK);
686+
687+
if (status != Z_STREAM_END)
688+
die("unable to deflate appended object (%d)", status);
687689
size = stream.total_out;
688-
sha1write(f, out, size);
689-
free(out);
690+
deflateEnd(&stream);
690691
return size;
691692
}
692693

0 commit comments

Comments
 (0)