Skip to content

Commit 341fa34

Browse files
derrickstoleegitster
authored andcommitted
pack-bitmap-write: use existing bitmaps
When constructing new bitmaps, we perform a commit and tree walk in fill_bitmap_commit() and fill_bitmap_tree(). This walk would benefit from using existing bitmaps when available. We must track the existing bitmaps and translate them into the new object order, but this is generally faster than parsing trees. In fill_bitmap_commit(), we must reorder thing somewhat. The priority queue walks commits from newest-to-oldest, which means we correctly stop walking when reaching a commit with a bitmap. However, if we walk trees interleaved with the commits, then we might be parsing trees that are actually part of a re-used bitmap. To avoid over-walking trees, add them to a LIFO queue and walk them after exploring commits completely. On git.git, this reduces a second immediate bitmap computation from 2.0s to 1.0s. On linux.git, we go from 32s to 22s. On chromium's fork network, we go from 227s to 198s. Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8357805 commit 341fa34

File tree

1 file changed

+36
-4
lines changed

1 file changed

+36
-4
lines changed

pack-bitmap-write.c

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -340,20 +340,37 @@ static void fill_bitmap_tree(struct bitmap *bitmap,
340340

341341
static void fill_bitmap_commit(struct bb_commit *ent,
342342
struct commit *commit,
343-
struct prio_queue *queue)
343+
struct prio_queue *queue,
344+
struct prio_queue *tree_queue,
345+
struct bitmap_index *old_bitmap,
346+
const uint32_t *mapping)
344347
{
345348
if (!ent->bitmap)
346349
ent->bitmap = bitmap_new();
347350

348-
bitmap_set(ent->bitmap, find_object_pos(&commit->object.oid));
349351
prio_queue_put(queue, commit);
350352

351353
while (queue->nr) {
352354
struct commit_list *p;
353355
struct commit *c = prio_queue_get(queue);
354356

357+
if (old_bitmap && mapping) {
358+
struct ewah_bitmap *old = bitmap_for_commit(old_bitmap, c);
359+
/*
360+
* If this commit has an old bitmap, then translate that
361+
* bitmap and add its bits to this one. No need to walk
362+
* parents or the tree for this commit.
363+
*/
364+
if (old && !rebuild_bitmap(mapping, old, ent->bitmap))
365+
continue;
366+
}
367+
368+
/*
369+
* Mark ourselves and queue our tree. The commit
370+
* walk ensures we cover all parents.
371+
*/
355372
bitmap_set(ent->bitmap, find_object_pos(&c->object.oid));
356-
fill_bitmap_tree(ent->bitmap, get_commit_tree(c));
373+
prio_queue_put(tree_queue, get_commit_tree(c));
357374

358375
for (p = c->parents; p; p = p->next) {
359376
int pos = find_object_pos(&p->item->object.oid);
@@ -363,6 +380,9 @@ static void fill_bitmap_commit(struct bb_commit *ent,
363380
}
364381
}
365382
}
383+
384+
while (tree_queue->nr)
385+
fill_bitmap_tree(ent->bitmap, prio_queue_get(tree_queue));
366386
}
367387

368388
static void store_selected(struct bb_commit *ent, struct commit *commit)
@@ -386,6 +406,9 @@ void bitmap_writer_build(struct packing_data *to_pack)
386406
size_t i;
387407
int nr_stored = 0; /* for progress */
388408
struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
409+
struct prio_queue tree_queue = { NULL };
410+
struct bitmap_index *old_bitmap;
411+
uint32_t *mapping;
389412

390413
writer.bitmaps = kh_init_oid_map();
391414
writer.to_pack = to_pack;
@@ -395,14 +418,21 @@ void bitmap_writer_build(struct packing_data *to_pack)
395418
trace2_region_enter("pack-bitmap-write", "building_bitmaps_total",
396419
the_repository);
397420

421+
old_bitmap = prepare_bitmap_git(to_pack->repo);
422+
if (old_bitmap)
423+
mapping = create_bitmap_mapping(old_bitmap, to_pack);
424+
else
425+
mapping = NULL;
426+
398427
bitmap_builder_init(&bb, &writer);
399428
for (i = bb.commits_nr; i > 0; i--) {
400429
struct commit *commit = bb.commits[i-1];
401430
struct bb_commit *ent = bb_data_at(&bb.data, commit);
402431
struct commit *child;
403432
int reused = 0;
404433

405-
fill_bitmap_commit(ent, commit, &queue);
434+
fill_bitmap_commit(ent, commit, &queue, &tree_queue,
435+
old_bitmap, mapping);
406436

407437
if (ent->selected) {
408438
store_selected(ent, commit);
@@ -428,7 +458,9 @@ void bitmap_writer_build(struct packing_data *to_pack)
428458
ent->bitmap = NULL;
429459
}
430460
clear_prio_queue(&queue);
461+
clear_prio_queue(&tree_queue);
431462
bitmap_builder_clear(&bb);
463+
free(mapping);
432464

433465
trace2_region_leave("pack-bitmap-write", "building_bitmaps_total",
434466
the_repository);

0 commit comments

Comments
 (0)