Git development
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: Gatla Vishweshwar Reddy <gatlavishweshwarreddy26@gmail.com>
Cc: git@vger.kernel.org
Subject: Re: [PATCH v6] show-branch: convert per-branch flags to commit-slab
Date: Thu, 16 Jul 2026 23:00:09 -0700	[thread overview]
Message-ID: <xmqqfr1i6tqu.fsf@gitster.g> (raw)
In-Reply-To: <20260715184241.56635-1-gatlavishweshwarreddy26@gmail.com> (Gatla Vishweshwar Reddy's message of "Thu, 16 Jul 2026 00:12:41 +0530")

Gatla Vishweshwar Reddy <gatlavishweshwarreddy26@gmail.com> writes:

> show-branch uses commit->object.flags to store per-branch
> reachability bits, one bit per branch starting at REV_SHIFT.
> The flags word has only a fixed number of available bits, limiting
> the number of branches that can be shown simultaneously to MAX_REVS.
>
> Convert the per-branch bits to a dedicated commit-slab using uint64_t
> as the element type, initialized with a stride via
> init_commit_rev_flags_with_stride(). Keep the UNINTERESTING bit in
> object.flags where it belongs, as it is used for revision walking and
> does not need to be in the per-branch slab. With UNINTERESTING removed
> from the slab, REV_SHIFT becomes 0 and all 64 bits of uint64_t are
> available for branch tracking, lifting MAX_REVS from 27 to 64 branches.

Thanks.  This version looks much cleaner.  I appreciate your
addressing the correctness issues around UNINTERESTING
propagation that we spotted in the previous round.

I do have a slight worry about a potential performance regression,
though.  We might run the risk of slowing down the traversal in
how we skip parents.

> @@ -226,39 +285,43 @@ static void join_revs(struct prio_queue *queue,
> ...

In the original code, we avoided parsing and re-queueing the parent 'p'
if we knew it already had all the flags we were trying to propagate.

> -			int this_flag = p->object.flags;
> -			parents = parents->next;
> -			if ((this_flag & flags) == flags)
> -				continue;
> -			repo_parse_commit(the_repository, p);
> ...
> +		{
> +			int commit_is_merge_base = has_all_rev_flags(commit, num_rev);
> +			parents = commit->parents;
> +
> +			while (parents) {
> +				struct commit *p = parents->item;
> +				parents = parents->next;
> +				if (has_all_rev_flags(p, num_rev) &&
> +				    (!commit_is_merge_base || (p->object.flags & UNINTERESTING)))
> +					continue;

With the new slab-based approach, we skip only when 'p' already has
all possible revision flags, num_rev.  If 'p' already carries all
the flags that the current 'commit' has (even if it lacks some of
the other num_rev flags), the traversal could be pruned early, but
the proposed change fails to do so.

Consequently, we proceed to propagate the flags (which amounts to a
no-op on the slab anyway) and, worse, re-queue 'p' for further
processing.  In a densely tangled history with many merges, this
would lead to significant redundant work and queue thrashing.  We
instead should check whether the flags of 'commit' are a subset of
those of 'p'.  Since the flags_stride is known, introducing a
helper, perhaps has_subset_rev_flags(commit, p), to perform this
check should be a straightforward exercise.

Also, looking at the bigger picture ...

> -#define REV_SHIFT	 2
> -#define MAX_REVS	(FLAG_BITS - REV_SHIFT) /* should not exceed bits_per_int - REV_SHIFT */
> -
> +#define REV_SHIFT	 0
> +#define MAX_REVS	(sizeof(uint64_t) * 8)

While lifting the limit from 27 to 64 is a welcome improvement, I
wonder why we stop there and still tolerate a hardcoded MAX_REVS
limit.

The introduction of flags_stride and init_commit_rev_flags_with_stride
already lays the groundwork for supporting an arbitrary number of
flags.  The only remaining blockages that keep MAX_REVS alive are:

 - The static ref_name[] array; and

 - The stack-allocated arrays rev[] and reflog_msg[] in the
   cmd_show_branch() function.

If we

 - dynamically grow the ref_name[] array (perhaps using the
   ALLOC_GROW macro),

 - dynamically allocate rev[] and reflog_msg[] in cmd_show_branch()
   once options are parsed (and thus ref_name_cnt and the reflog
   flag are known), and

 - calculate flags_stride at runtime as (ref_name_cnt + 63) / 64,

then we can get rid of MAX_REVS and the associated boundary checks
entirely.  Since the proposed patch already does 90% of the work
needed to support an arbitrary stride, it feels like a missed
opportunity not to take that final step.

Thoughts?

  reply	other threads:[~2026-07-17  6:00 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-14 18:30 [PATCH] show-branch: convert object.flags usage to a commit-slab Gatla Vishweshwar Reddy
2026-07-14 20:01 ` [PATCH v2] show-branch: convert object.flags to commit-slab with uint64_t Gatla Vishweshwar Reddy
2026-07-14 20:41   ` Junio C Hamano
2026-07-14 22:00     ` Jeff King
2026-07-15  1:47       ` [PATCH v3] show-branch: convert per-branch flags to commit-slab Gatla Vishweshwar Reddy
2026-07-15  3:34         ` Junio C Hamano
2026-07-15  4:18           ` [PATCH v4] " Gatla Vishweshwar Reddy
2026-07-15  6:47             ` Patrick Steinhardt
2026-07-15  7:20         ` [PATCH v3] " Junio C Hamano
2026-07-15 12:01           ` [PATCH v5] " Gatla Vishweshwar Reddy
2026-07-15 17:17             ` Junio C Hamano
2026-07-15 18:42               ` [PATCH v6] " Gatla Vishweshwar Reddy
2026-07-17  6:00                 ` Junio C Hamano [this message]
2026-07-17  7:42                   ` [PATCH v7] " Gatla Vishweshwar Reddy
2026-07-17  8:52                     ` Patrick Steinhardt
2026-07-17  8:51             ` [PATCH v5] " 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=xmqqfr1i6tqu.fsf@gitster.g \
    --to=gitster@pobox.com \
    --cc=gatlavishweshwarreddy26@gmail.com \
    --cc=git@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox