Subject: Re: Git is not scalable with too many refs/*

From: René Scharfe <[email-masked]>
Date: Fri, 30 Sep 2011 11:12:08 +0200

Hi Martin,

Am 29.09.2011 22:11, schrieb Martin Fick:
> Your patch works well for me.  It achieves about the same 
> gains as Julian's patch. Thanks!

OK, and what happens if you apply the following patch on top of my first
one?  It avoids going through all the refs a second time during cleanup,
at the cost of going through the list of all known objects.  I wonder if
that's any faster in your case.

Thanks,
René

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 84e0cdc..a4b1003 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -596,15 +596,14 @@ static int add_pending_uninteresting_ref(const char *refname,
 	return 0;
 }
 
-static int clear_commit_marks_from_one_ref(const char *refname,
-				      const unsigned char *sha1,
-				      int flags,
-				      void *cb_data)
+static void clear_commit_marks_for_all(unsigned int mark)
 {
-	struct commit *commit = lookup_commit_reference_gently(sha1, 1);
-	if (commit)
-		clear_commit_marks(commit, -1);
-	return 0;
+	unsigned int i, max = get_max_object_index();
+	for (i = 0; i < max; i++) {
+		struct object *object = get_indexed_object(i);
+		if (object && object->type == OBJ_COMMIT)
+			object->flags &= ~mark;
+	}
 }
 
 static void describe_one_orphan(struct strbuf *sb, struct commit *commit)
@@ -690,8 +689,7 @@ static void orphaned_commit_warning(struct commit *commit)
 	else
 		describe_detached_head(_("Previous HEAD position was"), commit);
 
-	clear_commit_marks(commit, -1);
-	for_each_ref(clear_commit_marks_from_one_ref, NULL);
+	clear_commit_marks_for_all(ALL_REV_FLAGS);
 }
 
 static int switch_branches(struct checkout_opts *opts, struct branch_info *new)