Skip to content

Commit 55d5d5b

Browse files
committed
combine-diff.c: fix performance problem when folding common deleted lines
For a deleted line in a patch with the parent we are looking at, the append_lost() function finds the same line among a run of lines that were deleted from the same location by patches from parents we previously checked. This is so that patches with two parents @@ -1,4 +1,3 @@ @@ -1,4 +1,3 @@ one one -two -two three three -quatro -fyra +four +four can be coalesced into this sequence, reusing one line that describes the removal of "two" for both parents. @@@ -1,4 -1,4 +1,3 @@@ one --two three - quatro -frya ++four While reading the second patch (that removes "two" and then "fyra"), after finding where removal of the "two" matches, we need to find existing removal of "fyra" (if exists) in the removal list, but the match has to happen after all the existing matches (in this case "two"). The code used a naïve O(n^2) algorithm to compute this by scanning the whole removal list over and over again. This patch remembers where the next scan should be started in the existing removal list to avoid this. Noticed by Linus Torvalds. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 78d3b06 commit 55d5d5b

File tree

1 file changed

+5
-8
lines changed

1 file changed

+5
-8
lines changed

combine-diff.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ struct lline {
8080
/* Lines surviving in the merge result */
8181
struct sline {
8282
struct lline *lost_head, **lost_tail;
83+
struct lline *next_lost;
8384
char *bol;
8485
int len;
8586
/* bit 0 up to (N-1) are on if the parent has this line (i.e.
@@ -121,18 +122,12 @@ static void append_lost(struct sline *sline, int n, const char *line, int len)
121122

122123
/* Check to see if we can squash things */
123124
if (sline->lost_head) {
124-
struct lline *last_one = NULL;
125-
/* We cannot squash it with earlier one */
126-
for (lline = sline->lost_head;
127-
lline;
128-
lline = lline->next)
129-
if (lline->parent_map & this_mask)
130-
last_one = lline;
131-
lline = last_one ? last_one->next : sline->lost_head;
125+
lline = sline->next_lost;
132126
while (lline) {
133127
if (lline->len == len &&
134128
!memcmp(lline->line, line, len)) {
135129
lline->parent_map |= this_mask;
130+
sline->next_lost = lline->next;
136131
return;
137132
}
138133
lline = lline->next;
@@ -147,6 +142,7 @@ static void append_lost(struct sline *sline, int n, const char *line, int len)
147142
lline->line[len] = 0;
148143
*sline->lost_tail = lline;
149144
sline->lost_tail = &lline->next;
145+
sline->next_lost = NULL;
150146
}
151147

152148
struct combine_diff_state {
@@ -187,6 +183,7 @@ static void consume_line(void *state_, char *line, unsigned long len)
187183
xcalloc(state->num_parent,
188184
sizeof(unsigned long));
189185
state->sline[state->nb-1].p_lno[state->n] = state->ob;
186+
state->lost_bucket->next_lost = state->lost_bucket->lost_head;
190187
return;
191188
}
192189
if (!state->lost_bucket)

0 commit comments

Comments
 (0)