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

[PATCH] fetch: avoid repeated commits in mark_complete

From
Jeff King <peff@peff.net>
Date
May 19, 2011, 20:48 UTC
Message-ID
<20110519204851.GA28574@sigill.intra.peff.net>

We add every local ref to a list so that we can mark them and all of their ancestors back to a certain cutoff point. However, if some refs point to the same commit, we will end up adding them to the list many times.

Furthermore, since commit_lists are stored as linked lists, we must do an O(n) traversal of the list in order to find the right place to insert each commit. This makes building the list O(n^2) in the number of refs.

For normal repositories, this isn't a big deal. We have a few hundreds refs at most, and most of them are unique. But consider an "alternates" repo that serves as an object database for many other similar repos. For reachability, it needs to keep a copy of the refs in each child repo. This means it may have a large number of refs, many of which point to the same commits.

By noting commits we have already added to the list, we can shrink the size of "n" in such a repo to the number of unique commits, which is on the order of what a normal repo would contain (it's actually more than a normal repo, since child repos may have branches at different states, but in practice it tends to be much smaller than the list with duplicates).

Here are the results on one particular giant repo (containing objects for all Rails forks on GitHub):

  $ git for-each-ref | wc -l
  112514
  [before]
  $ 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
  $ git fetch --no-tags ../remote.git
  6.15user 0.08system 0:06.25elapsed 99%CPU (0avgtext+0avgdata 123856maxresident)k
  0inputs+40outputs (0major+18872minor)pagefaults 0swaps
Signed-off-by: Jeff King <peff@peff.net>
---
 builtin/fetch-pack.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index 85aff02..56c0b4a 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -472,8 +472,10 @@ 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);
+		if (!(commit->object.flags & COMPLETE)) {
+			commit->object.flags |= COMPLETE;
+			commit_list_insert_by_date(commit, &complete);
+		}
 	}
 	return 0;
 }
-- 
1.7.5.8.ga95ab
Next: Jeff King
Message 1 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.