]> git.ipfire.org Git - thirdparty/git.git/commit - refs/files-backend.c
refs/files-backend: optimize reading of symbolic refs
authorPatrick Steinhardt <ps@pks.im>
Tue, 1 Mar 2022 09:33:54 +0000 (10:33 +0100)
committerJunio C Hamano <gitster@pobox.com>
Tue, 1 Mar 2022 18:13:46 +0000 (10:13 -0800)
commit0a7b38707d5d5c8a7baeb88a85d6259cee4f4e4d
treec233e2c2ba016d8e3b21389290eedec7aad4ec0c
parent1553f5e76c72243f61b454412b651706a869388f
refs/files-backend: optimize reading of symbolic refs

When reading references via `files_read_raw_ref()` we always consult
both the loose reference, and if that wasn't found, we also consult the
packed-refs file. While this makes sense to read a generic reference, it
is wasteful in the case where we only care about symbolic references:
the packed-refs backend does not support them, and thus it cannot ever
return one for us.

Special-case reading of symbolic references for the files backend such
that we always skip asking the packed-refs backend.

We use `refs_read_symbolic_ref()` extensively to determine whether we
need to skip updating local symbolic references during a fetch, which is
why the change results in a significant speedup when doing fetches in
repositories with huge numbers of references. The following benchmark
executes a mirror-fetch in a repository with about 2 million references
via `git fetch --prune --no-write-fetch-head +refs/*:refs/*`:

    Benchmark 1: HEAD~
      Time (mean ± σ):     68.372 s ±  2.344 s    [User: 65.629 s, System: 8.786 s]
      Range (min … max):   65.745 s … 70.246 s    3 runs

    Benchmark 2: HEAD
      Time (mean ± σ):     60.259 s ±  0.343 s    [User: 61.019 s, System: 7.245 s]
      Range (min … max):   60.003 s … 60.649 s    3 runs

    Summary
      'HEAD' ran
        1.13 ± 0.04 times faster than 'HEAD~'

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
refs/files-backend.c