git-pickaxe: cache one already found path per commit.

Depending on how bushy the commit DAG is, this saves calls to
the internal diff-tree for fork-point commits.  For example,
annotating Makefile in the kernel repository saves about a third
of such diff-tree calls.

Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Junio C Hamano 2006-10-31 01:00:01 -08:00
parent f69e743d97
commit 0d981c67d8

View File

@ -141,6 +141,8 @@ static int cmp_suspect(struct origin *a, struct origin *b)
return strcmp(a->path, b->path); return strcmp(a->path, b->path);
} }
#define cmp_suspect(a, b) ( ((a)==(b)) ? 0 : cmp_suspect(a,b) )
static void sanity_check_refcnt(struct scoreboard *); static void sanity_check_refcnt(struct scoreboard *);
static void coalesce(struct scoreboard *sb) static void coalesce(struct scoreboard *sb)
@ -213,6 +215,12 @@ static struct origin *find_origin(struct scoreboard *sb,
struct diff_options diff_opts; struct diff_options diff_opts;
const char *paths[2]; const char *paths[2];
if (parent->util) {
struct origin *cached = parent->util;
if (!strcmp(cached->path, origin->path))
return origin_incref(cached);
}
/* See if the origin->path is different between parent /* See if the origin->path is different between parent
* and origin first. Most of the time they are the * and origin first. Most of the time they are the
* same and diff-tree is fairly efficient about this. * same and diff-tree is fairly efficient about this.
@ -259,6 +267,12 @@ static struct origin *find_origin(struct scoreboard *sb,
} }
} }
diff_flush(&diff_opts); diff_flush(&diff_opts);
if (porigin) {
origin_incref(porigin);
if (parent->util)
origin_decref(parent->util);
parent->util = porigin;
}
return porigin; return porigin;
} }
@ -905,7 +919,7 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
continue; continue;
if (parse_commit(p)) if (parse_commit(p))
continue; continue;
porigin = find(sb, parent->item, origin); porigin = find(sb, p, origin);
if (!porigin) if (!porigin)
continue; continue;
if (!hashcmp(porigin->blob_sha1, origin->blob_sha1)) { if (!hashcmp(porigin->blob_sha1, origin->blob_sha1)) {
@ -1371,8 +1385,10 @@ static void sanity_check_refcnt(struct scoreboard *sb)
ent->suspect->refcnt = -ent->suspect->refcnt; ent->suspect->refcnt = -ent->suspect->refcnt;
} }
for (ent = sb->ent; ent; ent = ent->next) { for (ent = sb->ent; ent; ent = ent->next) {
/* then pick each and see if they have the the /* then pick each and see if they have the the correct
* correct refcnt * refcnt; note that ->util caching means origin's refcnt
* may well be greater than the number of blame entries
* that use it.
*/ */
int found; int found;
struct blame_entry *e; struct blame_entry *e;
@ -1386,7 +1402,7 @@ static void sanity_check_refcnt(struct scoreboard *sb)
continue; continue;
found++; found++;
} }
if (suspect->refcnt != found) if (suspect->refcnt < found)
baa = 1; baa = 1;
} }
if (baa) { if (baa) {