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

[PATCH 1/2] pack-objects: break out of want_object loop early

From
Jeff King <peff@peff.net>
Date
Jul 25, 2016, 18:50 UTC
Message-ID
<20160725185010.GA12974@sigill.intra.peff.net>
In-Reply-To
<20160725184938.GA12871@sigill.intra.peff.net>

When pack-objects collects the list of objects to pack (either from stdin, or via its internal rev-list), it filters each one through want_object_in_pack().

This function loops through each existing packfile, looking for the object. When we find it, we mark the pack/offset combo for later use. However, we can't just return "yes, we want it" at that point. If --honor-pack-keep is in effect, we must keep looking to find it in _all_ packs, to make sure none of them has a .keep. Likewise, if --local is in effect, we must make sure it is not present in any local pack.

As a result, the sum effort of these calls is effectively O(nr_objects * nr_packs). In an ordinary repository, we have only a handful of packs, and this doesn't make a big difference. But in pathological cases, it can slow the counting phase to a crawl.

This patch notices the case that we have neither "--local" nor "--honor-pack-keep" in effect and breaks out of the loop early, after finding the first instance. Note that our worst case is still "objects * packs" (i.e., we might find each object in the last pack we look in), but in practice we will often break out early. On an "average" repo, my git.git with 8 packs, this shows a modest 2% (a few dozen milliseconds) improvement in the counting-objects phase of "git pack-objects --all <foo" (hackily instrumented by sticking exit(0) right after list_objects).

But in a much more pathological case, it makes a bigger difference. I ran the same command on a real-world example with ~9 million objects across 1300 packs. The counting time dropped from 413s to 45s, an improvement of about 89%.

Note that this patch won't do anything by itself for a normal "git gc", as it uses both --honor-pack-keep and --local.

Signed-off-by: Jeff King <peff@peff.net>
---
 builtin/pack-objects.c | 2 ++
 1 file changed, 2 insertions(+)
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index a2f8cfd..55ef5a8 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -981,6 +981,8 @@ static int want_object_in_pack(const unsigned char *sha1,
 				return 0;
 			if (ignore_packed_keep && p->pack_local && p->pack_keep)
 				return 0;
+			if (!ignore_packed_keep && !local)
+				break;
 		}
 	}
 
-- 
2.9.2.512.g8a06708
Previous: Jeff KingNext: Junio C Hamano
Message 2 of 13 in “speed up "Counting objects" when there are many packs”
  1. 0/2 speed up "Counting objects" when there are many packsJeff King, Jul 25, 2016
  2. 1/2 pack-objects: break out of want_object loop earlyJeff King, Jul 25, 2016
  3. Junio C HamanoJul 25, 2016
  4. Jeff KingJul 25, 2016
  5. Junio C HamanoJul 25, 2016
  6. Jeff KingJul 25, 2016
  7. Junio C HamanoJul 26, 2016
  8. Jeff KingJul 26, 2016
  9. Junio C HamanoJul 26, 2016
  10. Jeff KingJul 27, 2016
  11. Junio C HamanoJul 27, 2016
  12. Jeff KingJul 27, 2016
  13. 2/2 pack-objects: compute local/ignore_pack_keep earlyJeff King, Jul 25, 2016

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.