fetch-pack: avoid quadratic loop in filter_refs
We have a list of refs that we want to compare against the "match" array. The current code searches the match list linearly, giving quadratic behavior over the number of refs when you want to fetch all of them. Instead, we can compare the lists as we go, giving us linear behavior. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
9e8e704f0b
commit
a0de28805d
@ -528,6 +528,7 @@ static void filter_refs(struct ref **refs, int nr_match, char **match)
|
|||||||
struct ref **newtail = &newlist;
|
struct ref **newtail = &newlist;
|
||||||
struct ref *ref, *next;
|
struct ref *ref, *next;
|
||||||
struct ref *fastarray[32];
|
struct ref *fastarray[32];
|
||||||
|
int match_pos;
|
||||||
|
|
||||||
if (nr_match && !args.fetch_all) {
|
if (nr_match && !args.fetch_all) {
|
||||||
if (ARRAY_SIZE(fastarray) < nr_match)
|
if (ARRAY_SIZE(fastarray) < nr_match)
|
||||||
@ -540,6 +541,7 @@ static void filter_refs(struct ref **refs, int nr_match, char **match)
|
|||||||
else
|
else
|
||||||
return_refs = NULL;
|
return_refs = NULL;
|
||||||
|
|
||||||
|
match_pos = 0;
|
||||||
for (ref = *refs; ref; ref = next) {
|
for (ref = *refs; ref; ref = next) {
|
||||||
next = ref->next;
|
next = ref->next;
|
||||||
if (!memcmp(ref->name, "refs/", 5) &&
|
if (!memcmp(ref->name, "refs/", 5) &&
|
||||||
@ -553,15 +555,20 @@ static void filter_refs(struct ref **refs, int nr_match, char **match)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int i;
|
int cmp = -1;
|
||||||
for (i = 0; i < nr_match; i++) {
|
while (match_pos < nr_match) {
|
||||||
if (!strcmp(ref->name, match[i])) {
|
cmp = strcmp(ref->name, match[match_pos]);
|
||||||
match[i][0] = '\0';
|
if (cmp < 0) /* definitely do not have it */
|
||||||
return_refs[i] = ref;
|
break;
|
||||||
|
else if (cmp == 0) { /* definitely have it */
|
||||||
|
match[match_pos][0] = '\0';
|
||||||
|
return_refs[match_pos] = ref;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else /* might have it; keep looking */
|
||||||
|
match_pos++;
|
||||||
}
|
}
|
||||||
if (i < nr_match)
|
if (!cmp)
|
||||||
continue; /* we will link it later */
|
continue; /* we will link it later */
|
||||||
}
|
}
|
||||||
free(ref);
|
free(ref);
|
||||||
|
Loading…
Reference in New Issue
Block a user