Skip to content

Commit 66576c9

Browse files
derrickstoleedscho
authored andcommitted
repack: add --path-walk option
Since 'git pack-objects' supports a --path-walk option, allow passing it through in 'git repack'. This presents interesting testing opportunities for comparing the different repacking strategies against each other. Add the --path-walk option to the performance tests in p5313. For the microsoft/fluentui repo [1] checked out at a specific commit [2], the results are very interesting: Test this tree ------------------------------------------------------------------ 5313.2: thin pack 0.40(0.47+0.04) 5313.3: thin pack size 1.2M 5313.4: thin pack with --full-name-hash 0.09(0.10+0.04) 5313.5: thin pack size with --full-name-hash 22.8K 5313.6: thin pack with --path-walk 0.08(0.06+0.02) 5313.7: thin pack size with --path-walk 20.8K 5313.8: big pack 2.16(8.43+0.23) 5313.9: big pack size 17.7M 5313.10: big pack with --full-name-hash 1.42(3.06+0.21) 5313.11: big pack size with --full-name-hash 18.0M 5313.12: big pack with --path-walk 2.21(8.39+0.24) 5313.13: big pack size with --path-walk 17.8M 5313.14: repack 98.05(662.37+2.64) 5313.15: repack size 449.1K 5313.16: repack with --full-name-hash 33.95(129.44+2.63) 5313.17: repack size with --full-name-hash 182.9K 5313.18: repack with --path-walk 106.21(121.58+0.82) 5313.19: repack size with --path-walk 159.6K [1] https://github.com/microsoft/fluentui [2] e70848ebac1cd720875bccaa3026f4a9ed700e08 This repo suffers from having a lot of paths that collide in the name hash, so examining them in groups by path leads to better deltas. Also, in this case, the single-threaded implementation is competitive with the full repack. This is saving time diffing files that have significant differences from each other. A similar, but private, repo has even more extremes in the thin packs: Test this tree -------------------------------------------------------------- 5313.2: thin pack 2.39(2.91+0.10) 5313.3: thin pack size 4.5M 5313.4: thin pack with --full-name-hash 0.29(0.47+0.12) 5313.5: thin pack size with --full-name-hash 15.5K 5313.6: thin pack with --path-walk 0.35(0.31+0.04) 5313.7: thin pack size with --path-walk 14.2K Notice, however, that while the --full-name-hash version is working quite well in these cases for the thin pack, it does poorly for some other standard cases, such as this test on the Linux kernel repository: Test this tree -------------------------------------------------------------- 5313.2: thin pack 0.01(0.00+0.00) 5313.3: thin pack size 310 5313.4: thin pack with --full-name-hash 0.00(0.00+0.00) 5313.5: thin pack size with --full-name-hash 1.4K 5313.6: thin pack with --path-walk 0.00(0.00+0.00) 5313.7: thin pack size with --path-walk 310 Here, the --full-name-hash option does much worse than the default name hash, but the path-walk option does exactly as well. Signed-off-by: Derrick Stolee <[email protected]>
1 parent da42d88 commit 66576c9

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-2
lines changed

Documentation/git-repack.txt

+14-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ SYNOPSIS
1111
[verse]
1212
'git repack' [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]
1313
[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]
14-
[--write-midx] [--full-name-hash]
14+
[--write-midx] [--full-name-hash] [--path-walk]
1515

1616
DESCRIPTION
1717
-----------
@@ -251,6 +251,19 @@ linkgit:git-multi-pack-index[1]).
251251
Write a multi-pack index (see linkgit:git-multi-pack-index[1])
252252
containing the non-redundant packs.
253253

254+
--path-walk::
255+
This option passes the `--path-walk` option to the underlying
256+
`git pack-options` process (see linkgit:git-pack-objects[1]).
257+
By default, `git pack-objects` walks objects in an order that
258+
presents trees and blobs in an order unrelated to the path they
259+
appear relative to a commit's root tree. The `--path-walk` option
260+
enables a different walking algorithm that organizes trees and
261+
blobs by path. This has the potential to improve delta compression
262+
especially in the presence of filenames that cause collisions in
263+
Git's default name-hash algorithm. Due to changing how the objects
264+
are walked, this option is not compatible with `--delta-islands`
265+
or `--filter`.
266+
254267
CONFIGURATION
255268
-------------
256269

builtin/repack.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ static char *packdir, *packtmp_name, *packtmp;
4343
static const char *const git_repack_usage[] = {
4444
N_("git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n"
4545
"[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n"
46-
"[--write-midx] [--full-name-hash]"),
46+
"[--write-midx] [--full-name-hash] [--path-walk]"),
4747
NULL
4848
};
4949

@@ -63,6 +63,7 @@ struct pack_objects_args {
6363
int quiet;
6464
int local;
6565
int full_name_hash;
66+
int path_walk;
6667
struct list_objects_filter_options filter_options;
6768
};
6869

@@ -313,6 +314,8 @@ static void prepare_pack_objects(struct child_process *cmd,
313314
strvec_pushf(&cmd->args, "--no-reuse-object");
314315
if (args->full_name_hash)
315316
strvec_pushf(&cmd->args, "--full-name-hash");
317+
if (args->path_walk)
318+
strvec_pushf(&cmd->args, "--path-walk");
316319
if (args->local)
317320
strvec_push(&cmd->args, "--local");
318321
if (args->quiet)
@@ -1212,6 +1215,8 @@ int cmd_repack(int argc,
12121215
N_("pass --no-reuse-object to git-pack-objects")),
12131216
OPT_BOOL(0, "full-name-hash", &po_args.full_name_hash,
12141217
N_("(EXPERIMENTAL!) pass --full-name-hash to git-pack-objects")),
1218+
OPT_BOOL(0, "path-walk", &po_args.path_walk,
1219+
N_("(EXPERIMENTAL!) pass --path-walk to git-pack-objects")),
12151220
OPT_NEGBIT('n', NULL, &run_update_server_info,
12161221
N_("do not run git-update-server-info"), 1),
12171222
OPT__QUIET(&po_args.quiet, N_("be quiet")),

t/perf/p5313-pack-objects.sh

+24
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ test_size 'thin pack size with --full-name-hash' '
3636
test_file_size out
3737
'
3838

39+
test_perf 'thin pack with --path-walk' '
40+
git pack-objects --thin --stdout --revs --sparse --path-walk <in-thin >out
41+
'
42+
43+
test_size 'thin pack size with --path-walk' '
44+
wc -c <out
45+
'
46+
3947
test_perf 'big pack' '
4048
git pack-objects --stdout --revs --sparse <in-big >out
4149
'
@@ -52,6 +60,14 @@ test_size 'big pack size with --full-name-hash' '
5260
test_file_size out
5361
'
5462

63+
test_perf 'big pack with --path-walk' '
64+
git pack-objects --stdout --revs --sparse --path-walk <in-big >out
65+
'
66+
67+
test_size 'big pack size with --path-walk' '
68+
wc -c <out
69+
'
70+
5571
test_perf 'repack' '
5672
git repack -adf
5773
'
@@ -70,4 +86,12 @@ test_size 'repack size with --full-name-hash' '
7086
test_file_size "$pack"
7187
'
7288

89+
test_perf 'repack with --path-walk' '
90+
git repack -adf --path-walk
91+
'
92+
93+
test_size 'repack size with --path-walk' '
94+
wc -c <.git/objects/pack/pack-*.pack
95+
'
96+
7397
test_done

0 commit comments

Comments
 (0)