]> git.ipfire.org Git - thirdparty/git.git/commitdiff
rev-list: allow commit-only bitmap traversals
authorJeff King <peff@peff.net>
Fri, 14 Feb 2020 18:22:27 +0000 (13:22 -0500)
committerJunio C Hamano <gitster@pobox.com>
Fri, 14 Feb 2020 18:46:22 +0000 (10:46 -0800)
Ever since we added reachability bitmap support, we've been able to use
it with rev-list to get the full list of objects, like:

  git rev-list --objects --use-bitmap-index --all

But you can't do so without --objects, since we weren't ready to just
show the commits. However, the internals of the bitmap code are mostly
ready for this: they avoid opening up trees when walking to fill in the
bitmaps. We just need to actually pass in the rev_info to
traverse_bitmap_commit_list() so it knows which types to bother
triggering our callback for.

For completeness, the perf test now covers both the existing --objects
case, as well as the new commits-only behavior (the objects one got way
faster when we introduced bitmaps, but obviously isn't improved now).

Here are numbers for linux.git:

  Test                         HEAD^               HEAD
  ------------------------------------------------------------------------
  5310.7: rev-list (commits)   8.29(8.10+0.19)       1.76(1.72+0.04) -78.8%
  5310.8: rev-list (objects)   8.06(7.94+0.12)       8.14(7.94+0.13) +1.0%

That run was cheating a little, as I didn't have any commit-graph in the
repository, and we'd built it by default these days when running git-gc.
Here are numbers with a commit-graph:

  Test                         HEAD^               HEAD
  ------------------------------------------------------------------------
  5310.7: rev-list (commits)   0.70(0.58+0.12)     0.51(0.46+0.04) -27.1%
  5310.8: rev-list (objects)   6.20(6.09+0.10)     6.27(6.16+0.11) +1.1%

Still an improvement, but a lot less impressive.

We could have the perf script remove any commit-graph to show the
out-sized effect, but it probably makes sense to leave it in what would
be a more typical setup.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/pack-objects.c
builtin/rev-list.c
pack-bitmap.c
pack-bitmap.h
reachable.c
t/perf/p5310-pack-bitmaps.sh
t/t5310-pack-bitmaps.sh

index 393c20a2d78b50f8852ed11bc9e943b27ba58d2e..06915ebe7f86714700b090db58a50cc4263ba87e 100644 (file)
@@ -3054,7 +3054,8 @@ static int get_object_list_from_bitmap(struct rev_info *revs)
                display_progress(progress_state, nr_result);
        }
 
-       traverse_bitmap_commit_list(bitmap_git, &add_object_entry_from_bitmap);
+       traverse_bitmap_commit_list(bitmap_git, revs,
+                                   &add_object_entry_from_bitmap);
        return 0;
 }
 
index 70f3207ecce5ba0c2e47cdc2e1954fc6d64090dc..937324cef030b9489591be720182451cacf39d0e 100644 (file)
@@ -434,18 +434,11 @@ static int try_bitmap_traversal(struct rev_info *revs)
        if (revs->max_count >= 0)
                return -1;
 
-       /*
-        * Our bitmap result will return all objects, and we're not
-        * yet prepared to show only particular types.
-        */
-       if (!revs->tag_objects || !revs->tree_objects || !revs->blob_objects)
-               return -1;
-
        bitmap_git = prepare_bitmap_walk(revs);
        if (!bitmap_git)
                return -1;
 
-       traverse_bitmap_commit_list(bitmap_git, &show_object_fast);
+       traverse_bitmap_commit_list(bitmap_git, revs, &show_object_fast);
        free_bitmap_index(bitmap_git);
        return 0;
 }
index a97b717e559adb4fa75a342643fea1bb805d39c6..2fbc748b193eabbe147aff930ce1a23cdeed2436 100644 (file)
@@ -599,6 +599,7 @@ static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
 }
 
 static void show_extended_objects(struct bitmap_index *bitmap_git,
+                                 struct rev_info *revs,
                                  show_reachable_fn show_reach)
 {
        struct bitmap *objects = bitmap_git->result;
@@ -612,6 +613,11 @@ static void show_extended_objects(struct bitmap_index *bitmap_git,
                        continue;
 
                obj = eindex->objects[i];
+               if ((obj->type == OBJ_BLOB && !revs->blob_objects) ||
+                   (obj->type == OBJ_TREE && !revs->tree_objects) ||
+                   (obj->type == OBJ_TAG && !revs->tag_objects))
+                       continue;
+
                show_reach(&obj->oid, obj->type, 0, eindex->hashes[i], NULL, 0);
        }
 }
