summaryrefslogtreecommitdiff
path: root/pack-bitmap-write.c
diff options
context:
space:
mode:
authorDerrick Stolee <dstolee@microsoft.com>2020-12-08 22:05:26 (GMT)
committerJunio C Hamano <gitster@pobox.com>2020-12-08 22:49:07 (GMT)
commit45f4eeb2919e2c802a6c1f64a2b1c299f7434938 (patch)
tree22b0301626576d50f487bedf98ab1fbd0fd8bc64 /pack-bitmap-write.c
parent341fa34887630a7adf6b3a771ae866ce66e7967e (diff)
downloadgit-45f4eeb2919e2c802a6c1f64a2b1c299f7434938.zip
git-45f4eeb2919e2c802a6c1f64a2b1c299f7434938.tar.gz
git-45f4eeb2919e2c802a6c1f64a2b1c299f7434938.tar.bz2
pack-bitmap-write: relax unique revwalk condition
The previous commits improved the bitmap computation process for very long, linear histories with many refs by removing quadratic growth in how many objects were walked. The strategy of computing "intermediate commits" using bitmasks for which refs can reach those commits partitioned the poset of reachable objects so each part could be walked exactly once. This was effective for linear histories. However, there was a (significant) drawback: wide histories with many refs had an explosion of memory costs to compute the commit bitmasks during the exploration that discovers these intermediate commits. Since these wide histories are unlikely to repeat walking objects, the benefit of walking objects multiple times was not expensive before. But now, the commit walk *before computing bitmaps* is incredibly expensive. In an effort to discover a happy medium, this change reduces the walk for intermediate commits to only the first-parent history. This focuses the walk on how the histories converge, which still has significant reduction in repeat object walks. It is still possible to create quadratic behavior in this version, but it is probably less likely in realistic data shapes. Here is some data taken on a fresh clone of the kernel: | runtime (sec) | peak heap (GB) | | | | | from | with | from | with | | scratch | existing | scratch | existing | -----------+---------+----------+---------+----------- original | 64.044 | 83.241 | 2.088 | 2.194 | last patch | 45.049 | 37.624 | 2.267 | 2.334 | this patch | 88.478 | 53.218 | 2.157 | 2.224 | Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Helped-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'pack-bitmap-write.c')
-rw-r--r--pack-bitmap-write.c14
1 files changed, 5 insertions, 9 deletions
diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c
index 76c8236..d2af4a9 100644
--- a/pack-bitmap-write.c
+++ b/pack-bitmap-write.c
@@ -199,7 +199,7 @@ static void bitmap_builder_init(struct bitmap_builder *bb,
{
struct rev_info revs;
struct commit *commit;
- unsigned int i, num_maximal;
+ unsigned int i, num_maximal = 0;
memset(bb, 0, sizeof(*bb));
init_bb_data(&bb->data);
@@ -207,6 +207,7 @@ static void bitmap_builder_init(struct bitmap_builder *bb,
reset_revision_walk();
repo_init_revisions(writer->to_pack->repo, &revs, NULL);
revs.topo_order = 1;
+ revs.first_parent_only = 1;
for (i = 0; i < writer->selected_nr; i++) {
struct commit *c = writer->selected[i].commit;
@@ -221,13 +222,12 @@ static void bitmap_builder_init(struct bitmap_builder *bb,
add_pending_object(&revs, &c->object, "");
}
- num_maximal = writer->selected_nr;
if (prepare_revision_walk(&revs))
die("revision walk setup failed");
while ((commit = get_revision(&revs))) {
- struct commit_list *p;
+ struct commit_list *p = commit->parents;
struct bb_commit *c_ent;
parse_commit_or_die(commit);
@@ -235,16 +235,12 @@ static void bitmap_builder_init(struct bitmap_builder *bb,
c_ent = bb_data_at(&bb->data, commit);
if (c_ent->maximal) {
- if (!c_ent->selected) {
- bitmap_set(c_ent->commit_mask, num_maximal);
- num_maximal++;
- }
-
+ num_maximal++;
ALLOC_GROW(bb->commits, bb->commits_nr + 1, bb->commits_alloc);
bb->commits[bb->commits_nr++] = commit;
}
- for (p = commit->parents; p; p = p->next) {
+ if (p) {
struct bb_commit *p_ent = bb_data_at(&bb->data, p->item);
int c_not_p, p_not_c;