Skip to content

Commit 3e5e6c6

Browse files
pks-tgitster
authored andcommitted
fetch-pack: speed up loading of refs via commit graph
When doing reference negotiation, git-fetch-pack(1) is loading all refs from disk in order to determine which commits it has in common with the remote repository. This can be quite expensive in repositories with many references though: in a real-world repository with around 2.2 million refs, fetching a single commit by its ID takes around 44 seconds. Dominating the loading time is decompression and parsing of the objects which are referenced by commits. Given the fact that we only care about commits (or tags which can be peeled to one) in this context, there is thus an easy performance win by switching the parsing logic to make use of the commit graph in case we have one available. Like this, we avoid hitting the object database to parse these commits but instead only load them from the commit-graph. This results in a significant performance boost when executing git-fetch in said repository with 2.2 million refs: Benchmark #1: HEAD~: git fetch $remote $commit Time (mean ± σ): 44.168 s ± 0.341 s [User: 42.985 s, System: 1.106 s] Range (min … max): 43.565 s … 44.577 s 10 runs Benchmark #2: HEAD: git fetch $remote $commit Time (mean ± σ): 19.498 s ± 0.724 s [User: 18.751 s, System: 0.690 s] Range (min … max): 18.629 s … 20.454 s 10 runs Summary 'HEAD: git fetch $remote $commit' ran 2.27 ± 0.09 times faster than 'HEAD~: git fetch $remote $commit' Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ebf3c04 commit 3e5e6c6

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

fetch-pack.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,14 @@ static struct commit *deref_without_lazy_fetch(const struct object_id *oid,
137137
break;
138138
}
139139
}
140-
if (type == OBJ_COMMIT)
141-
return (struct commit *) parse_object(the_repository, oid);
140+
141+
if (type == OBJ_COMMIT) {
142+
struct commit *commit = lookup_commit(the_repository, oid);
143+
if (!commit || repo_parse_commit(the_repository, commit))
144+
return NULL;
145+
return commit;
146+
}
147+
142148
return NULL;
143149
}
144150

0 commit comments

Comments
 (0)