From 005f3fbe07a20dd5f7dea57f6f46cd797387e56a Mon Sep 17 00:00:00 2001 From: Adrian Ratiu Date: Mon, 2 Mar 2026 21:17:04 +0200 Subject: [PATCH] builtin/receive-pack: avoid spinning no-op sideband async threads Exit early if the hooks do not exist, to avoid spinning up/down sideband async threads which no-op. It is important to call the hook_exists() API provided by hook.[ch] because it covers both config-defined hooks and the "traditional" hooks from the hookdir. find_hook() only covers the hookdir hooks. The regression happened because the no-op async threads add some additional overhead which can be measured with the receive-refs test of the benchmarks suite [1]. Reproduced using: cd benchmarks/receive-refs && \ ./run --revisions /path/to/git \ fc148b146ad41be71a7852c4867f0773cbfe1ff9~,fc148b146ad41be71a7852c4867f0773cbfe1ff9 \ --parameter-list refformat reftable --parameter-list refcount 10000 1: https://gitlab.com/gitlab-org/data-access/git/benchmarks Fixes: fc148b146ad4 ("receive-pack: convert update hooks to new API") Reported-by: Patrick Steinhardt Helped-by: Jeff King Signed-off-by: Adrian Ratiu [jc: avoid duplicated hardcoded hook names] Signed-off-by: Junio C Hamano --- builtin/receive-pack.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index b5379a4895..e53aaf5104 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -914,6 +914,9 @@ static int run_receive_hook(struct command *commands, int saved_stderr = -1; int ret; + if (!hook_exists(the_repository, hook_name)) + return 0; + /* if there are no valid commands, don't invoke the hook at all. */ while (iter && skip_broken && (iter->error_string || iter->did_not_exist)) iter = iter->next; @@ -955,12 +958,16 @@ static int run_receive_hook(struct command *commands, static int run_update_hook(struct command *cmd) { + static const char hook_name[] = "update"; struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT; struct async sideband_async; int sideband_async_started = 0; int saved_stderr = -1; int code; + if (!hook_exists(the_repository, hook_name)) + return 0; + strvec_pushl(&opt.args, cmd->ref_name, oid_to_hex(&cmd->old_oid), @@ -969,7 +976,7 @@ static int run_update_hook(struct command *cmd) prepare_sideband_async(&sideband_async, &saved_stderr, &sideband_async_started); - code = run_hooks_opt(the_repository, "update", &opt); + code = run_hooks_opt(the_repository, hook_name, &opt); finish_sideband_async(&sideband_async, saved_stderr, sideband_async_started); @@ -1649,12 +1656,16 @@ out: static void run_update_post_hook(struct command *commands) { + static const char hook_name[] = "post-update"; struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT; struct async sideband_async; struct command *cmd; int sideband_async_started = 0; int saved_stderr = -1; + if (!hook_exists(the_repository, hook_name)) + return; + for (cmd = commands; cmd; cmd = cmd->next) { if (cmd->error_string || cmd->did_not_exist) continue; @@ -1665,7 +1676,7 @@ static void run_update_post_hook(struct command *commands) prepare_sideband_async(&sideband_async, &saved_stderr, &sideband_async_started); - run_hooks_opt(the_repository, "post-update", &opt); + run_hooks_opt(the_repository, hook_name, &opt); finish_sideband_async(&sideband_async, saved_stderr, sideband_async_started); }