fetch-prune: optimize dangling-ref reporting

When pruning during `git fetch` we check each pruned ref against the
ref_store one at a time to decide whether to report it as dangling.
This causes every local ref to be scanned for each ref being pruned.

If there are N refs in the repo and M refs being pruned, this code is
O(M*N). However, `git remote prune` uses a very similar function that
is only O(N*log(M)).

Remove the wasteful ref scanning for each pruned ref and use the faster
version already available in refs_warn_dangling_symrefs. Change the
message to include the original refname since the message is no longer
printed immediately after the line that did just print the refname.

In a repo with 126,000 refs, where I was pruning 28,000 refs, this
code made about 3.6 billion calls to strcmp and consumed 410 seconds
of CPU. (Invariably in that time, my remote would timeout and the
fetch would fail anyway.)

After this change, the same operation completes in under a second.

Signed-off-by: Phil Hord <phil.hord@gmail.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Phil Hord
2025-07-01 18:12:13 -07:00
committed by Junio C Hamano
parent f93ff170b9
commit cc7dc407fe
3 changed files with 13 additions and 13 deletions

2
refs.c
View File

@@ -461,7 +461,7 @@ static int warn_if_dangling_symref(const char *refname, const char *referent UNU
return 0;
}
fprintf(d->fp, d->msg_fmt, refname);
fprintf(d->fp, d->msg_fmt, refname, resolves_to);
fputc('\n', d->fp);
return 0;
}