Re: [PATCH] describe: Don’t look up commits with --exact-match
From: Anders Kaseorg <hidden>
Date: 2016-06-15 22:50:11
Subsystem:
the rest · Maintainer:
Linus Torvalds
On Mon, 6 Dec 2010, Jonathan Nieder wrote:
Depends on what "Don't lookup commits" means, I suppose. I think the difference between _ref and _rawref is […] so if I understand correctly, for_each_ref would still allow one to get away without unpacking the objects. Is that correct?
Yeah. Okay, I see that “lookup” implies unpacking, as opposed to “find”, which doesn’t. The important part is to avoid the find, of course, because the I/O is expensive. Anyway, here’s a series with that change split out. Anders -- 8< -- From 2ad1e58b8f6e9c117c77748b6e8b85227d9d5412 Mon Sep 17 00:00:00 2001 From: Anders Kaseorg <redacted> Subject: [PATCH 1/2] describe: Use for_each_rawref Don’t waste time checking for dangling refs; they wouldn’t affect the output of ‘git describe’ anyway. Although this doesn’t gain much performance by itself, it does in conjunction with the next commit. Signed-off-by: Anders Kaseorg <redacted> --- builtin/describe.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/builtin/describe.c b/builtin/describe.c
index 43caff2..700f740 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c@@ -418,7 +418,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix) return cmd_name_rev(i + argc, args, prefix); } - for_each_ref(get_name, NULL); + for_each_rawref(get_name, NULL); if (!found_names && !always) die("No names found, cannot describe anything.");
--
1.7.3.3
From ce8a2ab9cf80247c2834d21f36f63cedb794e62f Mon Sep 17 00:00:00 2001
From: Anders Kaseorg <andersk@ksplice.com>
Subject: describe: Don’t look up commits with --exact-match
This makes ‘git describe --exact-match HEAD’ about 15 times faster on
a cold cache (2.3s instead of 35s) in a linux-2.6 repository with many
packed tags. That’s a huge win for the interactivity of the __git_ps1
shell prompt helper.
Signed-off-by: Anders Kaseorg <andersk@ksplice.com>
---
builtin/describe.c | 62 ++++++++++++++++++++++++++-------------------------
1 files changed, 32 insertions(+), 30 deletions(-)
diff --git a/builtin/describe.c b/builtin/describe.c
index 700f740..0cddef1 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -22,7 +22,7 @@ static int tags; /* Allow lightweight tags */
static int longformat;
static int abbrev = DEFAULT_ABBREV;
static int max_candidates = 10;
-static int found_names;
+static struct commit_name *names;
static const char *pattern;
static int always;
static const char *dirty;
@@ -34,6 +34,8 @@ static const char *diff_index_args[] = {
struct commit_name {
+ struct commit_name *next;
+ unsigned char peeled[20];
struct tag *tag;
unsigned prio:2; /* annotated tag = 2, tag = 1, head = 0 */
unsigned name_checked:1;
@@ -78,31 +80,26 @@ 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)
{
- struct commit_name *e = commit->util;
struct tag *tag = NULL;
- if (replace_name(e, prio, sha1, &tag)) {
- size_t len = strlen(path)+1;
- free(e);
- e = xmalloc(sizeof(struct commit_name) + len);
- e->tag = tag;
- e->prio = prio;
- e->name_checked = 0;
- hashcpy(e->sha1, sha1);
- memcpy(e->path, path, len);
- commit->util = e;
- }
- found_names = 1;
+ size_t len = strlen(path)+1;
+ struct commit_name *e = xmalloc(sizeof(struct commit_name) + len);
+ hashcpy(e->peeled, peeled);
+ e->tag = tag;
+ e->prio = prio;
+ e->name_checked = 0;
+ hashcpy(e->sha1, sha1);
+ memcpy(e->path, path, len);
+ e->next = names;
+ names = e;
}
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;
@@ -110,16 +107,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.
@@ -142,7 +133,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;
}
@@ -228,7 +219,7 @@ static void describe(const char *arg, int last_one)
unsigned char sha1[20];
struct commit *cmit, *gave_up_on = NULL;
struct commit_list *list;
- struct commit_name *n;
+ struct commit_name *n, *e;
struct possible_tag all_matches[MAX_TAGS];
unsigned int match_cnt = 0, annotated_cnt = 0, cur_match;
unsigned long seen_commits = 0;
@@ -240,7 +231,12 @@ static void describe(const char *arg, int last_one)
if (!cmit)
die("%s is not a valid '%s' object", arg, commit_type);
- n = cmit->util;
+ n = NULL;
+ for (e = names; e; e = e->next) {
+ if (!hashcmp(e->peeled, cmit->object.sha1) &&
+ replace_name(n, e->prio, e->sha1, &e->tag))
+ n = e;
+ }
if (n && (tags || all || n->prio == 2)) {
/*
* Exact match to an existing ref.
@@ -259,6 +255,12 @@ static void describe(const char *arg, int last_one)
if (debug)
fprintf(stderr, "searching to describe %s\n", arg);
+ for (e = names; e; e = e->next) {
+ struct commit *c = lookup_commit_reference_gently(e->peeled, 1);
+ if (c && replace_name(c->util, e->prio, e->sha1, &e->tag))
+ c->util = e;
+ }
+
list = NULL;
cmit->object.flags = SEEN;
commit_list_insert(cmit, &list);
@@ -419,7 +421,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
}
for_each_rawref(get_name, NULL);
- if (!found_names && !always)
+ if (!names && !always)
die("No names found, cannot describe anything.");
if (argc == 0) {
--
1.7.3.3