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>
This commit is contained in:
Jonathan Tan 2019-03-27 14:11:10 -07:00 committed by Junio C Hamano
parent aeb582a983
commit b764300912

View File

@ -1295,6 +1295,11 @@ static void receive_shallow_info(struct fetch_pack_args *args,
} }
} }
static int cmp_name_ref(const void *name, const void *ref)
{
return strcmp(name, (*(struct ref **)ref)->name);
}
static void receive_wanted_refs(struct packet_reader *reader, static void receive_wanted_refs(struct packet_reader *reader,
struct ref **sought, int nr_sought) struct ref **sought, int nr_sought)
{ {
@ -1302,20 +1307,16 @@ static void receive_wanted_refs(struct packet_reader *reader,
while (packet_reader_read(reader) == PACKET_READ_NORMAL) { while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
struct object_id oid; struct object_id oid;
const char *end; const char *end;
int i; struct ref **found;
if (parse_oid_hex(reader->line, &oid, &end) || *end++ != ' ') if (parse_oid_hex(reader->line, &oid, &end) || *end++ != ' ')
die(_("expected wanted-ref, got '%s'"), reader->line); die(_("expected wanted-ref, got '%s'"), reader->line);
for (i = 0; i < nr_sought; i++) { found = bsearch(end, sought, nr_sought, sizeof(*sought),
if (!strcmp(end, sought[i]->name)) { cmp_name_ref);
oidcpy(&sought[i]->old_oid, &oid); if (!found)
break;
}
}
if (i == nr_sought)
die(_("unexpected wanted-ref: '%s'"), reader->line); die(_("unexpected wanted-ref: '%s'"), reader->line);
oidcpy(&(*found)->old_oid, &oid);
} }
if (reader->status != PACKET_READ_DELIM) if (reader->status != PACKET_READ_DELIM)