Skip to content

Commit 9892beb

Browse files
npitregitster
authored andcommitted
sha1_file: don't malloc the whole compressed result when writing out objects
There is no real advantage to malloc the whole output buffer and deflate the data in a single pass when writing loose objects. That is like only 1% faster while using more memory, especially with large files where memory usage is far more. It is best to deflate and write the data out in small chunks reusing the same memory instead. For example, using 'git add' on a few large files averaging 40 MB ... Before: 21.45user 1.10system 0:22.57elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+828040outputs (0major+142640minor)pagefaults 0swaps After: 21.50user 1.25system 0:22.76elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+828040outputs (0major+104408minor)pagefaults 0swaps While the runtime stayed relatively the same, the number of minor page faults went down significantly. Signed-off-by: Nicolas Pitre <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent e923eae commit 9892beb

File tree

1 file changed

+10
-14
lines changed

1 file changed

+10
-14
lines changed

sha1_file.c

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2281,8 +2281,7 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
22812281
void *buf, unsigned long len, time_t mtime)
22822282
{
22832283
int fd, ret;
2284-
size_t size;
2285-
unsigned char *compressed;
2284+
unsigned char compressed[4096];
22862285
z_stream stream;
22872286
char *filename;
22882287
static char tmpfile[PATH_MAX];
@@ -2301,12 +2300,8 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
23012300
/* Set it up */
23022301
memset(&stream, 0, sizeof(stream));
23032302
deflateInit(&stream, zlib_compression_level);
2304-
size = 8 + deflateBound(&stream, len+hdrlen);
2305-
compressed = xmalloc(size);
2306-
2307-
/* Compress it */
23082303
stream.next_out = compressed;
2309-
stream.avail_out = size;
2304+
stream.avail_out = sizeof(compressed);
23102305

23112306
/* First header.. */
23122307
stream.next_in = (unsigned char *)hdr;
@@ -2317,20 +2312,21 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
23172312
/* Then the data itself.. */
23182313
stream.next_in = buf;
23192314
stream.avail_in = len;
2320-
ret = deflate(&stream, Z_FINISH);
2315+
do {
2316+
ret = deflate(&stream, Z_FINISH);
2317+
if (write_buffer(fd, compressed, stream.next_out - compressed) < 0)
2318+
die("unable to write sha1 file");
2319+
stream.next_out = compressed;
2320+
stream.avail_out = sizeof(compressed);
2321+
} while (ret == Z_OK);
2322+
23212323
if (ret != Z_STREAM_END)
23222324
die("unable to deflate new object %s (%d)", sha1_to_hex(sha1), ret);
2323-
23242325
ret = deflateEnd(&stream);
23252326
if (ret != Z_OK)
23262327
die("deflateEnd on object %s failed (%d)", sha1_to_hex(sha1), ret);
23272328

2328-
size = stream.total_out;
2329-
2330-
if (write_buffer(fd, compressed, size) < 0)
2331-
die("unable to write sha1 file");
23322329
close_sha1_file(fd);
2333-
free(compressed);
23342330

23352331
if (mtime) {
23362332
struct utimbuf utb;

0 commit comments

Comments
 (0)