summaryrefslogtreecommitdiff
path: root/pack-objects.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2018-05-23 05:38:19 (GMT)
committerJunio C Hamano <gitster@pobox.com>2018-05-23 05:38:19 (GMT)
commitad635e82d600e1b725a2e65d69114140db6bc876 (patch)
tree6e6eff741825aaa150ef5a053730f50f09d63988 /pack-objects.c
parentc67de747f44c149747f1f4ce5f6d5d6659ba0fbc (diff)
parentf6a5576d521693963092dd69355d8e96ecd73635 (diff)
downloadgit-ad635e82d600e1b725a2e65d69114140db6bc876.zip
git-ad635e82d600e1b725a2e65d69114140db6bc876.tar.gz
git-ad635e82d600e1b725a2e65d69114140db6bc876.tar.bz2
Merge branch 'nd/pack-objects-pack-struct'
"git pack-objects" needs to allocate tons of "struct object_entry" while doing its work, and shrinking its size helps the performance quite a bit. * nd/pack-objects-pack-struct: ci: exercise the whole test suite with uncommon code in pack-objects pack-objects: reorder members to shrink struct object_entry pack-objects: shrink delta_size field in struct object_entry pack-objects: shrink size field in struct object_entry pack-objects: clarify the use of object_entry::size pack-objects: don't check size when the object is bad pack-objects: shrink z_delta_size field in struct object_entry pack-objects: refer to delta objects by index instead of pointer pack-objects: move in_pack out of struct object_entry pack-objects: move in_pack_pos out of struct object_entry pack-objects: use bitfield for object_entry::depth pack-objects: use bitfield for object_entry::dfs_state pack-objects: turn type and in_pack_type to bitfields pack-objects: a bit of document about struct object_entry read-cache.c: make $GIT_TEST_SPLIT_INDEX boolean
Diffstat (limited to 'pack-objects.c')
-rw-r--r--pack-objects.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/pack-objects.c b/pack-objects.c
index 9558d13..e0c4600 100644
--- a/pack-objects.c
+++ b/pack-objects.c
@@ -2,6 +2,8 @@
#include "object.h"
#include "pack.h"
#include "pack-objects.h"
+#include "packfile.h"
+#include "config.h"
static uint32_t locate_object_entry_hash(struct packing_data *pdata,
const unsigned char *sha1,
@@ -86,6 +88,66 @@ struct object_entry *packlist_find(struct packing_data *pdata,
return &pdata->objects[pdata->index[i] - 1];
}
+static void prepare_in_pack_by_idx(struct packing_data *pdata)
+{
+ struct packed_git **mapping, *p;
+ int cnt = 0, nr = 1U << OE_IN_PACK_BITS;
+
+ ALLOC_ARRAY(mapping, nr);
+ /*
+ * oe_in_pack() on an all-zero'd object_entry
+ * (i.e. in_pack_idx also zero) should return NULL.
+ */
+ mapping[cnt++] = NULL;
+ for (p = get_packed_git(the_repository); p; p = p->next, cnt++) {
+ if (cnt == nr) {
+ free(mapping);
+ return;
+ }
+ p->index = cnt;
+ mapping[cnt] = p;
+ }
+ pdata->in_pack_by_idx = mapping;
+}
+
+/*
+ * A new pack appears after prepare_in_pack_by_idx() has been
+ * run. This is likely a race.
+ *
+ * We could map this new pack to in_pack_by_idx[] array, but then we
+ * have to deal with full array anyway. And since it's hard to test
+ * this fall back code, just stay simple and fall back to using
+ * in_pack[] array.
+ */
+void oe_map_new_pack(struct packing_data *pack,
+ struct packed_git *p)
+{
+ uint32_t i;
+
+ REALLOC_ARRAY(pack->in_pack, pack->nr_alloc);
+
+ for (i = 0; i < pack->nr_objects; i++)
+ pack->in_pack[i] = oe_in_pack(pack, pack->objects + i);
+
+ FREE_AND_NULL(pack->in_pack_by_idx);
+}
+
+/* assume pdata is already zero'd by caller */
+void prepare_packing_data(struct packing_data *pdata)
+{
+ if (git_env_bool("GIT_TEST_FULL_IN_PACK_ARRAY", 0)) {
+ /*
+ * do not initialize in_pack_by_idx[] to force the
+ * slow path in oe_in_pack()
+ */
+ } else {
+ prepare_in_pack_by_idx(pdata);
+ }
+
+ pdata->oe_size_limit = git_env_ulong("GIT_TEST_OE_SIZE",
+ 1U << OE_SIZE_BITS);
+}
+
struct object_entry *packlist_alloc(struct packing_data *pdata,
const unsigned char *sha1,
uint32_t index_pos)
@@ -95,6 +157,9 @@ struct object_entry *packlist_alloc(struct packing_data *pdata,
if (pdata->nr_objects >= pdata->nr_alloc) {
pdata->nr_alloc = (pdata->nr_alloc + 1024) * 3 / 2;
REALLOC_ARRAY(pdata->objects, pdata->nr_alloc);
+
+ if (!pdata->in_pack_by_idx)
+ REALLOC_ARRAY(pdata->in_pack, pdata->nr_alloc);
}
new_entry = pdata->objects + pdata->nr_objects++;
@@ -107,5 +172,8 @@ struct object_entry *packlist_alloc(struct packing_data *pdata,
else
pdata->index[index_pos] = pdata->nr_objects;
+ if (pdata->in_pack)
+ pdata->in_pack[pdata->nr_objects - 1] = NULL;
+
return new_entry;
}