Skip to content

Commit 94fcf0e

Browse files
vdyettaylorr
authored andcommitted
cache-tree: add perf test comparing update and prime
Add a performance test comparing the execution times of 'prime_cache_tree()' and 'cache_tree_update(_, WRITE_TREE_SILENT | WRITE_TREE_REPAIR)'. The goal of comparing these two is to identify which is the faster method for rebuilding an invalid cache tree, ultimately to remove one when both are (reundantly) called in immediate succession. Both methods are fast, so the new tests in 'p0090-cache-tree.sh' must call each tested function multiple times to ensure the reported times (to 0.01s resolution) convey the differences between them. The tests compare the timing of a 'test-tool cache-tree' run as a no-op (to capture a baseline for the overhead associated with running the tool), 'cache_tree_update()', and 'prime_cache_tree()' on four scenarios: - A completely valid cache tree - A cache tree with 2 invalid paths - A cache tree with 50 invalid paths - A completely empty cache tree Example results: Test this tree ----------------------------------------------------------- 0090.2: no-op, clean 1.27(0.48+0.52) 0090.3: prime_cache_tree, clean 2.02(0.83+0.85) 0090.4: cache_tree_update, clean 1.30(0.49+0.54) 0090.5: no-op, invalidate 2 1.29(0.48+0.54) 0090.6: prime_cache_tree, invalidate 2 1.98(0.81+0.83) 0090.7: cache_tree_update, invalidate 2 2.12(0.94+0.86) 0090.8: no-op, invalidate 50 1.32(0.50+0.55) 0090.9: prime_cache_tree, invalidate 50 2.10(0.86+0.89) 0090.10: cache_tree_update, invalidate 50 2.35(1.14+0.90) 0090.11: no-op, empty 1.33(0.50+0.54) 0090.12: prime_cache_tree, empty 2.04(0.84+0.87) 0090.13: cache_tree_update, empty 2.51(1.27+0.92) These timings show that, while 'cache_tree_update()' is faster when the cache tree is completely valid, it is equal to or slower than 'prime_cache_tree()' when there are any invalid paths. Since the redundant calls are mostly in scenarios where the cache tree will be at least partially invalid (e.g., 'git reset --hard'), 'prime_cache_tree()' will likely perform better than 'cache_tree_update()' in typical cases. Helped-by: SZEDER Gábor <[email protected]> Signed-off-by: Victoria Dye <[email protected]> Signed-off-by: Taylor Blau <[email protected]>
1 parent 319605f commit 94fcf0e

File tree

5 files changed

+103
-0
lines changed

5 files changed

+103
-0
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,7 @@ TEST_BUILTINS_OBJS += test-advise.o
723723
TEST_BUILTINS_OBJS += test-bitmap.o
724724
TEST_BUILTINS_OBJS += test-bloom.o
725725
TEST_BUILTINS_OBJS += test-bundle-uri.o
726+
TEST_BUILTINS_OBJS += test-cache-tree.o
726727
TEST_BUILTINS_OBJS += test-chmtime.o
727728
TEST_BUILTINS_OBJS += test-config.o
728729
TEST_BUILTINS_OBJS += test-crontab.o

