Skip to content

Commit 9bd3421

Browse files
newrengitster
authored andcommitted
diffcore-rename: determine which relevant_sources are no longer relevant
As noted a few commits ago ("diffcore-rename: only compute dir_rename_count for relevant directories"), when a source file rename is used as part of directory rename detection, we need to increment counts for each ancestor directory in dirs_removed with value RELEVANT_FOR_SELF. However, a few commits ago ("diffcore-rename: check if we have enough renames for directories early on"), we may have downgraded all relevant ancestor directories from RELEVANT_FOR_SELF to RELEVANT_FOR_ANCESTOR. For a given file, if no ancestor directory is found in dirs_removed with a value of RELEVANT_FOR_SELF, then we can downgrade relevant_source[PATH] from RELEVANT_LOCATION to RELEVANT_NO_MORE. This means we can skip detecting a rename for that particular path (and any other paths in the same directory). For the testcases mentioned in commit 557ac03 ("merge-ort: begin performance work; instrument with trace2_region_* calls", 2020-10-28), this change improves the performance as follows: Before After no-renames: 5.680 s ± 0.096 s 5.665 s ± 0.129 s mega-renames: 13.812 s ± 0.162 s 11.435 s ± 0.158 s just-one-mega: 506.0 ms ± 3.9 ms 494.2 ms ± 6.1 ms While this improvement looks rather modest for these testcases (because all the previous optimizations were sufficient to nearly remove all time spent in rename detection already), consider this alternative testcase tweaked from the ones in commit 557ac03 as follows <Same initial setup as commit 557ac03, then...> $ git switch -c add-empty-file v5.5 $ >drivers/gpu/drm/i915/new-empty-file $ git add drivers/gpu/drm/i915/new-empty-file $ git commit -m "new file" $ git switch 5.4-rename $ git cherry-pick --strategy=ort add-empty-file For this testcase, we see the following improvement: Before After pick-empty: 1.936 s ± 0.024 s 688.1 ms ± 4.2 ms So roughly a factor of 3 speedup. At $DAYJOB, there was a particular repository and cherry-pick that inspired this optimization; for that case I saw a speedup factor of 7 with this optimization. Signed-off-by: Elijah Newren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ec59da6 commit 9bd3421

File tree

1 file changed

+50
-1
lines changed

1 file changed

+50
-1
lines changed

diffcore-rename.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1129,7 +1129,7 @@ static void handle_early_known_dir_renames(struct dir_rename_info *info,
11291129
* a majority.
11301130
*/
11311131

1132-
int i;
1132+
int i, new_num_src;
11331133
struct hashmap_iter iter;
11341134
struct strmap_entry *entry;
11351135

@@ -1193,6 +1193,55 @@ static void handle_early_known_dir_renames(struct dir_rename_info *info,
11931193
RELEVANT_FOR_ANCESTOR);
11941194
}
11951195
}
1196+
1197+
for (i = 0, new_num_src = 0; i < rename_src_nr; i++) {
1198+
struct diff_filespec *one = rename_src[i].p->one;
1199+
int val;
1200+
1201+
val = strintmap_get(relevant_sources, one->path);
1202+
1203+
/*
1204+
* sources that were not found in relevant_sources should
1205+
* have already been removed by a prior call to
1206+
* remove_unneeded_paths_from_src()
1207+
*/
1208+
assert(val != -1);
1209+
1210+
if (val == RELEVANT_LOCATION) {
1211+
int removable = 1;
1212+
char *dir = get_dirname(one->path);
1213+
while (1) {
1214+
char *freeme = dir;
1215+
int res = strintmap_get(dirs_removed, dir);
1216+
1217+
/* Quit if not found or irrelevant */
1218+
if (res == NOT_RELEVANT)
1219+
break;
1220+
/* If RELEVANT_FOR_SELF, can't remove */
1221+
if (res == RELEVANT_FOR_SELF) {
1222+
removable = 0;
1223+
break;
1224+
}
1225+
/* Else continue searching upwards */
1226+
assert(res == RELEVANT_FOR_ANCESTOR);
1227+
dir = get_dirname(dir);
1228+
free(freeme);
1229+
}
1230+
free(dir);
1231+
if (removable) {
1232+
strintmap_set(relevant_sources, one->path,
1233+
RELEVANT_NO_MORE);
1234+
continue;
1235+
}
1236+
}
1237+
1238+
if (new_num_src < i)
1239+
memcpy(&rename_src[new_num_src], &rename_src[i],
1240+
sizeof(struct diff_rename_src));
1241+
new_num_src++;
1242+
}
1243+
1244+
rename_src_nr = new_num_src;
11961245
}
11971246

11981247
void diffcore_rename_extended(struct diff_options *options,

0 commit comments

Comments
 (0)