]> git.ipfire.org Git - thirdparty/git.git/commitdiff
packfile: skip unpacking object header for disk size requests
authorPatrick Steinhardt <ps@pks.im>
Thu, 18 Dec 2025 10:54:18 +0000 (11:54 +0100)
committerJunio C Hamano <gitster@pobox.com>
Thu, 18 Dec 2025 11:55:18 +0000 (20:55 +0900)
While most of the object info requests for a packed object require us to
unpack its headers, reading its disk size doesn't. We still unpack the
object header in that case though, which is unnecessary work.

Skip reading the header if only the disk size is requested. This leads
to a small speedup when reading disk size, only. The following benchmark
was done in the Git repository:

    Benchmark 1: ./git rev-list --disk-usage HEAD (rev = HEAD~)
      Time (mean ± σ):     105.2 ms ±   0.6 ms    [User: 91.4 ms, System: 13.3 ms]
      Range (min … max):   103.7 ms … 106.0 ms    27 runs

    Benchmark 2: ./git rev-list --disk-usage HEAD (rev = HEAD)
      Time (mean ± σ):      96.7 ms ±   0.4 ms    [User: 86.2 ms, System: 10.0 ms]
      Range (min … max):    96.2 ms …  98.1 ms    30 runs

    Summary
      ./git rev-list --disk-usage HEAD (rev = HEAD) ran
        1.09 ± 0.01 times faster than ./git rev-list --disk-usage HEAD (rev = HEAD~)

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

index 8c6ef45a6727bde726deb215d5cadea90f0755ba..a2ba237ce76f57f27e5b52f6df9679aa5c1823c3 100644 (file)
@@ -1586,7 +1586,7 @@ int packed_object_info(struct repository *r, struct packed_git *p,
        struct pack_window *w_curs = NULL;
        unsigned long size;
        off_t curpos = obj_offset;
-       enum object_type type;
+       enum object_type type = OBJ_NONE;
        int ret;
 
        /*
@@ -1598,7 +1598,7 @@ int packed_object_info(struct repository *r, struct packed_git *p,
                                                      &type);
                if (!*oi->contentp)
                        type = OBJ_BAD;
-       } else {
+       } else if (oi->sizep || oi->typep || oi->delta_base_oid) {
                type = unpack_object_header(p, &w_curs, &curpos, &size);
        }
 
@@ -1662,6 +1662,9 @@ int packed_object_info(struct repository *r, struct packed_git *p,
        oi->u.packed.pack = p;
 
        switch (type) {
+       case OBJ_NONE:
+               oi->u.packed.type = PACKED_OBJECT_TYPE_UNKNOWN;
+               break;
        case OBJ_REF_DELTA:
                oi->u.packed.type = PACKED_OBJECT_TYPE_REF_DELTA;
                break;