From aad1d1c0d58f36d5cc7822c9ff6f0064708a1f20 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Tue, 6 Jan 2026 05:13:49 -0500 Subject: [PATCH 1/2] t/perf/perf-lib: fix assignment of TEST_OUTPUT_DIRECTORY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the perf suite's "run" helper in a vanilla build fails like this: $ make && (cd t/perf && ./run p0000-perf-lib-sanity.sh) === Running 1 tests in this tree === perf 1 - test_perf_default_repo works: 1 2 3 ok perf 2 - test_checkout_worktree works: 1 2 3 ok ok 3 - test_export works perf 4 - export a weird var: 1 2 3 ok perf 5 - éḿíẗ ńöń-ÁŚĆÍÍ ćḧáŕáćẗéŕś: 1 2 3 ok ok 6 - test_export works with weird vars perf 7 - important variables available in subshells: 1 2 3 ok perf 8 - test-lib-functions correctly loaded in subshells: 1 2 3 ok # passed all 8 test(s) 1..8 cannot open test-results/p0000-perf-lib-sanity.subtests: No such file or directory at ./aggregate.perl line 159. It is trying to aggregate results written into t/perf/test-results, but the p0000 script did not write anything there. The "run" script looks in $TEST_OUTPUT_DIRECTORY/test-results, or if that variable is not set, in test-results in the current working directory (which should be t/perf itself). It pulls the value of $TEST_OUTPUT_DIRECTORY from the GIT-BUILD-OPTIONS file. But that doesn't quite match the setup in perf-lib.sh (which is what scripts like p0000 use). There we do this at the top of the script: TEST_OUTPUT_DIRECTORY=$(pwd) and then let test-lib.sh append "/test-results" to that. Historically, that made the vanilla case work: we'd always use t/perf/test-results. But when $TEST_OUTPUT_DIRECTORY was set, it would break. Commit 5756ccd181 (t/perf: fix benchmarks with out-of-tree builds, 2025-04-28) fixed that second case by loading GIT-BUILD-OPTIONS ourselves. But that broke the vanilla case! Now our setting of $TEST_OUTPUT_DIRECTORY in perf-lib.sh is ignored, because it is overwritten by GIT-BUILD-OPTIONS. And when test-lib.sh sees that the output directory is empty, it defaults to t/test-results, rather than t/perf/test-results. Nobody seems to have noticed, probably for two reasons: 1. It only matters if you're trying to aggregate results (like the "run" script does). Just running "./p0000-perf-lib-sanity.sh" manually still produces useful output; the stored result files are just in an unexpected place. 2. There might be leftover files in t/perf/test-results from previous runs (before 5756ccd181). In particular, the ".subtests" files don't tend to change, and the lack of that file is what causes it to barf completely. So it's possible that the aggregation could have been showing stale results that did not match the run that just happened. We can fix it by setting TEST_OUTPUT_DIRECTORY only after we've loaded GIT-BUILD-OPTIONS, so that we override its value and not the other way around. And we'll do so only when the variable is not set, which should retain the fix for that case from 5756ccd181. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- t/perf/perf-lib.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh index b15c74d6f1..2ac007888e 100644 --- a/t/perf/perf-lib.sh +++ b/t/perf/perf-lib.sh @@ -20,7 +20,7 @@ # These variables must be set before the inclusion of test-lib.sh below, # because it will change our working directory. TEST_DIRECTORY=$(pwd)/.. -TEST_OUTPUT_DIRECTORY=$(pwd) +perf_dir=$(pwd) TEST_NO_CREATE_REPO=t TEST_NO_MALLOC_CHECK=t @@ -58,6 +58,7 @@ then fi . "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS +: ${TEST_OUTPUT_DIRECTORY:=$perf_dir} . "$GIT_SOURCE_DIR"/t/test-lib.sh # Then restore GIT_PERF_* settings. From 79d301c7676e79a09e7a1c65ca754132e1770828 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Tue, 6 Jan 2026 05:16:04 -0500 Subject: [PATCH 2/2] t/perf/run: preserve GIT_PERF_* from environment If you run: GIT_PERF_LARGE_REPO=/some/path ./p1006-cat-file.sh it will use the repo in /some/path. But if you use the "run" helper script to aggregate and compare results, like this: GIT_PERF_LARGE_REPO=/some/path ./run HEAD^ HEAD p1006-cat-file.sh it will ignore that variable. This is because the presence of the LARGE_REPO variable in GIT-BUILD-OPTIONS overrides what's in the environment. This started with 4638e8806e (Makefile: use common template for GIT-BUILD-OPTIONS, 2024-12-06), which now writes even empty variables (though arguably it was wrong even before with a non-empty value, as we generally prefer the environment to take precedence over on-disk config). We had the same problem in perf-lib.sh itself, and we hacked around it with 32b74b9809 (perf: do allow `GIT_PERF_*` to be overridden again, 2025-04-04). That's what lets the direct invocation of "./p1006" work above. And in fact that was sufficient for "./run", too, until it started loading GIT-BUILD-OPTIONS itself in 5756ccd181 (t/perf: fix benchmarks with out-of-tree builds, 2025-04-28). Now it has the same problem: it clobbers any incoming GIT_PERF options from the environment. We can use the same hack here in the "run" script. It's quite ugly, but it's just short enough that I don't think it's worth trying to factor it out into a common shell library. In the long run, we might consider teaching GIT-BUILD-OPTIONS to be more gentle in overwriting existing entries. There are probably other GIT_TEST_* variables which would need the same treatment. And if and when we come up with a more complete solution, we can use it in both spots. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- t/perf/run | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/t/perf/run b/t/perf/run index 073bcb2aff..13913db4a3 100755 --- a/t/perf/run +++ b/t/perf/run @@ -204,8 +204,18 @@ run_subsection () { get_var_from_env_or_config "GIT_PERF_CODESPEED_OUTPUT" "perf" "codespeedOutput" "--bool" get_var_from_env_or_config "GIT_PERF_SEND_TO_CODESPEED" "perf" "sendToCodespeed" +# Preserve GIT_PERF settings from the environment when loading +# GIT-BUILD-OPTIONS; see the similar hack in perf-lib.sh. +git_perf_settings="$(env | + sed -n "/^GIT_PERF_/{ + # escape all single-quotes in the value + s/'/'\\\\''/g + # turn this into an eval-able assignment + s/^\\([^=]*=\\)\\(.*\\)/\\1'\\2'/p + }")" cd "$(dirname $0)" . ../../GIT-BUILD-OPTIONS +eval "$git_perf_settings" if test -n "$TEST_OUTPUT_DIRECTORY" then