Skip to content

Commit

Permalink
pack-objects: avoid delta chains that are too long.
Browse files Browse the repository at this point in the history
This tries to rework the solution for the excess delta chain
problem. An earlier commit worked it around ``cheaply'', but
repeated repacking risks unbound growth of delta chains.

This version counts the length of delta chain we are reusing
from the existing pack, and makes sure a base object that has
sufficiently long delta chain does not get deltified.

Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Junio C Hamano committed Feb 22, 2006
1 parent 4181bda commit 15b4d57
Showing 1 changed file with 35 additions and 8 deletions.
43 changes: 35 additions & 8 deletions pack-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,22 @@ static const char pack_usage[] = "git-pack-objects [-q] [--no-reuse-delta] [--no
struct object_entry {
unsigned char sha1[20];
unsigned long size; /* uncompressed size */
unsigned long offset; /* offset into the final pack file (nonzero if already written) */
unsigned long offset; /* offset into the final pack file;
* nonzero if already written.
*/
unsigned int depth; /* delta depth */
unsigned int delta_limit; /* base adjustment for in-pack delta */
unsigned int hash; /* name hint hash */
enum object_type type;
unsigned char edge; /* reused delta chain points at this entry. */
enum object_type in_pack_type; /* could be delta */
unsigned long delta_size; /* delta data size (uncompressed) */
struct object_entry *delta; /* delta base object */
struct packed_git *in_pack; /* already in pack */
unsigned int in_pack_offset;
struct object_entry *delta_child; /* delitified objects who bases me */
struct object_entry *delta_sibling; /* other deltified objects who
* uses the same base as me
*/
};

/*
Expand Down Expand Up @@ -470,7 +476,8 @@ static void check_object(struct object_entry *entry)
entry->delta = base_entry;
entry->type = OBJ_DELTA;

base_entry->edge = 1;
entry->delta_sibling = base_entry->delta_child;
base_entry->delta_child = entry;

return;
}
Expand Down Expand Up @@ -513,15 +520,32 @@ static void hash_objects(void)
}
}

static unsigned int check_delta_limit(struct object_entry *me, unsigned int n)
{
struct object_entry *child = me->delta_child;
unsigned int m = n;
while (child) {
unsigned int c = check_delta_limit(child, n + 1);
if (m < c)
m = c;
child = child->delta_sibling;
}
return m;
}

static void get_object_details(void)
{
int i;
struct object_entry *entry = objects;
struct object_entry *entry;

hash_objects();
prepare_pack_ix();
for (i = 0; i < nr_objects; i++)
check_object(entry++);
for (i = 0, entry = objects; i < nr_objects; i++, entry++)
check_object(entry);
for (i = 0, entry = objects; i < nr_objects; i++, entry++)
if (!entry->delta && entry->delta_child)
entry->delta_limit =
check_delta_limit(entry, 1);
}

typedef int (*entry_sort_t)(const struct object_entry *, const struct object_entry *);
Expand Down Expand Up @@ -598,8 +622,11 @@ static int try_delta(struct unpacked *cur, struct unpacked *old, unsigned max_de
* that depend on the current object into account -- otherwise
* they would become too deep.
*/
if (cur_entry->edge)
max_depth /= 4;
if (cur_entry->delta_child) {
if (max_depth <= cur_entry->delta_limit)
return 0;
max_depth -= cur_entry->delta_limit;
}

size = cur_entry->size;
if (size < 50)
Expand Down

0 comments on commit 15b4d57

Please sign in to comment.