]> git.ipfire.org Git - thirdparty/git.git/commitdiff
pack-bitmap.c: support 'tree:0' filtering
authorTaylor Blau <me@ttaylorr.com>
Mon, 4 May 2020 23:12:35 +0000 (17:12 -0600)
committerJunio C Hamano <gitster@pobox.com>
Tue, 5 May 2020 04:57:58 +0000 (21:57 -0700)
In the previous patch, we made it easy to define other filters that
exclude all objects of a certain type. Use that in order to implement
bitmap-level filtering for the '--filter=tree:<n>' filter when 'n' is
equal to 0.

The general case is not helped by bitmaps, since for values of 'n > 0',
the object filtering machinery requires a full-blown tree traversal in
order to determine the depth of a given tree. Caching this is
non-obvious, too, since the same tree object can have a different depth
depending on the context (e.g., a tree was moved up in the directory
hierarchy between two commits).

But, the 'n = 0' case can be helped, and this patch does so. Running
p5310.11 in this tree and on master with the kernel, we can see that
this case is helped substantially:

  Test                                  master              this tree
  --------------------------------------------------------------------------------
  5310.11: rev-list count with tree:0   10.68(10.39+0.27)   0.06(0.04+0.01) -99.4%

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
pack-bitmap.c
t/perf/p5310-pack-bitmaps.sh
t/t6113-rev-list-bitmap-filters.sh

index 3693c9e62fa168645419bbd11a73619861ec6a55..195ee8cad02d54d3ea6c38d1bc8afbc733717df5 100644 (file)
@@ -749,7 +749,7 @@ static void filter_bitmap_exclude_type(struct bitmap_index *bitmap_git,
        eword_t mask;
        uint32_t i;
 
-       if (type != OBJ_BLOB)
+       if (type != OBJ_BLOB && type != OBJ_TREE)
                BUG("filter_bitmap_exclude_type: unsupported type '%d'", type);
 
        /*
@@ -867,6 +867,20 @@ static void filter_bitmap_blob_limit(struct bitmap_index *bitmap_git,
        bitmap_free(tips);
 }
 
+static void filter_bitmap_tree_depth(struct bitmap_index *bitmap_git,
+                                    struct object_list *tip_objects,
+                                    struct bitmap *to_filter,
+                                    unsigned long limit)
+{
+       if (limit)
+               BUG("filter_bitmap_tree_depth given non-zero limit");
+
+       filter_bitmap_exclude_type(bitmap_git, tip_objects, to_filter,
+                                  OBJ_TREE);
+       filter_bitmap_exclude_type(bitmap_git, tip_objects, to_filter,
+                                  OBJ_BLOB);
+}
+
 static int filter_bitmap(struct bitmap_index *bitmap_git,
                         struct object_list *tip_objects,
                         struct bitmap *to_filter,
@@ -890,6 +904,15 @@ static int filter_bitmap(struct bitmap_index *bitmap_git,
                return 0;
        }
 
+       if (filter->choice == LOFC_TREE_DEPTH &&
+           filter->tree_exclude_depth == 0) {
+               if (bitmap_git)
+                       filter_bitmap_tree_depth(bitmap_git, tip_objects,
+                                                to_filter,
+                                                filter->tree_exclude_depth);
+               return 0;
+       }
+
        /* filter choice not handled */
        return -1;
 }
index 80c53edca7af46556e50aa64c0fdfb912cae6a70..75ccf9f4e3b8f1c7d87455e7c583a093b0ce6f19 100755 (executable)
@@ -53,6 +53,11 @@ test_perf 'rev-list count with blob:limit=1k' '
                --filter=blob:limit=1k >/dev/null
 '
 
+test_perf 'rev-list count with tree:0' '
+       git rev-list --use-bitmap-index --count --objects --all \
+               --filter=tree:0 >/dev/null
+'
+
 test_perf 'simulated partial clone' '
        git pack-objects --stdout --all --filter=blob:none </dev/null >/dev/null
 '
index 145603f124574cb209155dd643fdc555685a79fa..2b551e6fd0ce1d6706334eaa2a65cda7f9e56618 100755 (executable)
@@ -53,4 +53,25 @@ test_expect_success 'blob:limit filter with specified blob' '
        test_bitmap_traversal expect actual
 '
 
+test_expect_success 'tree:0 filter' '
+       git rev-list --objects --filter=tree:0 HEAD >expect &&
+       git rev-list --use-bitmap-index \
+                    --objects --filter=tree:0 HEAD >actual &&
+       test_bitmap_traversal expect actual
+'
+
+test_expect_success 'tree:0 filter with specified blob, tree' '
+       git rev-list --objects --filter=tree:0 HEAD HEAD:two.t >expect &&
+       git rev-list --use-bitmap-index \
+                    --objects --filter=tree:0 HEAD HEAD:two.t >actual &&
+       test_bitmap_traversal expect actual
+'
+
+test_expect_success 'tree:1 filter' '
+       git rev-list --objects --filter=tree:1 HEAD >expect &&
+       git rev-list --use-bitmap-index \
+                    --objects --filter=tree:1 HEAD >actual &&
+       test_cmp expect actual
+'
+
 test_done