apply delta depth bias to already deltified objects
authorNicolas Pitre <nico@cam.org>
Thu, 12 Jul 2007 18:33:21 +0000 (14:33 -0400)
committerJunio C Hamano <gitster@pobox.com>
Thu, 12 Jul 2007 21:18:14 +0000 (14:18 -0700)
We already apply a bias on the initial delta attempt with max_size being
a function of the base object depth.  This has the effect of favoring
shallower deltas even if deeper deltas could be smaller, and therefore
creating a wider delta tree (see commits 4e8da195 and c3b06a69).

This principle should also be applied to all delta attempts for the same
object and not only the first attempt.  With this the criteria for the
best delta is not only its size but also its depth, so that a shallower
delta might be selected even if it is larger than a deeper one.  Even if
some deltas get larger, they allow for wider delta trees making the
depth limit less quickly reached and therefore better deltas can be
subsequently found, keeping the resulting pack size even smaller.
Runtime access to the pack should also benefit from shallower deltas.

Testing on different repositories showed slighter faster repacks,
smaller resulting packs, and a much nicer curve for delta depth
distribution with no more peak at the maximum depth level.
Improvements are even more significant with smaller depth limits.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin-pack-objects.c

index 54b9d268da7d3b968f7a950dbe8bad9c2735e345..b4f3e7c2ebf4f50172c7d8dfa068de7e81fdc9b4 100644 (file)
@@ -1303,6 +1303,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
        struct object_entry *trg_entry = trg->entry;
        struct object_entry *src_entry = src->entry;
        unsigned long trg_size, src_size, delta_size, sizediff, max_size, sz;
+       unsigned ref_depth;
        enum object_type type;
        void *delta_buf;
 
@@ -1332,12 +1333,17 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
 
        /* Now some size filtering heuristics. */
        trg_size = trg_entry->size;
-       max_size = trg_size/2 - 20;
-       max_size = max_size * (max_depth - src_entry->depth) / max_depth;
+       if (!trg_entry->delta) {
+               max_size = trg_size/2 - 20;
+               ref_depth = 1;
+       } else {
+               max_size = trg_entry->delta_size;
+               ref_depth = trg_entry->depth;
+       }
+       max_size = max_size * (max_depth - src_entry->depth) /
+                                               (max_depth - ref_depth + 1);
        if (max_size == 0)
                return 0;
-       if (trg_entry->delta && trg_entry->delta_size <= max_size)
-               max_size = trg_entry->delta_size;
        src_size = src_entry->size;
        sizediff = src_size < trg_size ? trg_size - src_size : 0;
        if (sizediff >= max_size)