mirror of
https://github.com/git/git.git
synced 2026-06-19 15:39:47 +02:00
Merge branch 'tb/pack-path-walk-bitmap-delta-islands' into seen
The pack-objects command now supports using reachability bitmaps and delta-islands concurrently with the `--path-walk` option, allowing faster packaging by falling back to path-walk when bitmaps cannot fully satisfy the request. * tb/pack-path-walk-bitmap-delta-islands: SQUASH??? pack-objects: support `--delta-islands` with `--path-walk` pack-objects: extract `record_tree_depth()` helper pack-objects: support reachability bitmaps with `--path-walk` t/perf: drop p5311's lookup-table permutation
This commit is contained in:
@@ -402,11 +402,13 @@ will be automatically changed to version `1`.
|
||||
of filenames that cause collisions in Git's default name-hash
|
||||
algorithm.
|
||||
+
|
||||
Incompatible with `--delta-islands`. The `--use-bitmap-index` option is
|
||||
ignored in the presence of `--path-walk`. The `--path-walk` option
|
||||
supports the `--filter=<spec>` forms `blob:none`, `blob:limit=<n>`,
|
||||
`tree:0`, `object:type=<type>`, and `sparse:<oid>`. These supported filter
|
||||
types can be combined with the `combine:<spec>+<spec>` form.
|
||||
When `--use-bitmap-index` is specified with `--path-walk`, a successful
|
||||
bitmap traversal is used for object enumeration, with path-walk
|
||||
remaining as the fallback traversal when the bitmap cannot satisfy the
|
||||
request. The `--path-walk` option supports the `--filter=<spec>` forms
|
||||
`blob:none`, `blob:limit=<n>`, `tree:0`, `object:type=<type>`, and
|
||||
`sparse:<oid>`. These supported filter types can be combined with the
|
||||
`combine:<spec>+<spec>` form.
|
||||
|
||||
|
||||
DELTA ISLANDS
|
||||
|
||||
+50
-18
@@ -2744,6 +2744,22 @@ static inline void oe_set_tree_depth(struct packing_data *pack,
|
||||
pack->tree_depth[e - pack->objects] = tree_depth;
|
||||
}
|
||||
|
||||
static void record_tree_depth(const struct object_id *oid, const char *name)
|
||||
{
|
||||
const char *p;
|
||||
unsigned depth;
|
||||
struct object_entry *ent;
|
||||
|
||||
/* the empty string is a root tree, which is depth 0 */
|
||||
depth = *name ? 1 : 0;
|
||||
for (p = strchr(name, '/'); p; p = strchr(p + 1, '/'))
|
||||
depth++;
|
||||
|
||||
ent = packlist_find(&to_pack, oid);
|
||||
if (ent && depth > oe_tree_depth(&to_pack, ent))
|
||||
oe_set_tree_depth(&to_pack, ent, depth);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the size of the object without doing any delta
|
||||
* reconstruction (so non-deltas are true object sizes, but deltas
|
||||
@@ -4406,20 +4422,8 @@ static void show_object(struct object *obj, const char *name,
|
||||
add_preferred_base_object(name);
|
||||
add_object_entry(&obj->oid, obj->type, name, 0);
|
||||
|
||||
if (use_delta_islands) {
|
||||
const char *p;
|
||||
unsigned depth;
|
||||
struct object_entry *ent;
|
||||
|
||||
/* the empty string is a root tree, which is depth 0 */
|
||||
depth = *name ? 1 : 0;
|
||||
for (p = strchr(name, '/'); p; p = strchr(p + 1, '/'))
|
||||
depth++;
|
||||
|
||||
ent = packlist_find(&to_pack, &obj->oid);
|
||||
if (ent && depth > oe_tree_depth(&to_pack, ent))
|
||||
oe_set_tree_depth(&to_pack, ent, depth);
|
||||
}
|
||||
if (use_delta_islands)
|
||||
record_tree_depth(&obj->oid, name);
|
||||
}
|
||||
|
||||
static void show_object__ma_allow_any(struct object *obj, const char *name, void *data)
|
||||
@@ -4763,6 +4767,31 @@ static int add_objects_by_path(const char *path,
|
||||
continue;
|
||||
|
||||
add_object_entry(oid, type, path, exclude);
|
||||
|
||||
if (type == OBJ_COMMIT) {
|
||||
struct commit *commit;
|
||||
|
||||
if (!write_bitmap_index && !use_delta_islands)
|
||||
continue;
|
||||
|
||||
commit = lookup_commit(the_repository, oid);
|
||||
if (!commit)
|
||||
die(_("could not find commit %s"), oid_to_hex(oid));
|
||||
if (write_bitmap_index)
|
||||
index_commit_for_bitmap(commit);
|
||||
/*
|
||||
* Skip island propagation for boundary commits.
|
||||
* The regular traversal's show_commit() is only
|
||||
* called for interesting commits; matching that
|
||||
* here keeps path-walk from doing extra work that
|
||||
* would only be a no-op anyway (boundary commits
|
||||
* are not in island_marks).
|
||||
*/
|
||||
if (use_delta_islands && !exclude)
|
||||
propagate_island_marks(the_repository, commit);
|
||||
} else if (type == OBJ_TREE && use_delta_islands) {
|
||||
record_tree_depth(oid, path);
|
||||
}
|
||||
}
|
||||
|
||||
oe_end = to_pack.nr_objects;
|
||||
@@ -4795,6 +4824,13 @@ static int get_object_list_path_walk(struct rev_info *revs)
|
||||
info.path_fn = add_objects_by_path;
|
||||
info.path_fn_data = &processed;
|
||||
|
||||
/*
|
||||
* Path-walk needs boundary commits to discover thin-pack bases, but
|
||||
* bitmap traversal does not understand the boundary state. Set it
|
||||
* here so any prior bitmap attempt sees the usual non-boundary walk.
|
||||
*/
|
||||
revs->boundary = 1;
|
||||
|
||||
/*
|
||||
* Allow the --[no-]sparse option to be interesting here, if only
|
||||
* for testing purposes. Paths with no interesting objects will not
|
||||
@@ -5218,8 +5254,6 @@ int cmd_pack_objects(int argc,
|
||||
const char *option = NULL;
|
||||
if (!path_walk_filter_compatible(&filter_options))
|
||||
option = "--filter";
|
||||
else if (use_delta_islands)
|
||||
option = "--delta-islands";
|
||||
|
||||
if (option) {
|
||||
warning(_("cannot use %s with %s"),
|
||||
@@ -5228,9 +5262,7 @@ int cmd_pack_objects(int argc,
|
||||
}
|
||||
}
|
||||
if (path_walk) {
|
||||
strvec_push(&rp, "--boundary");
|
||||
strvec_push(&rp, "--objects");
|
||||
use_bitmap_index = 0;
|
||||
} else if (thin) {
|
||||
use_internal_rev_list = 1;
|
||||
strvec_push(&rp, shallow
|
||||
|
||||
@@ -4,16 +4,18 @@ test_description='performance of fetches from bitmapped packs'
|
||||
. ./perf-lib.sh
|
||||
|
||||
test_fetch_bitmaps () {
|
||||
argv=$1
|
||||
export argv
|
||||
|
||||
test_expect_success 'setup test directory' '
|
||||
rm -fr * .git
|
||||
'
|
||||
|
||||
test_perf_default_repo
|
||||
|
||||
test_expect_success 'create bitmapped server repo' '
|
||||
test_expect_success "create bitmapped server repo ${argv:+($argv)}" '
|
||||
git config pack.writebitmaps true &&
|
||||
git config pack.writeBitmapLookupTable '"$1"' &&
|
||||
git repack -ad
|
||||
git repack -ad $argv
|
||||
'
|
||||
|
||||
# simulate a fetch from a repository that last fetched N days ago, for
|
||||
@@ -21,7 +23,7 @@ test_fetch_bitmaps () {
|
||||
# and assume the first entry in the chain that is N days older than the current
|
||||
# HEAD is where the HEAD would have been then.
|
||||
for days in 1 2 4 8 16 32 64 128; do
|
||||
title=$(printf '%10s' "($days days)")
|
||||
title=$(printf '%10s' "($days days${argv:+, $argv})")
|
||||
test_expect_success "setup revs from $days days ago" '
|
||||
now=$(git log -1 --format=%ct HEAD) &&
|
||||
then=$(($now - ($days * 86400))) &&
|
||||
@@ -32,7 +34,7 @@ test_fetch_bitmaps () {
|
||||
} >revs
|
||||
'
|
||||
|
||||
test_perf "server $title (lookup=$1)" '
|
||||
test_perf "server $title" '
|
||||
git pack-objects --stdout --revs \
|
||||
--thin --delta-base-offset \
|
||||
<revs >tmp.pack
|
||||
@@ -42,13 +44,15 @@ test_fetch_bitmaps () {
|
||||
test_file_size tmp.pack
|
||||
'
|
||||
|
||||
test_perf "client $title (lookup=$1)" '
|
||||
test_perf "client $title" '
|
||||
git index-pack --stdin --fix-thin <tmp.pack
|
||||
'
|
||||
done
|
||||
}
|
||||
|
||||
test_fetch_bitmaps true
|
||||
test_fetch_bitmaps false
|
||||
for argv in '' --path-walk
|
||||
do
|
||||
test_fetch_bitmaps $argv || return 1
|
||||
done
|
||||
|
||||
test_done
|
||||
|
||||
@@ -577,6 +577,42 @@ test_bitmap_cases
|
||||
|
||||
sane_unset GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL
|
||||
|
||||
test_expect_success 'path-walk repack can write and use bitmap indexes' '
|
||||
test_when_finished "rm -rf path-walk-bitmap" &&
|
||||
git init path-walk-bitmap &&
|
||||
(
|
||||
cd path-walk-bitmap &&
|
||||
test_commit first &&
|
||||
test_commit second &&
|
||||
test_commit third &&
|
||||
|
||||
git repack -a -d -b --path-walk &&
|
||||
git rev-list --test-bitmap --use-bitmap-index HEAD &&
|
||||
|
||||
git rev-parse HEAD >in &&
|
||||
|
||||
git rev-list --objects --no-object-names HEAD >expect.raw &&
|
||||
sort expect.raw >expect &&
|
||||
|
||||
for reuse in true false
|
||||
do
|
||||
: >trace.txt &&
|
||||
|
||||
GIT_TRACE2_EVENT="$(pwd)/trace.txt" \
|
||||
git -c pack.allowPackReuse=$reuse pack-objects \
|
||||
--stdout --revs --path-walk --use-bitmap-index \
|
||||
<in >out.pack &&
|
||||
test_grep "\"category\":\"bitmap\",\"key\":\"bitmap/hits\"" trace.txt &&
|
||||
|
||||
git index-pack out.pack &&
|
||||
|
||||
list_packed_objects out.idx >actual.raw &&
|
||||
sort actual.raw >actual &&
|
||||
test_cmp expect actual || return 1
|
||||
done
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'incremental repack fails when bitmaps are requested' '
|
||||
test_commit more-1 &&
|
||||
test_must_fail git repack -d 2>err &&
|
||||
|
||||
@@ -53,6 +53,35 @@ test_expect_success 'separate islands disallows delta' '
|
||||
! is_delta_base $two $one
|
||||
'
|
||||
|
||||
test_expect_success 'path-walk island repack respects islands' '
|
||||
GIT_TRACE2_EVENT="$(pwd)/trace.path-walk-islands" \
|
||||
git -c "pack.island=refs/heads/(.*)" repack -adfi \
|
||||
--path-walk 2>err &&
|
||||
test_region pack-objects path-walk trace.path-walk-islands &&
|
||||
test_grep ! "cannot use --delta-islands with --path-walk" err &&
|
||||
! is_delta_base $one $two &&
|
||||
! is_delta_base $two $one
|
||||
'
|
||||
|
||||
test_expect_success 'path-walk island bitmap repack respects islands' '
|
||||
GIT_TRACE2_EVENT="$(pwd)/trace.path-walk-island-bitmap" \
|
||||
git -c "pack.island=refs/heads/(.*)" repack -a -d -f -i -b \
|
||||
--path-walk 2>err &&
|
||||
test_region pack-objects path-walk trace.path-walk-island-bitmap &&
|
||||
test_path_is_file .git/objects/pack/*.bitmap &&
|
||||
git rev-list --test-bitmap --use-bitmap-index one &&
|
||||
test_grep ! "cannot use --delta-islands with --path-walk" err &&
|
||||
! is_delta_base $one $two &&
|
||||
! is_delta_base $two $one
|
||||
'
|
||||
|
||||
test_expect_success 'path-walk same island allows delta' '
|
||||
GIT_TRACE2_EVENT="$(pwd)/trace.path-walk-same-island" \
|
||||
git -c "pack.island=refs/heads" repack -adfi --path-walk &&
|
||||
test_region pack-objects path-walk trace.path-walk-same-island &&
|
||||
is_delta_base $one $two
|
||||
'
|
||||
|
||||
test_expect_success 'same island allows delta' '
|
||||
git -c "pack.island=refs/heads" repack -adfi &&
|
||||
is_delta_base $one $two
|
||||
|
||||
Reference in New Issue
Block a user