Skip to content

Commit

Permalink
fetch-pack: avoid quadratic loop in filter_refs
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jeff King authored and Junio C Hamano committed May 22, 2012
1 parent 9e8e704 commit a0de288
Showing 1 changed file with 13 additions and 6 deletions.
19 changes: 13 additions & 6 deletions builtin/fetch-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ static void filter_refs(struct ref **refs, int nr_match, char **match)
struct ref **newtail = &newlist;
struct ref *ref, *next;
struct ref *fastarray[32];
int match_pos;

if (nr_match && !args.fetch_all) {
if (ARRAY_SIZE(fastarray) < nr_match)
Expand All @@ -540,6 +541,7 @@ static void filter_refs(struct ref **refs, int nr_match, char **match)
else
return_refs = NULL;

match_pos = 0;
for (ref = *refs; ref; ref = next) {
next = ref->next;
if (!memcmp(ref->name, "refs/", 5) &&
Expand All @@ -553,15 +555,20 @@ static void filter_refs(struct ref **refs, int nr_match, char **match)
continue;
}
else {
int i;
for (i = 0; i < nr_match; i++) {
if (!strcmp(ref->name, match[i])) {
match[i][0] = '\0';
return_refs[i] = ref;
int cmp = -1;
while (match_pos < nr_match) {
cmp = strcmp(ref->name, match[match_pos]);
if (cmp < 0) /* definitely do not have it */
break;
else if (cmp == 0) { /* definitely have it */
match[match_pos][0] = '\0';
return_refs[match_pos] = ref;
break;
}
else /* might have it; keep looking */
match_pos++;
}
if (i < nr_match)
if (!cmp)
continue; /* we will link it later */
}
free(ref);
Expand Down

0 comments on commit a0de288

Please sign in to comment.