Skip to content

Commit

Permalink
Add pack-objects window memory usage limit
Browse files Browse the repository at this point in the history
This adds an option (--window-memory=N) and configuration variable
(pack.windowMemory = N) to limit the memory size of the pack-objects
delta search window.  This works by removing the oldest unpacked objects
whenever the total size goes above the limit.  It will always leave
at least one object, though, so as not to completely eliminate the
possibility of computing deltas.

This is an extra limit on top of the normal window size (--window=N);
the window will not dynamically grow above the fixed number of entries
specified to fill the memory limit.

With this, repacking a repository with a mix of large and small objects
is possible even with a very large window.

Cleaner and correct circular buffer handling courtesy of Nicolas Pitre.

Signed-off-by: Brian Downing <bdowning@lavos.net>
Acked-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Brian Downing authored and Junio C Hamano committed Jul 12, 2007
1 parent 0b87b6e commit a97773c
Showing 1 changed file with 44 additions and 8 deletions.
52 changes: 44 additions & 8 deletions builtin-pack-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
#include "progress.h"

static const char pack_usage[] = "\
git-pack-objects [{ -q | --progress | --all-progress }] [--max-pack-size=N] \n\
[--local] [--incremental] [--window=N] [--depth=N] \n\
git-pack-objects [{ -q | --progress | --all-progress }] \n\
[--max-pack-size=N] [--local] [--incremental] \n\
[--window=N] [--window-memory=N] [--depth=N] \n\
[--no-reuse-delta] [--no-reuse-object] [--delta-base-offset] \n\
[--non-empty] [--revs [--unpacked | --all]*] [--reflog] \n\
[--stdout | base-name] [<ref-list | <object-list]";
Expand Down Expand Up @@ -79,6 +80,9 @@ static unsigned long delta_cache_size = 0;
static unsigned long max_delta_cache_size = 0;
static unsigned long cache_max_small_delta_size = 1000;

static unsigned long window_memory_usage = 0;
static unsigned long window_memory_limit = 0;

/*
* The object names in objects array are hashed with this hashtable,
* to help looking up the entry by object name.
Expand Down Expand Up @@ -1357,12 +1361,14 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
if (sz != trg_size)
die("object %s inconsistent object length (%lu vs %lu)",
sha1_to_hex(trg_entry->idx.sha1), sz, trg_size);
window_memory_usage += sz;
}
if (!src->data) {
src->data = read_sha1_file(src_entry->idx.sha1, &type, &sz);
if (sz != src_size)
die("object %s inconsistent object length (%lu vs %lu)",
sha1_to_hex(src_entry->idx.sha1), sz, src_size);
window_memory_usage += sz;
}
if (!src->index) {
src->index = create_delta_index(src->data, src_size);
Expand All @@ -1372,6 +1378,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
warning("suboptimal pack - out of memory");
return 0;
}
window_memory_usage += sizeof_delta_index(src->index);
}

delta_buf = create_delta(src->index, trg->data, trg_size, &delta_size, max_size);
Expand Down Expand Up @@ -1414,9 +1421,22 @@ static unsigned int check_delta_limit(struct object_entry *me, unsigned int n)
return m;
}

static void free_unpacked(struct unpacked *n)
{
window_memory_usage -= sizeof_delta_index(n->index);
free_delta_index(n->index);
n->index = NULL;
if (n->data) {
free(n->data);
n->data = NULL;
window_memory_usage -= n->entry->size;
}
n->entry = NULL;
}

static void find_deltas(struct object_entry **list, int window, int depth)
{
uint32_t i = nr_objects, idx = 0, processed = 0;
uint32_t i = nr_objects, idx = 0, count = 0, processed = 0;
unsigned int array_size = window * sizeof(struct unpacked);
struct unpacked *array;
int max_depth;
Expand Down Expand Up @@ -1451,12 +1471,17 @@ static void find_deltas(struct object_entry **list, int window, int depth)
if (entry->no_try_delta)
continue;

free_delta_index(n->index);
n->index = NULL;
free(n->data);
n->data = NULL;
free_unpacked(n);
n->entry = entry;

while (window_memory_limit &&
window_memory_usage > window_memory_limit &&
count > 1) {
uint32_t tail = (idx + window - count) % window;
free_unpacked(array + tail);
count--;
}

/*
* If the current object is at pack edge, take the depth the
* objects that depend on the current object into account
Expand Down Expand Up @@ -1491,6 +1516,8 @@ static void find_deltas(struct object_entry **list, int window, int depth)

next:
idx++;
if (count + 1 < window)
count++;
if (idx >= window)
idx = 0;
} while (i > 0);
Expand Down Expand Up @@ -1529,7 +1556,11 @@ static int git_pack_config(const char *k, const char *v)
window = git_config_int(k, v);
return 0;
}
if(!strcmp(k, "pack.depth")) {
if (!strcmp(k, "pack.windowmemory")) {
window_memory_limit = git_config_ulong(k, v);
return 0;
}
if (!strcmp(k, "pack.depth")) {
depth = git_config_int(k, v);
return 0;
}
Expand Down Expand Up @@ -1705,6 +1736,11 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
usage(pack_usage);
continue;
}
if (!prefixcmp(arg, "--window-memory=")) {
if (!git_parse_ulong(arg+16, &window_memory_limit))
usage(pack_usage);
continue;
}
if (!prefixcmp(arg, "--depth=")) {
char *end;
depth = strtoul(arg+8, &end, 0);
Expand Down

0 comments on commit a97773c

Please sign in to comment.