fetch-pack: binary search when storing wanted-refs

In do_fetch_pack_v2(), the "sought" array is sorted by name, and it is not subsequently reordered (within the function). Therefore, receive_wanted_refs() can assume that "sought" is sorted, and can thus use a binary search when storing wanted-refs retrieved from the server. Replace the existing linear search with a binary search. This improves performance significantly when mirror cloning a repository with more than 1 million refs. Signed-off-by: Jonathan Tan <jonathantanmy@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jonathan Tan committed Mar 27, 2019 at 14:11 UTC b7643009123216792aa158d3b2ca64a79adc01e2
1 file changed +10 -9
fetch-pack.c
+10 -9
@@ -1295,6 +1295,11 @@ static void receive_shallow_info(struct fetch_pack_args *args,
1295 }
1296 }
1297
1298 +static int cmp_name_ref(const void *name, const void *ref)
1299 +{
1300 + return strcmp(name, (*(struct ref **)ref)->name);
1301 +}
1302 +
1303 static void receive_wanted_refs(struct packet_reader *reader,
1304 struct ref **sought, int nr_sought)
1305 {
@@ -1302,20 +1307,16 @@ static void receive_wanted_refs(struct packet_reader *reader,
1307 while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
1308 struct object_id oid;
1309 const char *end;
1305 - int i;
1310 + struct ref **found;
1311
1312 if (parse_oid_hex(reader->line, &oid, &end) || *end++ != ' ')
1313 die(_("expected wanted-ref, got '%s'"), reader->line);
1314
1310 - for (i = 0; i < nr_sought; i++) {
1311 - if (!strcmp(end, sought[i]->name)) {
1312 - oidcpy(&sought[i]->old_oid, &oid);
1313 - break;
1314 - }
1315 - }
1316 -
1317 - if (i == nr_sought)
1315 + found = bsearch(end, sought, nr_sought, sizeof(*sought),
1316 + cmp_name_ref);
1317 + if (!found)
1318 die(_("unexpected wanted-ref: '%s'"), reader->line);
1319 + oidcpy(&(*found)->old_oid, &oid);
1320 }
1321
1322 if (reader->status != PACKET_READ_DELIM)