t/helper/test-cache-tree.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#include "test-tool.h"
2+
#include "cache.h"
3+
#include "tree.h"
4+
#include "cache-tree.h"
5+
#include "parse-options.h"
6+
7+
static char const * const test_cache_tree_usage[] = {
8+
N_("test-tool cache-tree <options> (control|prime|update)"),
9+
NULL
10+
};
11+
12+
int cmd__cache_tree(int argc, const char **argv)
13+
{
14+
struct object_id oid;
15+
struct tree *tree;
16+
int empty = 0;
17+
int invalidate_qty = 0;
18+
int i;
19+
20+
struct option options[] = {
21+
OPT_BOOL(0, "empty", &empty,
22+
N_("clear the cache tree before each iteration")),
23+
OPT_INTEGER_F(0, "invalidate", &invalidate_qty,
24+
N_("number of entries in the cache tree to invalidate (default 0)"),
25+
PARSE_OPT_NONEG),
26+
OPT_END()
27+
};
28+
29+
setup_git_directory();
30+
31+
argc = parse_options(argc, argv, NULL, options, test_cache_tree_usage, 0);
32+
33+
if (read_cache() < 0)
34+
die(_("unable to read index file"));
35+
36+
oidcpy(&oid, &the_index.cache_tree->oid);
37+
tree = parse_tree_indirect(&oid);
38+
if (!tree)
39+
die(_("not a tree object: %s"), oid_to_hex(&oid));
40+
41+
if (empty) {
42+
/* clear the cache tree & allocate a new one */
43+
cache_tree_free(&the_index.cache_tree);
44+
the_index.cache_tree = cache_tree();
45+
} else if (invalidate_qty) {
46+
/* invalidate the specified number of unique paths */
47+
float f_interval = (float)the_index.cache_nr / invalidate_qty;
48+
int interval = f_interval < 1.0 ? 1 : (int)f_interval;
49+
for (i = 0; i < invalidate_qty && i * interval < the_index.cache_nr; i++)
50+
cache_tree_invalidate_path(&the_index, the_index.cache[i * interval]->name);
51+
}
52+
53+
if (argc != 1)
54+
usage_with_options(test_cache_tree_usage, options);
55+
else if (!strcmp(argv[0], "prime"))
56+
prime_cache_tree(the_repository, &the_index, tree);
57+
else if (!strcmp(argv[0], "update"))
58+
cache_tree_update(&the_index, WRITE_TREE_SILENT | WRITE_TREE_REPAIR);
59+
/* use "control" subcommand to specify no-op */
60+
else if (!!strcmp(argv[0], "control"))
61+
die(_("Unhandled subcommand '%s'"), argv[0]);
62+
63+
return 0;
64+
}

t/helper/test-tool.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ static struct test_cmd cmds[] = {
1414
{ "bitmap", cmd__bitmap },
1515
{ "bloom", cmd__bloom },
1616
{ "bundle-uri", cmd__bundle_uri },
17+
{ "cache-tree", cmd__cache_tree },
1718
{ "chmtime", cmd__chmtime },
1819
{ "config", cmd__config },
1920
{ "crontab", cmd__crontab },

t/helper/test-tool.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ int cmd__advise_if_enabled(int argc, const char **argv);
88
int cmd__bitmap(int argc, const char **argv);
99
int cmd__bloom(int argc, const char **argv);
1010
int cmd__bundle_uri(int argc, const char **argv);
11+
int cmd__cache_tree(int argc, const char **argv);
1112
int cmd__chmtime(int argc, const char **argv);
1213
int cmd__config(int argc, const char **argv);
1314
int cmd__crontab(int argc, const char **argv);

t/perf/p0090-cache-tree.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/sh
2+
3+
test_description="Tests performance of cache tree update operations"
4+
5+
. ./perf-lib.sh
6+
7+
test_perf_large_repo
8+
test_checkout_worktree
9+
10+
count=100
11+
12+
test_expect_success 'setup cache tree' '
13+
git write-tree
14+
'
15+
16+
test_cache_tree () {
17+
test_perf "$1, $3" "
18+
for i in \$(test_seq $count)
19+
do
20+
test-tool cache-tree $4 $2
21+
done
22+
"
23+
}
24+
25+
test_cache_tree_update_functions () {
26+
test_cache_tree 'no-op' 'control' "$1" "$2"
27+
test_cache_tree 'prime_cache_tree' 'prime' "$1" "$2"
28+
test_cache_tree 'cache_tree_update' 'update' "$1" "$2"
29+
}
30+
31+
test_cache_tree_update_functions "clean" ""
32+
test_cache_tree_update_functions "invalidate 2" "--invalidate 2"
33+
test_cache_tree_update_functions "invalidate 50" "--invalidate 50"
34+
test_cache_tree_update_functions "empty" "--empty"
35+
36+
test_done

0 commit comments

Comments
 (0)