Skip to content

Commit 75c42d8

Browse files
author
Linus Torvalds
committed
Add a "max_size" parameter to diff_delta()
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.
1 parent 78817c1 commit 75c42d8

7 files changed

Lines changed: 28 additions & 17 deletions

File tree

delta.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/* handling of delta buffers */
55
extern void *diff_delta(void *from_buf, unsigned long from_size,
66
void *to_buf, unsigned long to_size,
7-
unsigned long *delta_size);
7+
unsigned long *delta_size, unsigned long max_size);
88
extern void *patch_delta(void *src_buf, unsigned long src_size,
99
void *delta_buf, unsigned long delta_size,
1010
unsigned long *dst_size);

diff-delta.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ static void delta_cleanup(bdfile_t *bdf)
203203

204204
void *diff_delta(void *from_buf, unsigned long from_size,
205205
void *to_buf, unsigned long to_size,
206-
unsigned long *delta_size)
206+
unsigned long *delta_size,
207+
unsigned long max_size)
207208
{
208209
int i, outpos, outsize, inscnt, csize, msize, moff;
209210
unsigned int fp;
@@ -312,6 +313,11 @@ void *diff_delta(void *from_buf, unsigned long from_size,
312313
}
313314

314315
/* next time around the largest possible output is 1 + 4 + 3 */
316+
if (max_size && outpos > max_size) {
317+
free(out);
318+
delta_cleanup(&bdf);
319+
return NULL;
320+
}
315321
if (outpos > outsize - 8) {
316322
void *tmp = out;
317323
outsize = outsize * 3 / 2;

diffcore-break.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ static int should_break(struct diff_filespec *src,
6565

6666
delta = diff_delta(src->data, src->size,
6767
dst->data, dst->size,
68-
&delta_size);
68+
&delta_size, ~0UL);
6969

7070
/* Estimate the edit size by interpreting delta. */
7171
if (count_delta(delta, delta_size,

diffcore-rename.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ static int estimate_similarity(struct diff_filespec *src,
165165

166166
delta = diff_delta(src->data, src->size,
167167
dst->data, dst->size,
168-
&delta_size);
168+
&delta_size, ~0UL);
169169

170170
/* A delta that has a lot of literal additions would have
171171
* big delta_size no matter what else it does.

mkdelta.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,8 @@ int main(int argc, char **argv)
278278
continue;
279279
}
280280
delta_buf = diff_delta(ref[r].buf, ref[r].size,
281-
trg.buf, trg.size, &delta_size);
281+
trg.buf, trg.size,
282+
&delta_size, ~0UL);
282283
if (!delta_buf)
283284
die("out of memory");
284285
if (trg.depth < max_depth &&

pack-objects.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ static void *delta_against(void *buf, unsigned long size, struct object_entry *e
8383

8484
if (!otherbuf)
8585
die("unable to read %s", sha1_to_hex(entry->delta->sha1));
86-
delta_buf = diff_delta(buf, size, otherbuf, othersize, &delta_size);
87-
if (delta_size != entry->delta_size)
86+
delta_buf = diff_delta(buf, size, otherbuf, othersize, &delta_size, ~0UL);
87+
if (!delta_buf || delta_size != entry->delta_size)
8888
die("delta size changed");
8989
free(buf);
9090
free(otherbuf);
@@ -292,6 +292,7 @@ static int try_delta(struct unpacked *cur, struct unpacked *old)
292292
struct object_entry *cur_entry = cur->entry;
293293
struct object_entry *old_entry = old->entry;
294294
unsigned long size, oldsize, delta_size;
295+
long max_size;
295296
void *delta_buf;
296297

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

301302
/* Size is guaranteed to be larger than or equal to oldsize */
302303
size = cur_entry->size;
304+
if (size < 50)
305+
return -1;
303306
oldsize = old_entry->size;
304307
if (size - oldsize > oldsize / 4)
305308
return -1;
@@ -311,15 +314,14 @@ static int try_delta(struct unpacked *cur, struct unpacked *old)
311314
* more space-efficient (deletes don't have to say _what_ they
312315
* delete).
313316
*/
314-
delta_buf = diff_delta(cur->data, size, old->data, oldsize, &delta_size);
317+
max_size = size / 2 - 20;
318+
if (cur_entry->delta)
319+
max_size = cur_entry->delta_size-1;
320+
delta_buf = diff_delta(cur->data, size, old->data, oldsize, &delta_size, max_size);
315321
if (!delta_buf)
316-
die("unable to create delta");
317-
if (delta_size + 20 < size / 2) {
318-
if (!cur_entry->delta || cur_entry->delta_size > delta_size) {
319-
cur_entry->delta = old_entry;
320-
cur_entry->delta_size = delta_size;
321-
}
322-
}
322+
return 0;
323+
cur_entry->delta = old_entry;
324+
cur_entry->delta_size = delta_size;
323325
free(delta_buf);
324326
return 0;
325327
}

test-delta.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,12 @@ int main(int argc, char *argv[])
6060

6161
if (argv[1][1] == 'd')
6262
out_buf = diff_delta(from_buf, from_size,
63-
data_buf, data_size, &out_size);
63+
data_buf, data_size,
64+
&out_size, ~0UL);
6465
else
6566
out_buf = patch_delta(from_buf, from_size,
66-
data_buf, data_size, &out_size);
67+
data_buf, data_size,
68+
&out_size);
6769
if (!out_buf) {
6870
fprintf(stderr, "delta operation failed (returned NULL)\n");
6971
return 1;

0 commit comments

Comments
 (0)