Skip to content

Commit

Permalink
Add a "max_size" parameter to diff_delta()
Browse files Browse the repository at this point in the history
Anything that generates a delta to see if two objects are close usually
isn't interested in the delta ends up being bigger than some specified
size, and this allows us to stop delta generation early when that
happens.
  • Loading branch information
Linus Torvalds committed Jun 26, 2005
1 parent 78817c1 commit 75c42d8
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 17 deletions.
2 changes: 1 addition & 1 deletion delta.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
/* handling of delta buffers */
extern void *diff_delta(void *from_buf, unsigned long from_size,
void *to_buf, unsigned long to_size,
unsigned long *delta_size);
unsigned long *delta_size, unsigned long max_size);
extern void *patch_delta(void *src_buf, unsigned long src_size,
void *delta_buf, unsigned long delta_size,
unsigned long *dst_size);
Expand Down
8 changes: 7 additions & 1 deletion diff-delta.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ static void delta_cleanup(bdfile_t *bdf)

void *diff_delta(void *from_buf, unsigned long from_size,
void *to_buf, unsigned long to_size,
unsigned long *delta_size)
unsigned long *delta_size,
unsigned long max_size)
{
int i, outpos, outsize, inscnt, csize, msize, moff;
unsigned int fp;
Expand Down Expand Up @@ -312,6 +313,11 @@ void *diff_delta(void *from_buf, unsigned long from_size,
}

/* next time around the largest possible output is 1 + 4 + 3 */
if (max_size && outpos > max_size) {
free(out);
delta_cleanup(&bdf);
return NULL;
}
if (outpos > outsize - 8) {
void *tmp = out;
outsize = outsize * 3 / 2;
Expand Down
2 changes: 1 addition & 1 deletion diffcore-break.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ static int should_break(struct diff_filespec *src,

delta = diff_delta(src->data, src->size,
dst->data, dst->size,
&delta_size);
&delta_size, ~0UL);

/* Estimate the edit size by interpreting delta. */
if (count_delta(delta, delta_size,
Expand Down
2 changes: 1 addition & 1 deletion diffcore-rename.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ static int estimate_similarity(struct diff_filespec *src,

delta = diff_delta(src->data, src->size,
dst->data, dst->size,
&delta_size);
&delta_size, ~0UL);

/* A delta that has a lot of literal additions would have
* big delta_size no matter what else it does.
Expand Down
3 changes: 2 additions & 1 deletion mkdelta.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,8 @@ int main(int argc, char **argv)
continue;
}
delta_buf = diff_delta(ref[r].buf, ref[r].size,
trg.buf, trg.size, &delta_size);
trg.buf, trg.size,
&delta_size, ~0UL);
if (!delta_buf)
die("out of memory");
if (trg.depth < max_depth &&
Expand Down
22 changes: 12 additions & 10 deletions pack-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ static void *delta_against(void *buf, unsigned long size, struct object_entry *e

if (!otherbuf)
die("unable to read %s", sha1_to_hex(entry->delta->sha1));
delta_buf = diff_delta(buf, size, otherbuf, othersize, &delta_size);
if (delta_size != entry->delta_size)
delta_buf = diff_delta(buf, size, otherbuf, othersize, &delta_size, ~0UL);
if (!delta_buf || delta_size != entry->delta_size)
die("delta size changed");
free(buf);
free(otherbuf);
Expand Down Expand Up @@ -292,6 +292,7 @@ static int try_delta(struct unpacked *cur, struct unpacked *old)
struct object_entry *cur_entry = cur->entry;
struct object_entry *old_entry = old->entry;
unsigned long size, oldsize, delta_size;
long max_size;
void *delta_buf;

/* Don't bother doing diffs between different types */
Expand All @@ -300,6 +301,8 @@ static int try_delta(struct unpacked *cur, struct unpacked *old)

/* Size is guaranteed to be larger than or equal to oldsize */
size = cur_entry->size;
if (size < 50)
return -1;
oldsize = old_entry->size;
if (size - oldsize > oldsize / 4)
return -1;
Expand All @@ -311,15 +314,14 @@ static int try_delta(struct unpacked *cur, struct unpacked *old)
* more space-efficient (deletes don't have to say _what_ they
* delete).
*/
delta_buf = diff_delta(cur->data, size, old->data, oldsize, &delta_size);
max_size = size / 2 - 20;
if (cur_entry->delta)
max_size = cur_entry->delta_size-1;
delta_buf = diff_delta(cur->data, size, old->data, oldsize, &delta_size, max_size);
if (!delta_buf)
die("unable to create delta");
if (delta_size + 20 < size / 2) {
if (!cur_entry->delta || cur_entry->delta_size > delta_size) {
cur_entry->delta = old_entry;
cur_entry->delta_size = delta_size;
}
}
return 0;
cur_entry->delta = old_entry;
cur_entry->delta_size = delta_size;
free(delta_buf);
return 0;
}
Expand Down
6 changes: 4 additions & 2 deletions test-delta.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,12 @@ int main(int argc, char *argv[])

if (argv[1][1] == 'd')
out_buf = diff_delta(from_buf, from_size,
data_buf, data_size, &out_size);
data_buf, data_size,
&out_size, ~0UL);
else
out_buf = patch_delta(from_buf, from_size,
data_buf, data_size, &out_size);
data_buf, data_size,
&out_size);
if (!out_buf) {
fprintf(stderr, "delta operation failed (returned NULL)\n");
return 1;
Expand Down

0 comments on commit 75c42d8

Please sign in to comment.