Subject: Re: [BUG?] Major performance issue with some commands on our repo's master branch

From: Junio C Hamano <[email-masked]>
Date: Thu, 09 Jun 2022 13:06:48 -0700

Jeff King <[email-masked]> writes:

> But what I wondered is whether "show" in particular, because it would
> never want to skip showing a commit, could get away with avoiding the
> diff automatically.

Ahh, that is a clever thought.  At least unless we automatically
turn ourselves into "git log" by giving an range, we are naming
individual object we want to see, so why not show them?

But I wonder if "git show A -- P" should or should not show the
commit if A does not touch the path P.  Right now we apply the same
history simplification so "git show master -- t/" gives nothing to
me, which is probably one sensible thing to do.  It is debatable why
somebody who wants to see 'master' wants to hide it when it does not
touch the paths that match the pathspec given, but it can also be
debated why somebody would give a pathspec if commits are to be
hidden when they do not touch paths that match it, so...

> I.e., currently "git show -Sfoo HEAD" will always
> show HEAD, even if "-S" does not match anything. So if we are not
> showing any diff output, there is no need to compute the diff in that
> case. That is unlike "git log", which would omit commits that didn't
> match.

OK, you came up with an example that behaves differently.

> And really it is not "git show" that is special there, but the
> always_show_header flag it sets. So something like this might work:

A tempting thought, indeed.

> diff --git a/log-tree.c b/log-tree.c
> index d0ac0a6327..ed57386938 100644
> --- a/log-tree.c
> +++ b/log-tree.c
> @@ -1024,6 +1024,10 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log
>  	if (!all_need_diff && !opt->merges_need_diff)
>  		return 0;
>  
> +	if (opt->diffopt.output_format == DIFF_FORMAT_NO_OUTPUT &&
> +	    opt->always_show_header)
> +		return 0;
> +
>  	parse_commit_or_die(commit);
>  	oid = get_commit_tree_oid(commit);
>  
>
> It produces the same output in the cases I tried. And running with
> GIT_TRACE2_PERF shows that it doesn't diff and rename code.
>
> I'm not overly confident that it isn't violating some other subtle
> assumption / corner case that I haven't thought of, though. :)
>
> -Peff