{"thread":{"id":"63251","subject":"[PATCH] perf: do allow `GIT_PERF_*` to be overridden again","startedAt":"2025-04-04T10:56:10Z","lastAt":"2025-04-22T15:37:05Z","messageCount":6,"participants":["Johannes Schindelin via GitGitGadget","Derrick Stolee","Jeff King","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"515653","messageId":"pull.1900.git.1743764167548.gitgitgadget@gmail.com","threadId":"63251","inReplyTo":null,"subject":"[PATCH] perf: do allow `GIT_PERF_*` to be overridden again","fromName":"Johannes Schindelin via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-04-04T10:56:07Z","receivedAt":"2025-04-04T10:56:10Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"From: Johannes Schindelin <johannes.schindelin@gmx.de>\n\nA common way to run Git's performance benchmarks on repositories other\nthan Git's own repository (which is not exactly large when compared to\nactually large repositories) is to run them like this:\n\n\tGIT_PERF_LARGE_REPO=/path/to/my/large/repo \\\n\t./p1234-*.sh -ivx\n\nContrary to developers' common expectations, this failed to work when\nGit was built with a different `GIT_PERF_LARGE_REPO` value specified at\nbuild time: That build-time option would have been written to the\n`GIT-BUILD-OPTIONS` file, which in turn would have been sourced by\n`test-lib.sh`, which in turn would have been sourced by `perf-lib.sh`,\nwhich in turn would have been sourced by the perf test script,\n_overriding_ the environment variable specified in the way illustrated\nabove.\n\nSince perf tests are not run as part of the build, this most likely\nunintended behavior was not caught and certainly not fixed, as the\n`GIT_PERF_*` values would have been empty at build-time.\n\nHowever, in 4638e8806e3a (Makefile: use common template for\nGIT-BUILD-OPTIONS, 2024-12-06), a subtle change of behavior was\nintroduced: Whereas before, a couple of build-time options (the\n`GIT_PERF_*` ones included) were written to `GIT-BUILD-OPTIONS` only\nwhen their values were non-empty. With this commit, they are also\nwritten when they are empty.\n\nThe consequence is that above-mentioned way to run the perf tests will\nnot only fail to pick up the desired `GIT_PERF_*` settings when they\nwere specified differently while building Git, instead the desired\nsettings will be only respected when specified _while building_ Git.\n\nLet's work around the original issue, i.e. let `GIT_PERF_*` environment\nvariables override what is recorded in `GIT-BUILD-OPTIONS`.\n\nNote that this is just the tip of the iceberg, there are a couple of\n`GIT_TEST_*` options that may want a similar fix in `test-lib.sh`. Due\nto time constraints on my side, this here patch focuses exclusively on\nthe `GIT_PERF_*` settings.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n    perf: do allow GIT_PERF_* to be overridden again\n    \n    This issue was noticed when working on large-scale issues.\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1900%2Fdscho%2Fsupport-ad-hoc-git-perf-settings-again-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1900/dscho/support-ad-hoc-git-perf-settings-again-v1\nPull-Request: https://github.com/gitgitgadget/git/pull/1900\n\n t/perf/perf-lib.sh | 12 ++++++++++++\n 1 file changed, 12 insertions(+)\n\ndiff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh\nindex 8ab6d9c4694..39c37284452 100644\n--- a/t/perf/perf-lib.sh\n+++ b/t/perf/perf-lib.sh\n@@ -25,7 +25,19 @@ TEST_OUTPUT_DIRECTORY=$(pwd)\n TEST_NO_CREATE_REPO=t\n TEST_NO_MALLOC_CHECK=t\n \n+# GIT-BUILD-OPTIONS, sourced by test-lib.sh, overwrites the `GIT_PERF_*`\n+# values that are set by the user (if any). Let's stash them away as\n+# `eval`-able assignments.\n+git_perf_settings=\"$(env |\n+\tsed -n \"/^GIT_PERF_/{\n+\t\t# escape all single-quotes in the value\n+\t\ts/'/'\\\\\\\\''/g\n+\t\t# turn this into an eval-able assignment\n+\t\ts/^\\\\([^=]*=\\\\)\\\\(.*\\\\)/\\\\1'\\\\2'/p\n+\t}\")\"\n+\n . ../test-lib.sh\n+eval \"$git_perf_settings\"\n \n unset GIT_CONFIG_NOSYSTEM\n GIT_CONFIG_SYSTEM=\"$TEST_DIRECTORY/perf/config\"\n\nbase-commit: 683c54c999c301c2cd6f715c411407c413b1d84e\n-- \ngitgitgadget\n"},{"id":"515664","messageId":"3bc8a906-ead6-4cce-9658-d45feb76cebf@gmail.com","threadId":"63251","inReplyTo":"pull.1900.git.1743764167548.gitgitgadget@gmail.com","subject":"Re: [PATCH] perf: do allow `GIT_PERF_*` to be overridden again","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2025-04-04T12:13:15Z","receivedAt":"2025-04-04T12:13:17Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 4/4/2025 6:56 AM, Johannes Schindelin via GitGitGadget wrote:\n> From: Johannes Schindelin <johannes.schindelin@gmx.de>\n> \n> A common way to run Git's performance benchmarks on repositories other\n> than Git's own repository (which is not exactly large when compared to\n> actually large repositories) is to run them like this:\n> \n> \tGIT_PERF_LARGE_REPO=/path/to/my/large/repo \\\n> \t./p1234-*.sh -ivx\n> \n\nThis issue also extends to other necessary variables such as\nGIT_PERF_REPEAT_COUNT.  \n> +# GIT-BUILD-OPTIONS, sourced by test-lib.sh, overwrites the `GIT_PERF_*`\n> +# values that are set by the user (if any). Let's stash them away as\n> +# `eval`-able assignments.\n> +git_perf_settings=\"$(env |\n> +\tsed -n \"/^GIT_PERF_/{\n> +\t\t# escape all single-quotes in the value\n> +\t\ts/'/'\\\\\\\\''/g\n> +\t\t# turn this into an eval-able assignment\n> +\t\ts/^\\\\([^=]*=\\\\)\\\\(.*\\\\)/\\\\1'\\\\2'/p\n> +\t}\")\"\n> +\n>  . ../test-lib.sh\n> +eval \"$git_perf_settings\"\nI verified this fix in my local environment. Thanks so much for digging\nin and finding the solution here!\n\n-Stolee\n\n"},{"id":"516389","messageId":"20250419035407.GA93039@coredump.intra.peff.net","threadId":"63251","inReplyTo":"pull.1900.git.1743764167548.gitgitgadget@gmail.com","subject":"Re: [PATCH] perf: do allow `GIT_PERF_*` to be overridden again","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2025-04-19T03:54:07Z","receivedAt":"2025-04-19T03:54:09Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Apr 04, 2025 at 10:56:07AM +0000, Johannes Schindelin via GitGitGadget wrote:\n\n> However, in 4638e8806e3a (Makefile: use common template for\n> GIT-BUILD-OPTIONS, 2024-12-06), a subtle change of behavior was\n> introduced: Whereas before, a couple of build-time options (the\n> `GIT_PERF_*` ones included) were written to `GIT-BUILD-OPTIONS` only\n> when their values were non-empty. With this commit, they are also\n> written when they are empty.\n\nIt doesn't look like Junio picked this up, so I wanted to chime in that\nthis regression bit me today, too (specifically for GIT_PERF_LARGE_REPO,\nbut also another variable which I'll detail in a moment).\n\nThis is also the same issue that hit the interop suite discussed in:\n\n  https://lore.kernel.org/git/Z8IX2bMJe+V80idE@nand.local/\n\n(there I was a bit dismissive of it, because I think GIT_*_MAKE_OPTS\nwould usually be set at build time, but for these other variables,\nthey're almost always going to come from the environment).\n\n> Let's work around the original issue, i.e. let `GIT_PERF_*` environment\n> variables override what is recorded in `GIT-BUILD-OPTIONS`.\n\nI like this direction. It not only fixes the regression, but makes\nthings generally behave more as I'd expect them to.\n\nI think it doesn't quite fix everything, though. I noticed that\nGIT_PERF_REPEAT_COUNT no longer correctly defaults to \"3\" when using the\n\"run\" script. And there are two problems here:\n\n  1. The \"run\" script itself sources GIT-BUILD-OPTIONS, so it would need\n     similar treatment.\n\n  2. But even if we did, that, in my case I am not setting\n     PERF_REPEAT_COUNT at all. So there is no local env variable that\n     we'd use to take precedence. The problem is in the way the \"run\"\n     script assigns defaults. If it sees an environment variable set\n     (whether actually from the environment or from GIT-BUILD-OPTIONS)\n     it accepts it as-is, rather than installing its fallback. So it\n     will never use its default of \"3\", and instead retain the blank\n     string (which, by a stroke of luck, does still cause it to run each\n     trial at least once).\n\nSo I think we either need to rewrite the \"run\" script's fallback code,\nor teach the GIT-BUILD-OPTIONS writer to avoid mentioning unset\nvariables (which is the real source of the problem in 4638e8806e3a).\n\nSo...\n\n> Note that this is just the tip of the iceberg, there are a couple of\n> `GIT_TEST_*` options that may want a similar fix in `test-lib.sh`. Due\n> to time constraints on my side, this here patch focuses exclusively on\n> the `GIT_PERF_*` settings.\n\n...yes, this is definitely the tip of the iceberg. I don't mind doing\nthis patch as an incremental step forward (and because it is an\nimprovement in behavior even if 4638e8806e3a were reverted). But the\nissue is far from solved overall.\n\n> +# GIT-BUILD-OPTIONS, sourced by test-lib.sh, overwrites the `GIT_PERF_*`\n> +# values that are set by the user (if any). Let's stash them away as\n> +# `eval`-able assignments.\n> +git_perf_settings=\"$(env |\n> +\tsed -n \"/^GIT_PERF_/{\n> +\t\t# escape all single-quotes in the value\n> +\t\ts/'/'\\\\\\\\''/g\n> +\t\t# turn this into an eval-able assignment\n> +\t\ts/^\\\\([^=]*=\\\\)\\\\(.*\\\\)/\\\\1'\\\\2'/p\n> +\t}\")\"\n\nThe implementation here looks correct to me, including the quoting. The\nnumber of backslashes is a bit vomit-inducing, but I think unavoidable\n(we could put the sed command into single-quotes, but then you'd have to\nescape out of it to show the single-quotes you do need to mention).\n\n-Peff\n"},{"id":"516415","messageId":"xmqqfri28rlp.fsf@gitster.g","threadId":"63251","inReplyTo":"20250419035407.GA93039@coredump.intra.peff.net","subject":"Re: [PATCH] perf: do allow `GIT_PERF_*` to be overridden again","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-04-20T21:12:34Z","receivedAt":"2025-04-20T21:12:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Fri, Apr 04, 2025 at 10:56:07AM +0000, Johannes Schindelin via GitGitGadget wrote:\n>\n>> However, in 4638e8806e3a (Makefile: use common template for\n>> GIT-BUILD-OPTIONS, 2024-12-06), a subtle change of behavior was\n>> introduced: Whereas before, a couple of build-time options (the\n>> `GIT_PERF_*` ones included) were written to `GIT-BUILD-OPTIONS` only\n>> when their values were non-empty. With this commit, they are also\n>> written when they are empty.\n>\n> It doesn't look like Junio picked this up, so I wanted to chime in that\n> this regression bit me today, too (specifically for GIT_PERF_LARGE_REPO,\n> but also another variable which I'll detail in a moment).\n\nThis was lost in the cracks.  Thanks for bringing it back to our\nattention.  I think what happened was that I saw whack-a-mole aspect\nof the root cause, which makes this \"the tip of the iceberg\", and\nfelt it was more sensible to wait before a real solution, like ...\n\n> So I think we either need to rewrite the \"run\" script's fallback code,\n> or teach the GIT-BUILD-OPTIONS writer to avoid mentioning unset\n> variables (which is the real source of the problem in 4638e8806e3a).\n\n... this was raised.  And then I completely forgot about the topic,\nas nothing happened since then.\n\n> ...yes, this is definitely the tip of the iceberg. I don't mind doing\n> this patch as an incremental step forward (and because it is an\n> improvement in behavior even if 4638e8806e3a were reverted). But the\n> issue is far from solved overall.\n\nI do not mind it as an incremental band-aid.\n\nThanks, all.\n"},{"id":"516489","messageId":"20250422104125.GA1460472@coredump.intra.peff.net","threadId":"63251","inReplyTo":"xmqqfri28rlp.fsf@gitster.g","subject":"Re: [PATCH] perf: do allow `GIT_PERF_*` to be overridden again","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2025-04-22T10:41:25Z","receivedAt":"2025-04-22T10:41:32Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Apr 20, 2025 at 02:12:34PM -0700, Junio C Hamano wrote:\n\n> > So I think we either need to rewrite the \"run\" script's fallback code,\n> > or teach the GIT-BUILD-OPTIONS writer to avoid mentioning unset\n> > variables (which is the real source of the problem in 4638e8806e3a).\n> \n> ... this was raised.  And then I completely forgot about the topic,\n> as nothing happened since then.\n> \n> > ...yes, this is definitely the tip of the iceberg. I don't mind doing\n> > this patch as an incremental step forward (and because it is an\n> > improvement in behavior even if 4638e8806e3a were reverted). But the\n> > issue is far from solved overall.\n> \n> I do not mind it as an incremental band-aid.\n\nLooks like this is in 'jch' now, but there's a mis-merge in e8cf2b99cd\n(Merge branch 'ps/meson-build-perf-bench' into jch, 2025-04-21).\n\nThe original patch in this thread did something like:\n\n  git_perf_settings=$(...pull GIT_PERF_* from env...)\n   . ../test-lib.sh\n  eval \"$git_perf_settings\"\n\nThat is, we stash away the environment, then load test-lib.sh, which\noverwrites the environment, and then we restore (some of) the original\nvalues.\n\nIn that merge, the test-lib.sh inclusion is moved (and in fact is now\naccompanied by an explicit inclusion of GIT-BUILD-OPTIONS), and we now\nhave:\n\n   . \"$GIT_BUILD_DIR\"/GIT-BUILD-OPTIONS\n   . \"$GIT_SOURCE_DIR\"/t/test-lib.sh\n   git_perf_settings=$(...)\n   eval \"$git_perf_settings\"\n\nWhich of course does nothing. We need to set $git_perf_settings before\nthose other source lines (and the eval must remain after them).\n\n-Peff\n"},{"id":"516511","messageId":"xmqqzfg8438h.fsf@gitster.g","threadId":"63251","inReplyTo":"20250422104125.GA1460472@coredump.intra.peff.net","subject":"Re: [PATCH] perf: do allow `GIT_PERF_*` to be overridden again","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-04-22T15:37:02Z","receivedAt":"2025-04-22T15:37:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> The original patch in this thread did something like:\n>\n>   git_perf_settings=$(...pull GIT_PERF_* from env...)\n>    . ../test-lib.sh\n>   eval \"$git_perf_settings\"\n>\n> That is, we stash away the environment, then load test-lib.sh, which\n> overwrites the environment, and then we restore (some of) the original\n> values.\n>\n> In that merge, the test-lib.sh inclusion is moved (and in fact is now\n> accompanied by an explicit inclusion of GIT-BUILD-OPTIONS), and we now\n> have:\n>\n>    . \"$GIT_BUILD_DIR\"/GIT-BUILD-OPTIONS\n>    . \"$GIT_SOURCE_DIR\"/t/test-lib.sh\n>    git_perf_settings=$(...)\n>    eval \"$git_perf_settings\"\n>\n> Which of course does nothing. We need to set $git_perf_settings before\n> those other source lines (and the eval must remain after them).\n\nRight.  Thanks.\n\n"}]}