On Thu, Jul 19, 2018 at 07:57:37AM +0200, Duy Nguyen wrote:
> I thought 2M was generous but I was obviously wrong. I'd like to see
> the biggest delta size in this pack and whether it's still reasonable
> to increase OE_DELTA_SIZE_BITS. But if it's very close to 4GB limit
> then we could just store 64-bit delta size in a separate array.

I realize now that these two options don't have to be mutually
exclusive and I should provide a good fallback in terms of performance
anyway.

So Elijah, could you try this patch and see if performance and pack
size go back to 1.7.0? I can write proper commit message and test
support later if it proves a good improvement.

-- 8< --
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index ebc8cefb53..7f3546057d 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -2023,10 +2023,6 @@ static int try_delta(struct unpacked *trg, struct 
unpacked *src,
        delta_buf = create_delta(src->index, trg->data, trg_size, &delta_size, 
max_size);
        if (!delta_buf)
                return 0;
-       if (delta_size >= (1U << OE_DELTA_SIZE_BITS)) {
-               free(delta_buf);
-               return 0;
-       }
 
        if (DELTA(trg_entry)) {
                /* Prefer only shallower same-sized deltas. */
diff --git a/pack-objects.c b/pack-objects.c
index 92708522e7..191ed45faf 100644
--- a/pack-objects.c
+++ b/pack-objects.c
@@ -160,6 +160,8 @@ struct object_entry *packlist_alloc(struct packing_data 
*pdata,
 
                if (!pdata->in_pack_by_idx)
                        REALLOC_ARRAY(pdata->in_pack, pdata->nr_alloc);
+               if (pdata->delta_size)
+                       REALLOC_ARRAY(pdata->delta_size, pdata->nr_alloc);
        }
 
        new_entry = pdata->objects + pdata->nr_objects++;
@@ -177,3 +179,17 @@ struct object_entry *packlist_alloc(struct packing_data 
*pdata,
 
        return new_entry;
 }
+
+void oe_prepare_delta_size_array(struct packing_data *pack)
+{
+       int i;
+
+       /*
+        * nr_alloc, not nr_objects to align with realloc() strategy in
+        * packlist_alloc()
+        */
+       ALLOC_ARRAY(pack->delta_size, pack->nr_alloc);
+
+       for (i = 0; i < pack->nr_objects; i++)
+               pack->delta_size[i] = pack->objects[i].delta_size_;
+}
diff --git a/pack-objects.h b/pack-objects.h
index edf74dabdd..978500e474 100644
--- a/pack-objects.h
+++ b/pack-objects.h
@@ -14,7 +14,7 @@
  * above this limit. Don't lower it too much.
  */
 #define OE_SIZE_BITS           31
-#define OE_DELTA_SIZE_BITS     20
+#define OE_DELTA_SIZE_BITS     21
 
 /*
  * State flags for depth-first search used for analyzing delta cycles.
@@ -93,7 +93,6 @@ struct object_entry {
                                     * uses the same base as me
                                     */
        unsigned delta_size_:OE_DELTA_SIZE_BITS; /* delta data size 
(uncompressed) */
-       unsigned delta_size_valid:1;
        unsigned in_pack_idx:OE_IN_PACK_BITS;   /* already in pack */
        unsigned z_delta_size:OE_Z_DELTA_BITS;
        unsigned type_valid:1;
@@ -130,6 +129,7 @@ struct packing_data {
        uint32_t index_size;
 
        unsigned int *in_pack_pos;
+       unsigned long *delta_size;
 
        /*
         * Only one of these can be non-NULL and they have different
@@ -330,20 +330,27 @@ static inline void oe_set_size(struct packing_data *pack,
 static inline unsigned long oe_delta_size(struct packing_data *pack,
                                          const struct object_entry *e)
 {
-       if (e->delta_size_valid)
+       if (!pack->delta_size)
                return e->delta_size_;
-       return oe_size(pack, e);
+       return pack->delta_size[e - pack->objects];
 }
 
+void oe_prepare_delta_size_array(struct packing_data *pack);
 static inline void oe_set_delta_size(struct packing_data *pack,
                                     struct object_entry *e,
                                     unsigned long size)
 {
        e->delta_size_ = size;
-       e->delta_size_valid = e->delta_size_ == size;
-       if (!e->delta_size_valid && size != oe_size(pack, e))
-               BUG("this can only happen in check_object() "
-                   "where delta size is the same as entry size");
+       if (!pack->delta_size && e->delta_size_ == size)
+               return;
+       /*
+        * We have had at least one delta size exceeding OE_DELTA_SIZE_BITS
+        * limit. delta_size_ will not be used anymore. All delta sizes are now
+        * from the delta_size[] array.
+        */
+       if (!pack->delta_size)
+               oe_prepare_delta_size_array(pack);
+       pack->delta_size[e - pack->objects] = size;
 }
 
 #endif
-- 8< --


--
Duy

Reply via email to