Skip to content

Commit 521a4f4

Browse files
author
Linus Torvalds
committed
git-pack-objects: do the delta search in reverse size order
Starting from big objects and going backwards means that we end up picking a delta that goes from a bigger object to a smaller one. That's advantageous for two reasons: the bigger object is likely the newer one (since things tend to grow, rather than shrink), and doing a delete tends to be smaller than doing an add. So the deltas don't tend to be top-of-tree, and the packed end result is just slightly smaller.
1 parent 102fc37 commit 521a4f4

File tree

1 file changed

+16
-12
lines changed

1 file changed

+16
-12
lines changed

pack-objects.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -280,31 +280,31 @@ struct unpacked {
280280
};
281281

282282
/*
283-
* We search for deltas in a list sorted by type and by size, and
284-
* walk the "old" chain backwards in the list, so if the type
285-
* has changed or the size difference is too big, there's no point
286-
* in even continuing the walk, since the other old objects are
287-
* going to be even smaller or of a different type. So return -1
288-
* once we determine that there's no point even trying.
283+
* We search for deltas _backwards_ in a list sorted by type and
284+
* by size, so that we see progressively smaller and smaller files.
285+
* That's because we prefer deltas to be from the bigger file
286+
* to the smaller - deletes are potentially cheaper, but perhaps
287+
* more importantly, the bigger file is likely the more recent
288+
* one.
289289
*/
290290
static int try_delta(struct unpacked *cur, struct unpacked *old, unsigned max_depth)
291291
{
292292
struct object_entry *cur_entry = cur->entry;
293293
struct object_entry *old_entry = old->entry;
294-
unsigned long size, oldsize, delta_size;
294+
unsigned long size, oldsize, delta_size, sizediff;
295295
long max_size;
296296
void *delta_buf;
297297

298298
/* Don't bother doing diffs between different types */
299299
if (cur_entry->type != old_entry->type)
300300
return -1;
301301

302-
/* Size is guaranteed to be larger than or equal to oldsize */
303302
size = cur_entry->size;
304303
if (size < 50)
305304
return -1;
306305
oldsize = old_entry->size;
307-
if (size - oldsize > oldsize / 4)
306+
sizediff = oldsize > size ? oldsize - size : size - oldsize;
307+
if (sizediff > size / 8)
308308
return -1;
309309
if (old_entry->depth >= max_depth)
310310
return 0;
@@ -332,13 +332,14 @@ static int try_delta(struct unpacked *cur, struct unpacked *old, unsigned max_de
332332

333333
static void find_deltas(struct object_entry **list, int window, int depth)
334334
{
335-
unsigned int i;
335+
int i, idx;
336336
unsigned int array_size = window * sizeof(struct unpacked);
337337
struct unpacked *array = xmalloc(array_size);
338338

339339
memset(array, 0, array_size);
340-
for (i = 0; i < nr_objects; i++) {
341-
unsigned int idx = i % window;
340+
i = nr_objects;
341+
idx = 0;
342+
while (--i >= 0) {
342343
struct object_entry *entry = list[i];
343344
struct unpacked *n = array + idx;
344345
unsigned long size;
@@ -362,6 +363,9 @@ static void find_deltas(struct object_entry **list, int window, int depth)
362363
if (try_delta(n, m, depth) < 0)
363364
break;
364365
}
366+
idx++;
367+
if (idx >= window)
368+
idx = 0;
365369
}
366370
}
367371

0 commit comments

Comments
 (0)