packfile: skip unpacking object header for disk size requests

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>

Patrick Steinhardt committed Jan 12, 2026 at 10:00 UTC 5ff29698e077e712740691a1d15e8320115ebdbf
1 file changed +5 -2
packfile.c
+5 -2
@@ -1586,7 +1586,7 @@ int packed_object_info(struct repository *r, struct packed_git *p,
1586 struct pack_window *w_curs = NULL;
1587 unsigned long size;
1588 off_t curpos = obj_offset;
1589 - enum object_type type;
1589 + enum object_type type = OBJ_NONE;
1590 int ret;
1591
1592 /*
@@ -1598,7 +1598,7 @@ int packed_object_info(struct repository *r, struct packed_git *p,
1598 &type);
1599 if (!*oi->contentp)
1600 type = OBJ_BAD;
1601 - } else {
1601 + } else if (oi->sizep || oi->typep || oi->delta_base_oid) {
1602 type = unpack_object_header(p, &w_curs, &curpos, &size);
1603 }
1604
@@ -1662,6 +1662,9 @@ int packed_object_info(struct repository *r, struct packed_git *p,
1662 oi->u.packed.pack = p;
1663
1664 switch (type) {
1665 + case OBJ_NONE:
1666 + oi->u.packed.type = PACKED_OBJECT_TYPE_UNKNOWN;
1667 + break;
1668 case OBJ_REF_DELTA:
1669 oi->u.packed.type = PACKED_OBJECT_TYPE_REF_DELTA;
1670 break;