]> git.ipfire.org Git - thirdparty/git.git/commitdiff
commit: use commit graph in `lookup_commit_reference_gently()`
authorPatrick Steinhardt <ps@pks.im>
Mon, 16 Feb 2026 15:38:03 +0000 (16:38 +0100)
committerJunio C Hamano <gitster@pobox.com>
Thu, 19 Feb 2026 17:34:26 +0000 (09:34 -0800)
In the preceding commit we refactored `lookup_commit_reference_gently()`
so that it doesn't parse non-commit objects anymore. This has led to a
speedup when git-receive-pack(1) accepts a shallow push into a repo
with lots of refs that point to blobs or trees.

But while this case is now faster, we still have the issue that
accepting pushes with lots of "normal" refs that point to commits are
still slow. This is mostly because we look up the commits via the object
database, and that is rather costly.

Adapt the code to use `repo_parse_commit_gently()` instead of
`parse_object()` to parse the resulting commit object. This function
knows to use the commit-graph to fill in the object, which is way more
cost efficient.

This leads to another significant speedup when accepting shallow pushes.
The following benchmark pushes a single objects from a shallow clone
into a repository with 600,000 references that all point to commits:

  Benchmark 1: git-receive-pack (rev = HEAD~)
    Time (mean ± σ):      9.179 s ±  0.031 s    [User: 8.858 s, System: 0.528 s]
    Range (min … max):    9.154 s …  9.213 s    3 runs

  Benchmark 2: git-receive-pack (rev = HEAD)
    Time (mean ± σ):      2.337 s ±  0.032 s    [User: 2.331 s, System: 0.234 s]
    Range (min … max):    2.308 s …  2.371 s    3 runs

  Summary
    git-receive-pack . </tmp/input (rev = HEAD) ran
      3.93 ± 0.05 times faster than git-receive-pack (rev = HEAD~)

Also, this again leads to a significant reduction in memory allocations.
Before this change:

  HEAP SUMMARY:
      in use at exit: 17,524,978 bytes in 22,393 blocks
    total heap usage: 33,313 allocs, 10,920 frees, 407,774,251 bytes allocated

And after this change:

  HEAP SUMMARY:
      in use at exit: 11,534,036 bytes in 12,406 blocks
    total heap usage: 13,284 allocs, 878 frees, 15,521,451 bytes allocated

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

index fb1b01b9c3acf4bc9284ec591ceb6c48db5aa7b9..25cdbd3be41922728feaf73c0b3cf8e35687831b 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -45,7 +45,7 @@ struct commit *lookup_commit_reference_gently(struct repository *r,
 {
        const struct object_id *maybe_peeled;
        struct object_id peeled_oid;
-       struct object *object;
+       struct commit *commit;
        enum object_type type;
 
        switch (peel_object_ext(r, oid, &peeled_oid, 0, &type)) {
@@ -67,11 +67,11 @@ struct commit *lookup_commit_reference_gently(struct repository *r,
                return NULL;
        }
 
-       object = parse_object(r, maybe_peeled);
-       if (!object)
+       commit = lookup_commit(r, maybe_peeled);
+       if (!commit || repo_parse_commit_gently(r, commit, quiet) < 0)
                return NULL;
 
-       return object_as_type(object, OBJ_COMMIT, quiet);
+       return commit;
 }
 
 struct commit *lookup_commit_reference(struct repository *r, const struct object_id *oid)