Skip to content

Commit 11d45a6

Browse files
ttaylorrgitster
authored andcommitted
pack-bitmap.c: use pseudo-merges during traversal
Now that all of the groundwork has been laid to support reading and using pseudo-merges, make use of that work in this commit by teaching the pack-bitmap machinery to use pseudo-merge(s) when available during traversal. The basic operation is as follows: - When enumerating objects on either side of a reachability query, first see if any subset of the roots satisfies some pseudo-merge bitmap. If it does, apply that pseudo-merge bitmap. - If any pseudo-merge bitmap(s) were applied in the previous step, OR them into the result[^1]. Then repeat the process over all pseudo-merge bitmaps (we'll refer to this as "cascading" pseudo-merges). Once this is done, OR in the resulting bitmap. - If there is no fill-in traversal to be done, return the bitmap for that side of the reachability query. If there is fill-in traversal, then for each commit we encounter via show_commit(), check to see if any unsatisfied pseudo-merges containing that commit as one of its parents has been made satisfied by the presence of that commit. If so, OR in the object set from that pseudo-merge bitmap, and then cascade. If not, continue traversal. A similar implementation is present in the boundary-based bitmap traversal routines. [^1]: Importantly, we cannot OR in the entire set of roots along with the objects reachable from whatever pseudo-merge bitmaps were satisfied. This may leave some dangling bits corresponding to any unsatisfied root(s) getting OR'd into the resulting bitmap, tricking other parts of the traversal into thinking we already have a reachability closure over those commit(s) when we do not. Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8e41468 commit 11d45a6

File tree

2 files changed

+439
-1
lines changed

2 files changed

+439
-1
lines changed

pack-bitmap.c

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ struct bitmap_index {
114114
unsigned int version;
115115
};
116116

117+
static int pseudo_merges_satisfied_nr;
118+
static int pseudo_merges_cascades_nr;
119+
117120
static struct ewah_bitmap *lookup_stored_bitmap(struct stored_bitmap *st)
118121
{
119122
struct ewah_bitmap *parent;
@@ -1006,6 +1009,22 @@ static void show_commit(struct commit *commit UNUSED,
10061009
{
10071010
}
10081011

1012+
static unsigned apply_pseudo_merges_for_commit_1(struct bitmap_index *bitmap_git,
1013+
struct bitmap *result,
1014+
struct commit *commit,
1015+
uint32_t commit_pos)
1016+
{
1017+
int ret;
1018+
1019+
ret = apply_pseudo_merges_for_commit(&bitmap_git->pseudo_merges,
1020+
result, commit, commit_pos);
1021+
1022+
if (ret)
1023+
pseudo_merges_satisfied_nr += ret;
1024+
1025+
return ret;
1026+
}
1027+
10091028
static int add_to_include_set(struct bitmap_index *bitmap_git,
10101029
struct include_data *data,
10111030
struct commit *commit,
@@ -1026,6 +1045,10 @@ static int add_to_include_set(struct bitmap_index *bitmap_git,
10261045
}
10271046

10281047
bitmap_set(data->base, bitmap_pos);
1048+
if (apply_pseudo_merges_for_commit_1(bitmap_git, data->base, commit,
1049+
bitmap_pos))
1050+
return 0;
1051+
10291052
return 1;
10301053
}
10311054

@@ -1151,6 +1174,20 @@ static void show_boundary_object(struct object *object UNUSED,
11511174
BUG("should not be called");
11521175
}
11531176

1177+
static unsigned cascade_pseudo_merges_1(struct bitmap_index *bitmap_git,
1178+
struct bitmap *result,
1179+
struct bitmap *roots)
1180+
{
1181+
int ret = cascade_pseudo_merges(&bitmap_git->pseudo_merges,
1182+
result, roots);
1183+
if (ret) {
1184+
pseudo_merges_cascades_nr++;
1185+
pseudo_merges_satisfied_nr += ret;
1186+
}
1187+
1188+
return ret;
1189+
}
1190+
11541191
static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,
11551192
struct rev_info *revs,
11561193
struct object_list *roots)
@@ -1160,13 +1197,33 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,
11601197
unsigned int i;
11611198
unsigned int tmp_blobs, tmp_trees, tmp_tags;
11621199
int any_missing = 0;
1200+
int existing_bitmaps = 0;
11631201

11641202
cb.bitmap_git = bitmap_git;
11651203
cb.base = bitmap_new();
11661204
object_array_init(&cb.boundary);
11671205

11681206
revs->ignore_missing_links = 1;
11691207

1208+
if (bitmap_git->pseudo_merges.nr) {
1209+
struct bitmap *roots_bitmap = bitmap_new();
1210+
struct object_list *objects = NULL;
1211+
1212+
for (objects = roots; objects; objects = objects->next) {
1213+
struct object *object = objects->item;
1214+
int pos;
1215+
1216+
pos = bitmap_position(bitmap_git, &object->oid);
1217+
if (pos < 0)
1218+
continue;
1219+
1220+
bitmap_set(roots_bitmap, pos);
1221+
}
1222+
1223+
if (!cascade_pseudo_merges_1(bitmap_git, cb.base, roots_bitmap))
1224+
bitmap_free(roots_bitmap);
1225+
}
1226+
11701227
/*
11711228
* OR in any existing reachability bitmaps among `roots` into
11721229
* `cb.base`.
@@ -1178,15 +1235,20 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,
11781235
continue;
11791236

11801237
if (add_commit_to_bitmap(bitmap_git, &cb.base,
1181-
(struct commit *)object))
1238+
(struct commit *)object)) {
1239+
existing_bitmaps = 1;
11821240
continue;
1241+
}
11831242

11841243
any_missing = 1;
11851244
}
11861245

11871246
if (!any_missing)
11881247
goto cleanup;
11891248

1249+
if (existing_bitmaps)
1250+
cascade_pseudo_merges_1(bitmap_git, cb.base, NULL);
1251+
11901252
tmp_blobs = revs->blob_objects;
11911253
tmp_trees = revs->tree_objects;
11921254
tmp_tags = revs->blob_objects;
@@ -1242,16 +1304,46 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,
12421304
return cb.base;
12431305
}
12441306

1307+
static void unsatisfy_all_pseudo_merges(struct bitmap_index *bitmap_git)
1308+
{
1309+
uint32_t i;
1310+
for (i = 0; i < bitmap_git->pseudo_merges.nr; i++)
1311+
bitmap_git->pseudo_merges.v[i].satisfied = 0;
1312+
}
1313+
12451314
static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
12461315
struct rev_info *revs,
12471316
struct object_list *roots,
12481317
struct bitmap *seen)
12491318
{
12501319
struct bitmap *base = NULL;
12511320
int needs_walk = 0;
1321+
unsigned existing_bitmaps = 0;
12521322

12531323
struct object_list *not_mapped = NULL;
12541324

1325+
unsatisfy_all_pseudo_merges(bitmap_git);
1326+
1327+
if (bitmap_git->pseudo_merges.nr) {
1328+
struct bitmap *roots_bitmap = bitmap_new();
1329+
struct object_list *objects = NULL;
1330+
1331+
for (objects = roots; objects; objects = objects->next) {
1332+
struct object *object = objects->item;
1333+
int pos;
1334+
1335+
pos = bitmap_position(bitmap_git, &object->oid);
1336+
if (pos < 0)
1337+
continue;
1338+
1339+
bitmap_set(roots_bitmap, pos);
1340+
}
1341+
1342+
base = bitmap_new();
1343+
if (!cascade_pseudo_merges_1(bitmap_git, base, roots_bitmap))
1344+
bitmap_free(roots_bitmap);
1345+
}
1346+
12551347
/*
12561348
* Go through all the roots for the walk. The ones that have bitmaps
12571349
* on the bitmap index will be `or`ed together to form an initial
@@ -1262,11 +1354,21 @@ static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
12621354
*/
12631355
while (roots) {
12641356
struct object *object = roots->item;
1357+
12651358
roots = roots->next;
12661359

1360+
if (base) {
1361+
int pos = bitmap_position(bitmap_git, &object->oid);
1362+
if (pos > 0 && bitmap_get(base, pos)) {
1363+
object->flags |= SEEN;
1364+
continue;
1365+
}
1366+
}
1367+
12671368
if (object->type == OBJ_COMMIT &&
12681369
add_commit_to_bitmap(bitmap_git, &base, (struct commit *)object)) {
12691370
object->flags |= SEEN;
1371+
existing_bitmaps = 1;
12701372
continue;
12711373
}
12721374

@@ -1282,6 +1384,9 @@ static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
12821384

12831385
roots = not_mapped;
12841386

1387+
if (existing_bitmaps)
1388+
cascade_pseudo_merges_1(bitmap_git, base, NULL);
1389+
12851390
/*
12861391
* Let's iterate through all the roots that don't have bitmaps to
12871392
* check if we can determine them to be reachable from the existing
@@ -1866,6 +1971,11 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
18661971
object_list_free(&wants);
18671972
object_list_free(&haves);
18681973

1974+
trace2_data_intmax("bitmap", the_repository, "pseudo_merges_satisfied",
1975+
pseudo_merges_satisfied_nr);
1976+
trace2_data_intmax("bitmap", the_repository, "pseudo_merges_cascades",
1977+
pseudo_merges_cascades_nr);
1978+
18691979
return bitmap_git;
18701980

18711981
cleanup:

0 commit comments

Comments
 (0)