]> git.ipfire.org Git - thirdparty/git.git/commitdiff
builtin/receive-pack: avoid spinning no-op sideband async threads
authorAdrian Ratiu <adrian.ratiu@collabora.com>
Mon, 2 Mar 2026 19:17:04 +0000 (21:17 +0200)
committerJunio C Hamano <gitster@pobox.com>
Tue, 3 Mar 2026 00:00:43 +0000 (16:00 -0800)
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 <ps@pks.im>
Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
[jc: avoid duplicated hardcoded hook names]
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/receive-pack.c

index b5379a489569944097e00f7b72520e54d37c79b2..e53aaf5104194849c8b91e07c96df83197f74bec 100644 (file)
@@ -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);
 }