git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 1/2] index-pack: smarter memory usage when resolving deltas

From
Nicolas Pitre <nico@fluxnic.net>
Date
Apr 12, 2010, 02:57 UTC
Message-ID
<1271041047-32563-1-git-send-email-nico@fluxnic.net>

In the same spirit as commit 9892bebafe, 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 <nico@fluxnic.net>
---
 builtin/index-pack.c |   39 +++++++++++++++++++--------------------
 1 files changed, 19 insertions(+), 20 deletions(-)
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index b4cf8c5..c746d3b 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -359,34 +359,33 @@ static void *get_data_from_pack(struct object_entry *obj)
 {
 	off_t from = obj[0].idx.offset + obj[0].hdr_size;
 	unsigned long len = obj[1].idx.offset - from;
-	unsigned long rdy = 0;
-	unsigned char *src, *data;
+	unsigned char *data, inbuf[4096];
 	z_stream stream;
-	int st;
+	int status;
 
-	src = xmalloc(len);
-	data = src;
-	do {
-		ssize_t n = pread(pack_fd, data + rdy, len - rdy, from + rdy);
-		if (n < 0)
-			die_errno("cannot pread pack file");
-		if (!n)
-			die("premature end of pack file, %lu bytes missing",
-			    len - rdy);
-		rdy += n;
-	} while (rdy < len);
 	data = xmalloc(obj->size);
 	memset(&stream, 0, sizeof(stream));
+	git_inflate_init(&stream);
 	stream.next_out = data;
 	stream.avail_out = obj->size;
-	stream.next_in = src;
-	stream.avail_in = len;
-	git_inflate_init(&stream);
-	while ((st = git_inflate(&stream, Z_FINISH)) == Z_OK);
+
+	do {
+		ssize_t n = (len < sizeof(inbuf)) ? len : sizeof(inbuf);
+		n = pread(pack_fd, inbuf, n, from);
+		if (n < 0)
+			die_errno("cannot pread pack file");
+		if (!n)
+			die("premature end of pack file, %lu bytes missing", len);
+		from += n;
+		len -= n;
+		stream.next_in = inbuf;
+		stream.avail_in = n;
+		status = git_inflate(&stream, 0);
+	} while (len && status == Z_OK && !stream.avail_in);
 	git_inflate_end(&stream);
-	if (st != Z_STREAM_END || stream.total_out != obj->size)
+	/* This has been inflated OK when first encoumtered, so... */
+	if (status != Z_STREAM_END || stream.total_out != obj->size)
 		die("serious inflate inconsistency");
-	free(src);
 	return data;
 }
 
-- 
1.7.1.rc1.237.ge1730.dirty
Next: Nicolas Pitre
Message 1 of 6 in “index-pack: smarter memory usage when resolving deltas”
  1. 1/2 index-pack: smarter memory usage when resolving deltasNicolas Pitre, Apr 12, 2010
  2. 2/2 index-pack: rationalize unpack_entry_data()Nicolas Pitre, Apr 12, 2010
  3. Johannes SixtApr 12, 2010
  4. Nicolas PitreApr 12, 2010
  5. Johannes SixtApr 12, 2010
  6. Nicolas PitreApr 12, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.