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

[PATCH v3 4/4] describe: Delay looking up commits until searching for an inexact match

From
Anders Kaseorg <andersk@ksplice.com>
Date
Dec 9, 2010, 06:47 UTC
Message-ID
<alpine.DEB.2.02.1012090146160.23348@dr-wily.mit.edu>
In-Reply-To
<alpine.DEB.2.02.1012090140390.23348@dr-wily.mit.edu>

Now that struct commit.util is not used until after we’ve checked that the argument doesn’t exactly match a tag, we can wait until then to look up the commits for each tag.

This avoids a lot of I/O on --exact-match queries in repositories with many tags. For example, ‘git describe --exact-match HEAD’ becomes about 12 times faster on a cold cache (3.2s instead of 39s) in a linux-2.6 repository with 2000 packed tags. That’s a huge win for the interactivity of the __git_ps1 shell prompt helper when on a detached HEAD.

Signed-off-by: Anders Kaseorg <andersk@ksplice.com>
---
Change from v2: Process the entire hash chain in set_util().
 builtin/describe.c |   37 ++++++++++++++++++++++---------------
 1 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/builtin/describe.c b/builtin/describe.c
index 8149233..a0f52c1 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -24,6 +24,7 @@ static int longformat;
 static int abbrev = DEFAULT_ABBREV;
 static int max_candidates = 10;
 static struct hash_table names;
+static int have_util;
 static const char *pattern;
 static int always;
 static const char *dirty;
@@ -62,6 +63,17 @@ static inline struct commit_name *find_commit_name(const unsigned char *peeled)
 	return n;
 }
 
+static int set_util(void *chain)
+{
+	struct commit_name *n;
+	for (n = chain; n; n = n->next) {
+		struct commit *c = lookup_commit_reference_gently(n->peeled, 1);
+		if (c)
+			c->util = n;
+	}
+	return 0;
+}
+
 static int replace_name(struct commit_name *e,
 			       int prio,
 			       const unsigned char *sha1,
@@ -96,18 +108,16 @@ static int replace_name(struct commit_name *e,
 }
 
 static void add_to_known_names(const char *path,
-			       struct commit *commit,
+			       const unsigned char *peeled,
 			       int prio,
 			       const unsigned char *sha1)
 {
-	const unsigned char *peeled = commit->object.sha1;
 	struct commit_name *e = find_commit_name(peeled);
 	struct tag *tag = NULL;
 	if (replace_name(e, prio, sha1, &tag)) {
 		if (!e) {
 			void **pos;
 			e = xmalloc(sizeof(struct commit_name));
-			commit->util = e;
 			hashcpy(e->peeled, peeled);
 			pos = insert_hash(hash_sha1(peeled), e, &names);
 			if (pos) {
@@ -128,8 +138,6 @@ static void add_to_known_names(const char *path,
 static int get_name(const char *path, const unsigned char *sha1, int flag, void *cb_data)
 {
 	int might_be_tag = !prefixcmp(path, "refs/tags/");
-	struct commit *commit;
-	struct object *object;
 	unsigned char peeled[20];
 	int is_tag, prio;
 
@@ -137,16 +145,10 @@ static int get_name(const char *path, const unsigned char *sha1, int flag, void
 		return 0;
 
 	if (!peel_ref(path, peeled) && !is_null_sha1(peeled)) {
-		commit = lookup_commit_reference_gently(peeled, 1);
-		if (!commit)
-			return 0;
-		is_tag = !!hashcmp(sha1, commit->object.sha1);
+		is_tag = !!hashcmp(sha1, peeled);
 	} else {
-		commit = lookup_commit_reference_gently(sha1, 1);
-		object = parse_object(sha1);
-		if (!commit || !object)
-			return 0;
-		is_tag = object->type == OBJ_TAG;
+		hashcpy(peeled, sha1);
+		is_tag = 0;
 	}
 
 	/* If --all, then any refs are used.
@@ -169,7 +171,7 @@ static int get_name(const char *path, const unsigned char *sha1, int flag, void
 		if (!prio)
 			return 0;
 	}
-	add_to_known_names(all ? path + 5 : path + 10, commit, prio, sha1);
+	add_to_known_names(all ? path + 5 : path + 10, peeled, prio, sha1);
 	return 0;
 }
 
@@ -286,6 +288,11 @@ static void describe(const char *arg, int last_one)
 	if (debug)
 		fprintf(stderr, "searching to describe %s\n", arg);
 
+	if (!have_util) {
+		for_each_hash(&names, set_util);
+		have_util = 1;
+	}
+
 	list = NULL;
 	cmit->object.flags = SEEN;
 	commit_list_insert(cmit, &list);
-- 
1.7.3.3
Previous: Anders Kaseorg
Message 28 of 28 in “describe: Don’t look up commits with --exact-match”
  1. describe: Don’t look up commits with --exact-matchAnders Kaseorg, Nov 17, 2010
  2. Jonathan NiederDec 3, 2010
  3. Anders KaseorgDec 6, 2010
  4. describe: Don’t look up commits with --exact-matchAnders Kaseorg, Dec 6, 2010
  5. Jonathan NiederDec 6, 2010
  6. Thomas RastDec 6, 2010
  7. Anders KaseorgDec 6, 2010
  8. Jonathan NiederDec 6, 2010
  9. SZEDER GáborDec 7, 2010
  10. 1/2 describe: Use for_each_rawrefAnders Kaseorg, Dec 7, 2010
  11. 2/2 describe: Don’t look up commits with --exact-matchAnders Kaseorg, Dec 7, 2010
  12. Anders KaseorgDec 7, 2010
  13. Junio C HamanoDec 7, 2010
  14. Junio C HamanoDec 7, 2010
  15. Junio C HamanoDec 7, 2010
  16. Anders KaseorgDec 8, 2010
  17. 1/4 describe: Use for_each_rawrefAnders Kaseorg, Dec 8, 2010
  18. 2/4 describe: Don’t use a flex array in struct commit_nameAnders Kaseorg, Dec 8, 2010
  19. 3/4 describe: Store commit_names in a hash table by commit SHA1Anders Kaseorg, Dec 8, 2010
  20. 3/4 describe: Store commit_names in a hash table by commit SHA1Anders Kaseorg, Dec 8, 2010
  21. Junio C HamanoDec 8, 2010
  22. 4/4 describe: Delay looking up commits until searching for an inexact matchAnders Kaseorg, Dec 8, 2010
  23. Junio C HamanoDec 8, 2010
  24. Anders KaseorgDec 8, 2010
  25. 1/4 describe: Use for_each_rawrefAnders Kaseorg, Dec 9, 2010
  26. 2/4 describe: Don’t use a flex array in struct commit_nameAnders Kaseorg, Dec 9, 2010
  27. 3/4 describe: Store commit_names in a hash table by commit SHA1Anders Kaseorg, Dec 9, 2010
  28. 4/4 describe: Delay looking up commits until searching for an inexact matchAnders Kaseorg, Dec 9, 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.