All of lore.kernel.org
 help / color / mirror / Atom feed
From: Patrick Steinhardt <ps@pks.im>
To: Kristofer Karlsson via GitGitGadget <gitgitgadget@gmail.com>
Cc: git@vger.kernel.org, Kristofer Karlsson <krka@spotify.com>
Subject: Re: [PATCH v3 2/2] reftable: fix quadratic behavior in the presence of tombstones
Date: Fri, 10 Jul 2026 16:32:19 +0200	[thread overview]
Message-ID: <alECc90WZ9RPqMaA@pks.im> (raw)
In-Reply-To: <4fdcec84406431d56b7a7e593fd8e843c3b1ad52.1783679767.git.gitgitgadget@gmail.com>

On Fri, Jul 10, 2026 at 10:36:07AM +0000, Kristofer Karlsson via GitGitGadget wrote:
> From: Kristofer Karlsson <krka@spotify.com>
> 
> When many tombstones are present in a reftable, operations that need
> to look up or iterate over refs exhibit quadratic behavior.  With
> 8000 refs deleted and re-created, update-ref takes ~15s, quadrupling
> for each doubling of input size.
> 
> The root cause is the merged iterator's suppress_deletions flag.
> When set, merged_iter_next_void() silently consumes tombstone records
> in a tight internal loop before returning to the caller.  This
> prevents higher-level code from checking iteration bounds (such as
> prefix or refname comparisons) until after all tombstones have been
> scanned.
> 
> This affects any code path that seeks into a range containing
> tombstones, including:
> 
>  - refs_verify_refnames_available() seeks to "refs/tags/foo-1/" to
>    check for D/F conflicts and must scan through all subsequent
>    tombstones before the caller can see that they are past the prefix
>    of interest.
> 
>  - reftable_backend_read_ref() seeks to a specific refname and must
>    scan through all subsequent tombstones before returning "not
>    found", because the merged iterator skips the matching tombstone
>    and searches for the next live record.
> 
> Fix this by making suppress_deletions configurable via
> reftable_stack_options instead of unconditionally enabling it.  Git
> no longer sets the flag, so tombstones are now returned to callers in
> the reftable backend, which skip them after their existing bounds
> checks.  This allows iteration to terminate as soon as a tombstone
> past the relevant bound is encountered.
> 
> Downstream users of the reftable library (e.g. libgit2) can still
> enable suppress_deletions through the stack options to retain the
> previous behavior.
> 
> This also requires adding deletion checks to the log iteration paths,
> since suppress_deletions applied to both ref and log iterators.

Nit: s/applied/applies/

> diff --git a/reftable/reftable-stack.h b/reftable/reftable-stack.h
> index 11f9963f4f..5d22d84e80 100644
> --- a/reftable/reftable-stack.h
> +++ b/reftable/reftable-stack.h
> @@ -42,6 +42,8 @@ struct reftable_stack_options {
>  	 */
>  	void (*on_reload)(void *payload);
>  	void *on_reload_payload;
> +
> +	int suppress_deletions;
>  };

A comment would've been nice, but I don't think this warrants a reroll.

> diff --git a/reftable/stack.c b/reftable/stack.c
> index ab12926708..caaedf24d6 100644
> --- a/reftable/stack.c
> +++ b/reftable/stack.c
> @@ -337,7 +337,7 @@ static int reftable_stack_reload_once(struct reftable_stack *st,
>  	/* Update the stack to point to the new tables. */
>  	if (st->merged)
>  		reftable_merged_table_free(st->merged);
> -	new_merged->suppress_deletions = 1;
> +	new_merged->suppress_deletions = st->opts.suppress_deletions;
>  	st->merged = new_merged;

Yup, this looks good to me.

Thanks!

Patrick

  reply	other threads:[~2026-07-10 14:32 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-06 13:35 [PATCH 0/2] reftable: fix quadratic behavior when re-creating deleted refs Kristofer Karlsson via GitGitGadget
2026-07-06 13:35 ` [PATCH 1/2] t: add tests for ref tombstone scenarios Kristofer Karlsson via GitGitGadget
2026-07-07 15:24   ` Patrick Steinhardt
2026-07-07 16:12     ` Kristofer Karlsson
2026-07-08  5:59       ` Patrick Steinhardt
2026-07-08  7:28         ` Kristofer Karlsson
2026-07-06 13:35 ` [PATCH 2/2] reftable: fix quadratic behavior when re-creating deleted refs Kristofer Karlsson via GitGitGadget
2026-07-07 15:24   ` Patrick Steinhardt
2026-07-07 16:04     ` Kristofer Karlsson
2026-07-08 11:15 ` [PATCH 0/2] " brian m. carlson
2026-07-09 12:08 ` [PATCH v2 " Kristofer Karlsson via GitGitGadget
2026-07-09 12:08   ` [PATCH v2 1/2] t/perf: add perf test for ref tombstone scenarios Kristofer Karlsson via GitGitGadget
2026-07-09 12:08   ` [PATCH v2 2/2] reftable: fix quadratic behavior in the presence of tombstones Kristofer Karlsson via GitGitGadget
2026-07-09 13:53     ` Patrick Steinhardt
2026-07-09 14:48       ` Kristofer Karlsson
2026-07-09 14:54         ` Patrick Steinhardt
2026-07-10 10:36   ` [PATCH v3 0/2] reftable: fix quadratic behavior when re-creating deleted refs Kristofer Karlsson via GitGitGadget
2026-07-10 10:36     ` [PATCH v3 1/2] t/perf: add perf test for ref tombstone scenarios Kristofer Karlsson via GitGitGadget
2026-07-10 10:36     ` [PATCH v3 2/2] reftable: fix quadratic behavior in the presence of tombstones Kristofer Karlsson via GitGitGadget
2026-07-10 14:32       ` Patrick Steinhardt [this message]
2026-07-10 15:03         ` Kristofer Karlsson
2026-07-13  5:14           ` Patrick Steinhardt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=alECc90WZ9RPqMaA@pks.im \
    --to=ps@pks.im \
    --cc=git@vger.kernel.org \
    --cc=gitgitgadget@gmail.com \
    --cc=krka@spotify.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.