Skip to content

Commit 0a7b387

Browse files
pks-tgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1553f5e commit 0a7b387

File tree

1 file changed

+28
-6
lines changed

1 file changed

+28
-6
lines changed

refs/files-backend.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,9 @@ static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs)
338338
return refs->loose;
339339
}
340340

341-
static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
342-
struct object_id *oid, struct strbuf *referent,
343-
unsigned int *type, int *failure_errno)
341+
static int read_ref_internal(struct ref_store *ref_store, const char *refname,
342+
struct object_id *oid, struct strbuf *referent,
343+
unsigned int *type, int *failure_errno, int skip_packed_refs)
344344
{
345345
struct files_ref_store *refs =
346346
files_downcast(ref_store, REF_STORE_READ, "read_raw_ref");
@@ -381,7 +381,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
381381
if (lstat(path, &st) < 0) {
382382
int ignore_errno;
383383
myerr = errno;
384-
if (myerr != ENOENT)
384+
if (myerr != ENOENT || skip_packed_refs)
385385
goto out;
386386
if (refs_read_raw_ref(refs->packed_ref_store, refname, oid,
387387
referent, type, &ignore_errno)) {
@@ -425,7 +425,8 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
425425
* ref is supposed to be, there could still be a
426426
* packed ref:
427427
*/
428-
if (refs_read_raw_ref(refs->packed_ref_store, refname, oid,
428+
if (skip_packed_refs ||
429+
refs_read_raw_ref(refs->packed_ref_store, refname, oid,
429430
referent, type, &ignore_errno)) {
430431
myerr = EISDIR;
431432
goto out;
@@ -470,6 +471,27 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
470471
return ret;
471472
}
472473

474+
static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
475+
struct object_id *oid, struct strbuf *referent,
476+
unsigned int *type, int *failure_errno)
477+
{
478+
return read_ref_internal(ref_store, refname, oid, referent, type, failure_errno, 0);
479+
}
480+
481+
static int files_read_symbolic_ref(struct ref_store *ref_store, const char *refname,
482+
struct strbuf *referent)
483+
{
484+
struct object_id oid;
485+
int failure_errno, ret;
486+
unsigned int type;
487+
488+
ret = read_ref_internal(ref_store, refname, &oid, referent, &type, &failure_errno, 1);
489+
if (ret)
490+
return ret;
491+
492+
return !(type & REF_ISSYMREF);
493+
}
494+
473495
int parse_loose_ref_contents(const char *buf, struct object_id *oid,
474496
struct strbuf *referent, unsigned int *type,
475497
int *failure_errno)
@@ -3286,7 +3308,7 @@ struct ref_storage_be refs_be_files = {
32863308

32873309
files_ref_iterator_begin,
32883310
files_read_raw_ref,
3289-
NULL,
3311+
files_read_symbolic_ref,
32903312

32913313
files_reflog_iterator_begin,
32923314
files_for_each_reflog_ent,

0 commit comments

Comments
 (0)