summaryrefslogtreecommitdiff
path: root/file
diff options
context:
space:
mode:
authorWerner Almesberger <werner@almesberger.net>2016-10-29 02:00:06 (GMT)
committerWerner Almesberger <werner@almesberger.net>2016-10-29 02:00:06 (GMT)
commit11dce68a9b3684cbaaa9aff0a18e62bbe7e2f2e0 (patch)
tree805eaed1ea52ba653d1f0a1854289355568ac588 /file
parent60294e0b0f547160c592a13e7095607cd529433a (diff)
downloadeeshow-11dce68a9b3684cbaaa9aff0a18e62bbe7e2f2e0.zip
eeshow-11dce68a9b3684cbaaa9aff0a18e62bbe7e2f2e0.tar.gz
eeshow-11dce68a9b3684cbaaa9aff0a18e62bbe7e2f2e0.tar.bz2
file/git-file.c: add cache for remembering commits we've already visited
This brings the time for eeplot -d "%s" HEAD:neo900.pro -o neo900.pdf down from 100 s to about 1.2 s, only slightly longer than the 0.75 s plotting takes without date processing.
Diffstat (limited to 'file')
-rw-r--r--file/git-file.c55
1 files changed, 49 insertions, 6 deletions
diff --git a/file/git-file.c b/file/git-file.c
index 1593115..24c90fb 100644
--- a/file/git-file.c
+++ b/file/git-file.c
@@ -483,6 +483,49 @@ fail:
}
+/* ----- Hash table for avoiding redundant passes through ancestry --------- */
+
+
+#define HASH_BUCKETS 257
+
+
+static struct hash_bucket {
+ unsigned n;
+ const void **refs;
+} hash_buckets[HASH_BUCKETS];
+
+
+static void hash_init(void)
+{
+ memset(hash_buckets, 0, sizeof(hash_buckets));
+}
+
+
+static bool hash_test(const void *ref)
+{
+ unsigned h = (unsigned long) ref % HASH_BUCKETS;
+ struct hash_bucket *b = hash_buckets + h;
+ unsigned i;
+
+ for (i = 0; i != b->n; i++)
+ if (b->refs[i] == ref)
+ return 1;
+ b->refs = realloc_type_n(b->refs, const void *, b->n + 1);
+ b->refs[b->n] = ref;
+ b->n++;
+ return 0;
+}
+
+
+static void hash_free(void)
+{
+ unsigned i;
+
+ for (i = 0; i != HASH_BUCKETS; i++)
+ free((void *) hash_buckets[i].refs);
+}
+
+
/* ----- Commit time ------------------------------------------------------- */
@@ -495,10 +538,6 @@ static int search(const char *root, const git_tree_entry *entry, void *payload)
/*
- * @@@ Not very efficient. If there are branches, we will search the ancestry
- * for each branch, which could mean a lot of times. Should keep track of what
- * we we've already seen, like git-hist does.
- *
* We have to use git_tree_walk instead of git_tree_entry_byid since the latter
* doesn't recurse into sub-trees.
*/
@@ -542,7 +581,8 @@ static void recurse_time(const git_commit *commit, const git_oid *oid,
for (i = 0; i != n; i++) {
if (git_commit_parent(&parent, commit, i))
pfatal_git("git_commit_parent");
- recurse_time(parent, oid, best);
+ if (!hash_test(parent))
+ recurse_time(parent, oid, best);
}
}
@@ -566,8 +606,11 @@ time_t vcs_git_time(void *ctx)
* - cache results,
* - lazy evaluation.
*/
- if (date_override)
+ if (date_override) {
+ hash_init();
recurse_time(vcs_git->commit, oid, &t);
+ hash_free();
+ }
return t;
}