diffcore-rename: simplify and accelerate register_rename_src()

register_rename_src() took pains to create an array in rename_src which was sorted by pathname of the contained diff_filepair. The sorting was entirely unnecessary since callers pass filepairs to us in sorted order. We can simply append to the end of the rename_src array, speeding up diffcore_rename() setup time. Also, note that I dropped the return type on the function since it was unconditionally discarded anyway. This patch is being submitted in a different order than its original development, but in a large rebase of many commits with lots of renames and with several optimizations to inexact rename detection, diffcore_rename() setup time was a sizeable chunk of overall runtime. This patch dropped execution time of rebasing 35 commits with lots of renames by 2% overall. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed Dec 11, 2020 at 09:08 UTC b970b4ef62432980bf106c2f0970c25ae0de5cce
1 file changed +13 -26
diffcore-rename.c
+13 -26
@@ -76,36 +76,23 @@ static struct diff_rename_src {
76 } *rename_src;
77 static int rename_src_nr, rename_src_alloc;
78
79 -static struct diff_rename_src *register_rename_src(struct diff_filepair *p)
79 +static void register_rename_src(struct diff_filepair *p)
80 {
81 - int first, last;
82 - struct diff_filespec *one = p->one;
83 - unsigned short score = p->score;
84 -
85 - first = 0;
86 - last = rename_src_nr;
87 - while (last > first) {
88 - int next = first + ((last - first) >> 1);
89 - struct diff_rename_src *src = &(rename_src[next]);
90 - int cmp = strcmp(one->path, src->p->one->path);
91 - if (!cmp)
92 - return src;
93 - if (cmp < 0) {
94 - last = next;
95 - continue;
96 - }
97 - first = next+1;
98 - }
81 + /*
82 + * If we have multiple entries at the same path in the source tree
83 + * (an invalid tree, to be sure), avoid using more more than one
84 + * such entry in rename detection. Once upon a time, doing so
85 + * caused segfaults; see commit 25d5ea410f ("[PATCH] Redo
86 + * rename/copy detection logic.", 2005-05-24).
87 + */
88 + if (rename_src_nr > 0 &&
89 + !strcmp(rename_src[rename_src_nr-1].p->one->path, p->one->path))
90 + return;
91
100 - /* insert to make it at "first" */
92 ALLOC_GROW(rename_src, rename_src_nr + 1, rename_src_alloc);
93 + rename_src[rename_src_nr].p = p;
94 + rename_src[rename_src_nr].score = p->score;
95 rename_src_nr++;
103 - if (first < rename_src_nr)
104 - MOVE_ARRAY(rename_src + first + 1, rename_src + first,
105 - rename_src_nr - first - 1);
106 - rename_src[first].p = p;
107 - rename_src[first].score = score;
108 - return &(rename_src[first]);
96 }
97
98 static int basename_same(struct diff_filespec *src, struct diff_filespec *dst)