Skip to content

Commit 6fd1cc8

Browse files
pks-tgitster
authored andcommitted
fetch-pack: use commit-graph when computing cutoff
During packfile negotiation we iterate over all refs announced by the remote side to check whether their IDs refer to commits already known to us. If a commit is known to us already, then its date is a potential cutoff point for commits we have in common with the remote side. There is potentially a lot of commits announced by the remote depending on how many refs there are in the remote repository, and for every one of them we need to search for it in our object database and, if found, parse the corresponding object to find out whether it is a candidate for the cutoff date. This can be sped up by trying to look up commits via the commit-graph first, which is a lot more efficient. Benchmarks in a repository with about 2,1 million refs and an up-to-date commit-graph show an almost 20% speedup when mirror-fetching: Benchmark 1: git fetch +refs/*:refs/* (v2.35.0) Time (mean ± σ): 115.587 s ± 2.009 s [User: 109.874 s, System: 11.305 s] Range (min … max): 113.584 s … 118.820 s 5 runs Benchmark 2: git fetch +refs/*:refs/* (HEAD) Time (mean ± σ): 96.859 s ± 0.624 s [User: 91.948 s, System: 10.980 s] Range (min … max): 96.180 s … 97.875 s 5 runs Summary 'git fetch +refs/*:refs/* (HEAD)' ran 1.19 ± 0.02 times faster than 'git fetch +refs/*:refs/* (v2.35.0)' Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2b9c120 commit 6fd1cc8

File tree

1 file changed

+16
-12
lines changed

1 file changed

+16
-12
lines changed

fetch-pack.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -696,26 +696,30 @@ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator,
696696

697697
trace2_region_enter("fetch-pack", "parse_remote_refs_and_find_cutoff", NULL);
698698
for (ref = *refs; ref; ref = ref->next) {
699-
struct object *o;
699+
struct commit *commit;
700+
701+
commit = lookup_commit_in_graph(the_repository, &ref->old_oid);
702+
if (!commit) {
703+
struct object *o;
700704

701-
if (!has_object_file_with_flags(&ref->old_oid,
705+
if (!has_object_file_with_flags(&ref->old_oid,
702706
OBJECT_INFO_QUICK |
703-
OBJECT_INFO_SKIP_FETCH_OBJECT))
704-
continue;
705-
o = parse_object(the_repository, &ref->old_oid);
706-
if (!o)
707-
continue;
707+
OBJECT_INFO_SKIP_FETCH_OBJECT))
708+
continue;
709+
o = parse_object(the_repository, &ref->old_oid);
710+
if (!o || o->type != OBJ_COMMIT)
711+
continue;
712+
713+
commit = (struct commit *)o;
714+
}
708715

709716
/*
710717
* We already have it -- which may mean that we were
711718
* in sync with the other side at some time after
712719
* that (it is OK if we guess wrong here).
713720
*/
714-
if (o->type == OBJ_COMMIT) {
715-
struct commit *commit = (struct commit *)o;
716-
if (!cutoff || cutoff < commit->date)
717-
cutoff = commit->date;
718-
}
721+
if (!cutoff || cutoff < commit->date)
722+
cutoff = commit->date;
719723
}
720724
trace2_region_leave("fetch-pack", "parse_remote_refs_and_find_cutoff", NULL);
721725

0 commit comments

Comments
 (0)