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

[PATCH 4/4] fetch-pack: use priority queue for mark_complete

From
Jeff King <peff@peff.net>
Date
May 19, 2011, 21:26 UTC
Message-ID
<20110519212657.GD29584@sigill.intra.peff.net>
In-Reply-To
<20110519212349.GA28589@sigill.intra.peff.net>

The regular commit_list has quadratic insertion complexity. Fetch-pack will insert an item for each ref we have. For a "normal" number of refs, this is not a big deal, but it is quite inefficient when you have tens or hundreds of thousands of refs.

Instead, let's use a priority queue with better insertion performance. For example, timings from one repo (which stores alternates for all of the Rails forks at GitHub, with mirrored refs from each individual repo to manage object pruning):

  $ git for-each-ref | wc -l
  112514
  [before]
  $ time git fetch --no-tags ../remote.git
  63.52user 0.12system 1:03.68elapsed 99%CPU (0avgtext+0avgdata 137648maxresident)k
  1856inputs+48outputs (11major+19603minor)pagefaults 0swaps
  [after]
  $ time git fetch --no-tags ../remote.git
  6.20user 0.03system 0:06.25elapsed 99%CPU (0avgtext+0avgdata 123712maxresident)k
  0inputs+40outputs (0major+18885minor)pagefaults 0swaps
Signed-off-by: Jeff King <peff@peff.net>
---
So this is the big performance-win patch. But if you didn't read my
other "fetch: avoid repeated commits in mark_complete", go do that. It's
a much simpler solution that yields the same speedup in practice.
 builtin/fetch-pack.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index 85aff02..9a951f3 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -457,7 +457,7 @@ done:
 	return count ? retval : 0;
 }
 
-static struct commit_list *complete;
+static struct queue complete = COMMIT_QUEUE_INIT;
 
 static int mark_complete(const char *path, const unsigned char *sha1, int flag, void *cb_data)
 {
@@ -473,18 +473,19 @@ static int mark_complete(const char *path, const unsigned char *sha1, int flag,
 	if (o && o->type == OBJ_COMMIT) {
 		struct commit *commit = (struct commit *)o;
 		commit->object.flags |= COMPLETE;
-		commit_list_insert_by_date(commit, &complete);
+		queue_insert(&complete, commit);
 	}
 	return 0;
 }
 
 static void mark_recent_complete_commits(unsigned long cutoff)
 {
-	while (complete && cutoff <= complete->item->date) {
+	struct commit *c;
+	while ((c = queue_peek(&complete)) && cutoff <= c->date) {
 		if (args.verbose)
 			fprintf(stderr, "Marking %s as complete\n",
-				sha1_to_hex(complete->item->object.sha1));
-		pop_most_recent_commit(&complete, COMPLETE);
+				sha1_to_hex(c->object.sha1));
+		pop_commit_from_queue(&complete, COMPLETE);
 	}
 }
 
-- 
1.7.5.8.ga95ab
Previous: Jeff KingNext: Junio C Hamano
Message 10 of 12 in “fetch: avoid repeated commits in mark_complete”
  1. fetch: avoid repeated commits in mark_completeJeff King, May 19, 2011
  2. 0/4 commit lists as priority queuesJeff King, May 19, 2011
  3. 1/4 Makefile: sort TEST_PROGRAMS listJeff King, May 19, 2011
  4. 2/4 basic priority queue implementationJeff King, May 19, 2011
  5. Thiago FarinaMay 20, 2011
  6. Jeff KingMay 20, 2011
  7. Thiago FarinaMay 20, 2011
  8. Jeff KingMay 20, 2011
  9. 3/4 commit: add infrastructure for priority queues of commitsJeff King, May 19, 2011
  10. 4/4 fetch-pack: use priority queue for mark_completeJeff King, May 19, 2011
  11. Junio C HamanoMay 20, 2011
  12. Junio C HamanoMay 20, 2011

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.