@@ -872,16 +878,20 @@ int reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
 }
 
 void traverse_bitmap_commit_list(struct bitmap_index *bitmap_git,
+                                struct rev_info *revs,
                                 show_reachable_fn show_reachable)
 {
        assert(bitmap_git->result);
 
        show_objects_for_type(bitmap_git, OBJ_COMMIT, show_reachable);
-       show_objects_for_type(bitmap_git, OBJ_TREE, show_reachable);
-       show_objects_for_type(bitmap_git, OBJ_BLOB, show_reachable);
-       show_objects_for_type(bitmap_git, OBJ_TAG, show_reachable);
-
-       show_extended_objects(bitmap_git, show_reachable);
+       if (revs->tree_objects)
+               show_objects_for_type(bitmap_git, OBJ_TREE, show_reachable);
+       if (revs->blob_objects)
+               show_objects_for_type(bitmap_git, OBJ_BLOB, show_reachable);
+       if (revs->tag_objects)
+               show_objects_for_type(bitmap_git, OBJ_TAG, show_reachable);
+
+       show_extended_objects(bitmap_git, revs, show_reachable);
 }
 
 static uint32_t count_object_type(struct bitmap_index *bitmap_git,
index 466c5afa09c37c4e5a56a33604510659b209e86b..b0c06a212ebf60406d50ffc40fdf003ecbdbe00e 100644 (file)
@@ -44,6 +44,7 @@ struct bitmap_index *prepare_bitmap_git(struct repository *r);
 void count_bitmap_commit_list(struct bitmap_index *, uint32_t *commits,
                              uint32_t *trees, uint32_t *blobs, uint32_t *tags);
 void traverse_bitmap_commit_list(struct bitmap_index *,
+                                struct rev_info *revs,
                                 show_reachable_fn show_reachable);
 void test_bitmap_walk(struct rev_info *revs);
 struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs);
index 8f50235b28edd43c3a4e122a1bcae4d1c1b3f99b..0919f025c4a7ddf70ef2999608984fb571690456 100644 (file)
@@ -225,7 +225,7 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
 
        bitmap_git = prepare_bitmap_walk(revs);
        if (bitmap_git) {
-               traverse_bitmap_commit_list(bitmap_git, mark_object_seen);
+               traverse_bitmap_commit_list(bitmap_git, revs, mark_object_seen);
                free_bitmap_index(bitmap_git);
                return;
        }
index 6a3a42531b056285ac3a42cabe97c41146fa4291..e52f66ec9ed878f6f838e4a416f165ae4f294df7 100755 (executable)
@@ -39,6 +39,14 @@ test_perf 'pack to file (bitmap)' '
        git pack-objects --use-bitmap-index --all pack1b </dev/null >/dev/null
 '
 
+test_perf 'rev-list (commits)' '
+       git rev-list --all --use-bitmap-index >/dev/null
+'
+
+test_perf 'rev-list (objects)' '
+       git rev-list --all --use-bitmap-index --objects >/dev/null
+'
+
 test_expect_success 'create partial bitmap state' '
        # pick a commit to represent the repo tip in the past
        cutoff=$(git rev-list HEAD~100 -1) &&
index b8645ae070f17d1cd0fcb574981a491cb47b293f..2c64d0c4412a83d22cc0a0468d8456d3c95177ca 100755 (executable)
@@ -80,6 +80,12 @@ rev_list_tests() {
                test_cmp expect actual
        '
 
+       test_expect_success "enumerate commits ($state)" '
+               git rev-list --use-bitmap-index HEAD >actual &&
+               git rev-list HEAD >expect &&
+               test_bitmap_traversal --no-confirm-bitmaps expect actual
+       '
+
        test_expect_success "enumerate --objects ($state)" '
                git rev-list --objects --use-bitmap-index HEAD >actual &&
                git rev-list --objects HEAD >expect &&