Skip to content

Commit 63f4a7f

Browse files
peffgitster
authored andcommitted
pack-check: push oid lookup into loop
When we're checking a pack with fsck or verify-pack, we first sort the idx entries by offset, since accessing them in pack order is more efficient. To do so, we loop over them and fill in an array of structs with the offset, object_id, and index position of each, sort the result, and only then do we iterate over the sorted array and process each entry. In order to avoid the memory cost of storing the hash of each object, we just store a pointer into the copy in the mmap'd pack index file. To keep that property even as the rest of the code converted to "struct object_id", commit 9fd7504 (Convert the verify_pack callback to struct object_id, 2017-05-06) introduced a union in order to type-pun the pointer-to-hash into an object_id struct. But we can make this even simpler by observing that the sort operation doesn't need the object id at all! We only need them one at a time while we actually process each entry. So we can just omit the oid from the struct entirely and load it on the fly into a local variable in the second loop. This gets rid of the type-punning, and lets us directly use the more type-safe nth_packed_object_id(), simplifying the code. And as a bonus, it saves 8 bytes of memory per object. Note that this does mean we'll do the offset lookup for each object before the oid lookup. The oid lookup has more safety checks in it (e.g., for looking past p->num_objects) which in theory protected the offset lookup. But since violating those checks was already a BUG() condition (as described in the previous commit), it's not worth worrying about. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent e31c710 commit 63f4a7f

File tree

1 file changed

+10
-13
lines changed

1 file changed

+10
-13
lines changed

pack-check.c

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88

99
struct idx_entry {
1010
off_t offset;
11-
union idx_entry_object {
12-
const unsigned char *hash;
13-
struct object_id *oid;
14-
} oid;
1511
unsigned int nr;
1612
};
1713

@@ -97,30 +93,31 @@ static int verify_packfile(struct repository *r,
9793
entries[nr_objects].offset = pack_sig_ofs;
9894
/* first sort entries by pack offset, since unpacking them is more efficient that way */
9995
for (i = 0; i < nr_objects; i++) {
100-
entries[i].oid.hash = nth_packed_object_sha1(p, i);
101-
if (!entries[i].oid.hash)
102-
BUG("unable to get oid of object %lu from %s",
103-
(unsigned long)i, p->pack_name);
10496
entries[i].offset = nth_packed_object_offset(p, i);
10597
entries[i].nr = i;
10698
}
10799
QSORT(entries, nr_objects, compare_entries);
108100

109101
for (i = 0; i < nr_objects; i++) {
110102
void *data;
103+
struct object_id oid;
111104
enum object_type type;
112105
unsigned long size;
113106
off_t curpos;
114107
int data_valid;
115108

109+
if (nth_packed_object_id(&oid, p, entries[i].nr) < 0)
110+
BUG("unable to get oid of object %lu from %s",
111+
(unsigned long)entries[i].nr, p->pack_name);
112+
116113
if (p->index_version > 1) {
117114
off_t offset = entries[i].offset;
118115
off_t len = entries[i+1].offset - offset;
119116
unsigned int nr = entries[i].nr;
120117
if (check_pack_crc(p, w_curs, offset, len, nr))
121118
err = error("index CRC mismatch for object %s "
122119
"from %s at offset %"PRIuMAX"",
123-
oid_to_hex(entries[i].oid.oid),
120+
oid_to_hex(&oid),
124121
p->pack_name, (uintmax_t)offset);
125122
}
126123

@@ -143,14 +140,14 @@ static int verify_packfile(struct repository *r,
143140

144141
if (data_valid && !data)
145142
err = error("cannot unpack %s from %s at offset %"PRIuMAX"",
146-
oid_to_hex(entries[i].oid.oid), p->pack_name,
143+
oid_to_hex(&oid), p->pack_name,
147144
(uintmax_t)entries[i].offset);
148-
else if (check_object_signature(r, entries[i].oid.oid, data, size, type_name(type)))
145+
else if (check_object_signature(r, &oid, data, size, type_name(type)))
149146
err = error("packed %s from %s is corrupt",
150-
oid_to_hex(entries[i].oid.oid), p->pack_name);
147+
oid_to_hex(&oid), p->pack_name);
151148
else if (fn) {
152149
int eaten = 0;
153-
err |= fn(entries[i].oid.oid, type, size, data, &eaten);
150+
err |= fn(&oid, type, size, data, &eaten);
154151
if (eaten)
155152
data = NULL;
156153
}

0 commit comments

Comments
 (0)