use delta index data when finding best delta matches
This patch allows for computing the delta index for each base object only once and reuse it when trying to find the best delta match. This should set the mark and pave the way for possibly better delta generator algorithms. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
08abe669c0
commit
f6c7081aa9
@ -994,6 +994,7 @@ static int type_size_sort(const struct object_entry *a, const struct object_entr
|
|||||||
struct unpacked {
|
struct unpacked {
|
||||||
struct object_entry *entry;
|
struct object_entry *entry;
|
||||||
void *data;
|
void *data;
|
||||||
|
struct delta_index *index;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1004,64 +1005,56 @@ struct unpacked {
|
|||||||
* more importantly, the bigger file is likely the more recent
|
* more importantly, the bigger file is likely the more recent
|
||||||
* one.
|
* one.
|
||||||
*/
|
*/
|
||||||
static int try_delta(struct unpacked *cur, struct unpacked *old, unsigned max_depth)
|
static int try_delta(struct unpacked *trg, struct unpacked *src,
|
||||||
|
struct delta_index *src_index, unsigned max_depth)
|
||||||
{
|
{
|
||||||
struct object_entry *cur_entry = cur->entry;
|
struct object_entry *trg_entry = trg->entry;
|
||||||
struct object_entry *old_entry = old->entry;
|
struct object_entry *src_entry = src->entry;
|
||||||
unsigned long size, oldsize, delta_size, sizediff;
|
unsigned long size, src_size, delta_size, sizediff, max_size;
|
||||||
long max_size;
|
|
||||||
void *delta_buf;
|
void *delta_buf;
|
||||||
|
|
||||||
/* Don't bother doing diffs between different types */
|
/* Don't bother doing diffs between different types */
|
||||||
if (cur_entry->type != old_entry->type)
|
if (trg_entry->type != src_entry->type)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* We do not compute delta to *create* objects we are not
|
/* We do not compute delta to *create* objects we are not
|
||||||
* going to pack.
|
* going to pack.
|
||||||
*/
|
*/
|
||||||
if (cur_entry->preferred_base)
|
if (trg_entry->preferred_base)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* If the current object is at pack edge, take the depth the
|
/*
|
||||||
|
* If the current object is at pack edge, take the depth the
|
||||||
* objects that depend on the current object into account --
|
* objects that depend on the current object into account --
|
||||||
* otherwise they would become too deep.
|
* otherwise they would become too deep.
|
||||||
*/
|
*/
|
||||||
if (cur_entry->delta_child) {
|
if (trg_entry->delta_child) {
|
||||||
if (max_depth <= cur_entry->delta_limit)
|
if (max_depth <= trg_entry->delta_limit)
|
||||||
return 0;
|
return 0;
|
||||||
max_depth -= cur_entry->delta_limit;
|
max_depth -= trg_entry->delta_limit;
|
||||||
}
|
}
|
||||||
|
if (src_entry->depth >= max_depth)
|
||||||
size = cur_entry->size;
|
|
||||||
oldsize = old_entry->size;
|
|
||||||
sizediff = oldsize > size ? oldsize - size : size - oldsize;
|
|
||||||
|
|
||||||
if (size < 50)
|
|
||||||
return -1;
|
|
||||||
if (old_entry->depth >= max_depth)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/* Now some size filtering euristics. */
|
||||||
* NOTE!
|
size = trg_entry->size;
|
||||||
*
|
|
||||||
* We always delta from the bigger to the smaller, since that's
|
|
||||||
* more space-efficient (deletes don't have to say _what_ they
|
|
||||||
* delete).
|
|
||||||
*/
|
|
||||||
max_size = size / 2 - 20;
|
max_size = size / 2 - 20;
|
||||||
if (cur_entry->delta)
|
if (trg_entry->delta)
|
||||||
max_size = cur_entry->delta_size-1;
|
max_size = trg_entry->delta_size-1;
|
||||||
|
src_size = src_entry->size;
|
||||||
|
sizediff = src_size < size ? size - src_size : 0;
|
||||||
if (sizediff >= max_size)
|
if (sizediff >= max_size)
|
||||||
return 0;
|
return 0;
|
||||||
delta_buf = diff_delta(old->data, oldsize,
|
|
||||||
cur->data, size, &delta_size, max_size);
|
delta_buf = create_delta(src_index, trg->data, size, &delta_size, max_size);
|
||||||
if (!delta_buf)
|
if (!delta_buf)
|
||||||
return 0;
|
return 0;
|
||||||
cur_entry->delta = old_entry;
|
|
||||||
cur_entry->delta_size = delta_size;
|
trg_entry->delta = src_entry;
|
||||||
cur_entry->depth = old_entry->depth + 1;
|
trg_entry->delta_size = delta_size;
|
||||||
|
trg_entry->depth = src_entry->depth + 1;
|
||||||
free(delta_buf);
|
free(delta_buf);
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void progress_interval(int signum)
|
static void progress_interval(int signum)
|
||||||
@ -1109,11 +1102,19 @@ static void find_deltas(struct object_entry **list, int window, int depth)
|
|||||||
*/
|
*/
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (entry->size < 50)
|
||||||
|
continue;
|
||||||
|
if (n->index)
|
||||||
|
free_delta_index(n->index);
|
||||||
free(n->data);
|
free(n->data);
|
||||||
n->entry = entry;
|
n->entry = entry;
|
||||||
n->data = read_sha1_file(entry->sha1, type, &size);
|
n->data = read_sha1_file(entry->sha1, type, &size);
|
||||||
if (size != entry->size)
|
if (size != entry->size)
|
||||||
die("object %s inconsistent object length (%lu vs %lu)", sha1_to_hex(entry->sha1), size, entry->size);
|
die("object %s inconsistent object length (%lu vs %lu)",
|
||||||
|
sha1_to_hex(entry->sha1), size, entry->size);
|
||||||
|
n->index = create_delta_index(n->data, size);
|
||||||
|
if (!n->index)
|
||||||
|
die("out of memory");
|
||||||
|
|
||||||
j = window;
|
j = window;
|
||||||
while (--j > 0) {
|
while (--j > 0) {
|
||||||
@ -1124,7 +1125,7 @@ static void find_deltas(struct object_entry **list, int window, int depth)
|
|||||||
m = array + other_idx;
|
m = array + other_idx;
|
||||||
if (!m->entry)
|
if (!m->entry)
|
||||||
break;
|
break;
|
||||||
if (try_delta(n, m, depth) < 0)
|
if (try_delta(n, m, m->index, depth) < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
@ -1144,8 +1145,11 @@ static void find_deltas(struct object_entry **list, int window, int depth)
|
|||||||
if (progress)
|
if (progress)
|
||||||
fputc('\n', stderr);
|
fputc('\n', stderr);
|
||||||
|
|
||||||
for (i = 0; i < window; ++i)
|
for (i = 0; i < window; ++i) {
|
||||||
|
if (array[i].index)
|
||||||
|
free_delta_index(array[i].index);
|
||||||
free(array[i].data);
|
free(array[i].data);
|
||||||
|
}
|
||||||
free(array);
|
free(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user