diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2007-03-17 12:44:06 -0700 |
---|---|---|
committer | Junio C Hamano <junkio@cox.net> | 2007-03-18 15:36:59 -0700 |
commit | e5e01619bcb753a3c45fb51d498371c9ff0677da (patch) | |
tree | dbbbd964daa3b318fa304f5b3b7f7bb0e5370763 /sha1_file.c | |
parent | Make trivial wrapper functions around delta base generation and freeing (diff) | |
download | tgif-e5e01619bcb753a3c45fb51d498371c9ff0677da.tar.xz |
Implement a simple delta_base cache
This trivial 256-entry delta_base cache improves performance for some
loads by a factor of 2.5 or so.
Instead of always re-generating the delta bases (possibly over and over
and over again), just cache the last few ones. They often can get re-used.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'sha1_file.c')
-rw-r--r-- | sha1_file.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/sha1_file.c b/sha1_file.c index f11ca3fbac..a7e3a2a9f9 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1352,16 +1352,57 @@ static void *unpack_compressed_entry(struct packed_git *p, return buffer; } +#define MAX_DELTA_CACHE (256) + +static struct delta_base_cache_entry { + struct packed_git *p; + off_t base_offset; + unsigned long size; + void *data; + enum object_type type; +} delta_base_cache[MAX_DELTA_CACHE]; + +static unsigned long pack_entry_hash(struct packed_git *p, off_t base_offset) +{ + unsigned long hash; + + hash = (unsigned long)p + (unsigned long)base_offset; + hash += (hash >> 8) + (hash >> 16); + return hash & 0xff; +} + static void *cache_or_unpack_entry(struct packed_git *p, off_t base_offset, unsigned long *base_size, enum object_type *type) { + void *ret; + unsigned long hash = pack_entry_hash(p, base_offset); + struct delta_base_cache_entry *ent = delta_base_cache + hash; + + ret = ent->data; + if (ret && ent->p == p && ent->base_offset == base_offset) + goto found_cache_entry; return unpack_entry(p, base_offset, type, base_size); + +found_cache_entry: + ent->data = NULL; + *type = ent->type; + *base_size = ent->size; + return ret; } static void add_delta_base_cache(struct packed_git *p, off_t base_offset, void *base, unsigned long base_size, enum object_type type) { - free(base); + unsigned long hash = pack_entry_hash(p, base_offset); + struct delta_base_cache_entry *ent = delta_base_cache + hash; + + if (ent->data) + free(ent->data); + ent->p = p; + ent->base_offset = base_offset; + ent->type = type; + ent->data = base; + ent->size = base_size; } static void *unpack_delta_entry(struct packed_git *p, |