J Junio C Hamano #
Jeff Hostetler [off-list ref] writes:
I looked at doing this, but I didn't think the complexity and overhead to forward search for peers at the current level didn't warrant the limited gains.
It seems that I wasn't clear what I meant. I didn't mean anything complex like what you said. Just something simple, like this on top of yours, that passes and compares with only the previous one. I do not know if that gives any gain, though ;-). cache.h | 2 +- name-hash.c | 11 +++++++++-- preload-index.c | 4 +++- 3 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/cache.h b/cache.h
index 390aa803df..bd2980f6e3 100644
--- a/cache.h
+++ b/cache.h@@ -233,7 +233,7 @@ struct cache_entry { #error "CE_EXTENDED_FLAGS out of range" #endif -void precompute_istate_hashes(struct cache_entry *ce); +void precompute_istate_hashes(struct cache_entry *ce, struct cache_entry *prev); /* Forward structure decls */ struct pathspec;
diff --git a/name-hash.c b/name-hash.c
index f95054f44c..5e09b79170 100644
--- a/name-hash.c
+++ b/name-hash.c@@ -300,7 +300,7 @@ void free_name_hash(struct index_state *istate) * non-skip-worktree items (since status should not observe skipped items), but * because lazy_init_name_hash() hashes everything, we force it here. */ -void precompute_istate_hashes(struct cache_entry *ce) +void precompute_istate_hashes(struct cache_entry *ce, struct cache_entry *prev) { int namelen = ce_namelen(ce);
@@ -312,7 +312,14 @@ void precompute_istate_hashes(struct cache_entry *ce) ce->precomputed_hash.root_entry = 1; } else { namelen--; - ce->precomputed_hash.dir = memihash(ce->name, namelen); + + if (prev && + prev->precomputed_hash.initialized && + namelen <= ce_namelen(prev) && + !memcmp(ce->name, prev->name, namelen)) + ce->precomputed_hash.dir = prev->precomputed_hash.dir; + else + ce->precomputed_hash.dir = memihash(ce->name, namelen); ce->precomputed_hash.name = memihash_continue( ce->precomputed_hash.dir, ce->name + namelen, ce_namelen(ce) - namelen);
diff --git a/preload-index.c b/preload-index.c
index 602737f9d0..784378ffac 100644
--- a/preload-index.c
+++ b/preload-index.c@@ -37,6 +37,7 @@ static void *preload_thread(void *_data) struct thread_data *p = _data; struct index_state *index = p->index; struct cache_entry **cep = index->cache + p->offset; + struct cache_entry *previous = NULL; struct cache_def cache = CACHE_DEF_INIT; nr = p->nr;
@@ -47,7 +48,8 @@ static void *preload_thread(void *_data) struct cache_entry *ce = *cep++; struct stat st; - precompute_istate_hashes(ce); + precompute_istate_hashes(ce, previous); + previous = ce; if (ce_stage(ce)) continue;
(I was just looking at the complexity of clear_ce_flags_1() in unpack-trees.c and how hard it has to look to find the end of the current directory and the effect that that has on the recursion and it felt like too much work for the potential gain.) Whereas remembering the previous one was basically free. Granted, it only helps us for adjacent files in the index, so it's not perfect, but gives us the best bang for the buck. Jeff