summaryrefslogtreecommitdiff
path: root/sha1_file.c
diff options
context:
space:
mode:
authorShawn O. Pearce <spearce@spearce.org>2007-03-19 01:14:37 -0400
committerJunio C Hamano <junkio@cox.net>2007-03-18 22:43:37 -0700
commit18bdec1118df92649b70ce126aff2f147deecad5 (patch)
treeb4b4221974d0f4f48b32c3168365807e652caf5e /sha1_file.c
parent3635a187704ed30b32eb11f5098496e5e435a19d (diff)
downloadgit-18bdec1118df92649b70ce126aff2f147deecad5.tar.gz
Limit the size of the new delta_base_cache
The new configuration variable core.deltaBaseCacheLimit allows the user to control how much memory they are willing to give to Git for caching base objects of deltas. This is not normally meant to be a user tweakable knob; the "out of the box" settings are meant to be suitable for almost all workloads. We default to 16 MiB under the assumption that the cache is not meant to consume all of the user's available memory, and that the cache's main purpose was to cache trees, for faster path limiters during revision traversal. Since trees tend to be relatively small objects, this relatively small limit should still allow a large number of objects. On the other hand we don't want the cache to start storing 200 different versions of a 200 MiB blob, as this could easily blow the entire address space of a 32 bit process. We evict OBJ_BLOB from the cache first (credit goes to Junio) as we want to favor OBJ_TREE within the cache. These are the objects that have the highest inflate() startup penalty, as they tend to be small and thus don't have that much of a chance to ammortize that penalty over the entire data. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'sha1_file.c')
-rw-r--r--sha1_file.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/sha1_file.c b/sha1_file.c
index ee64865b60..b0b21776e7 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1354,6 +1354,7 @@ static void *unpack_compressed_entry(struct packed_git *p,
#define MAX_DELTA_CACHE (256)
+static size_t delta_base_cached;
static struct delta_base_cache_entry {
struct packed_git *p;
off_t base_offset;
@@ -1384,8 +1385,10 @@ static void *cache_or_unpack_entry(struct packed_git *p, off_t base_offset,
return unpack_entry(p, base_offset, type, base_size);
found_cache_entry:
- if (!keep_cache)
+ if (!keep_cache) {
ent->data = NULL;
+ delta_base_cached -= ent->size;
+ }
else {
ret = xmalloc(ent->size + 1);
memcpy(ret, ent->data, ent->size);
@@ -1396,14 +1399,33 @@ found_cache_entry:
return ret;
}
+static inline void release_delta_base_cache(struct delta_base_cache_entry *ent)
+{
+ if (ent->data) {
+ free(ent->data);
+ ent->data = NULL;
+ delta_base_cached -= ent->size;
+ }
+}
+
static void add_delta_base_cache(struct packed_git *p, off_t base_offset,
void *base, unsigned long base_size, enum object_type type)
{
- unsigned long hash = pack_entry_hash(p, base_offset);
+ unsigned long i, hash = pack_entry_hash(p, base_offset);
struct delta_base_cache_entry *ent = delta_base_cache + hash;
- if (ent->data)
- free(ent->data);
+ release_delta_base_cache(ent);
+ delta_base_cached += base_size;
+ for (i = 0; delta_base_cached > delta_base_cache_limit
+ && i < ARRAY_SIZE(delta_base_cache); i++) {
+ struct delta_base_cache_entry *f = delta_base_cache + i;
+ if (f->type == OBJ_BLOB)
+ release_delta_base_cache(f);
+ }
+ for (i = 0; delta_base_cached > delta_base_cache_limit
+ && i < ARRAY_SIZE(delta_base_cache); i++)
+ release_delta_base_cache(delta_base_cache + i);
+
ent->p = p;
ent->base_offset = base_offset;
ent->type = type;