Skip to content

Commit ae0560c

Browse files
committed
merge-ort: skip rename detection entirely if possible
diffcore_rename_extended() will do a bunch of setup, then check for exact renames, then abort before inexact rename detection if there are no more sources or destinations that need to be matched. It will sometimes be the case, however, that either * we start with neither any sources or destinations * we start with no *relevant* sources In the first of these two cases, the setup and exact rename detection will be very cheap since there are 0 files to operate on. In the second case, it is quite possible to have thousands of files with none of the source ones being relevant. Avoid calling diffcore_rename_extended() or even some of the setup before diffcore_rename_extended() when we can determine that rename detection is unnecessary. 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: 6.110 s ± 0.074 s 5.607 s ± 0.068 s mega-renames: 114.944 s ± 0.488 s 102.714 s ± 0.233 s just-one-mega: 3.551 s ± 0.018 s 3.511 s ± 0.017 s Signed-off-by: Elijah Newren <[email protected]>
1 parent f362ae4 commit ae0560c

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

merge-ort.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,6 +2158,19 @@ static int process_renames(struct merge_options *opt,
21582158
return clean_merge;
21592159
}
21602160

2161+
static inline int possible_side_renames(struct rename_info *renames,
2162+
unsigned side_index)
2163+
{
2164+
return renames->pairs[side_index].nr > 0 &&
2165+
!strset_empty(&renames->relevant_sources[side_index]);
2166+
}
2167+
2168+
static inline int possible_renames(struct rename_info *renames)
2169+
{
2170+
return possible_side_renames(renames, 1) ||
2171+
possible_side_renames(renames, 2);
2172+
}
2173+
21612174
static void resolve_diffpair_statuses(struct diff_queue_struct *q)
21622175
{
21632176
/*
@@ -2194,6 +2207,16 @@ static void detect_regular_renames(struct merge_options *opt,
21942207
struct diff_options diff_opts;
21952208
struct rename_info *renames = &opt->priv->renames;
21962209

2210+
if (!possible_side_renames(renames, side_index)) {
2211+
/*
2212+
* No rename detection needed for this side, but we still need
2213+
* to make sure 'adds' are marked correctly in case the other
2214+
* side had directory renames.
2215+
*/
2216+
resolve_diffpair_statuses(&renames->pairs[side_index]);
2217+
return;
2218+
}
2219+
21972220
repo_diff_setup(opt->repo, &diff_opts);
21982221
diff_opts.flags.recursive = 1;
21992222
diff_opts.flags.rename_empty = 0;
@@ -2311,6 +2334,8 @@ static int detect_and_process_renames(struct merge_options *opt,
23112334
int need_dir_renames, s, clean = 1;
23122335

23132336
memset(&combined, 0, sizeof(combined));
2337+
if (!possible_renames(renames))
2338+
goto cleanup;
23142339

23152340
trace2_region_enter("merge", "regular renames", opt->repo);
23162341
detect_regular_renames(opt, MERGE_SIDE1);
@@ -2345,6 +2370,26 @@ static int detect_and_process_renames(struct merge_options *opt,
23452370
clean &= process_renames(opt, &combined);
23462371
trace2_region_leave("merge", "process renames", opt->repo);
23472372

2373+
goto simple_cleanup; /* collect_renames() handles some of cleanup */
2374+
2375+
cleanup:
2376+
/*
2377+
* Free now unneeded filepairs, which would have been handled
2378+
* in collect_renames() normally but we're about to skip that
2379+
* code...
2380+
*/
2381+
for (s = MERGE_SIDE1; s <= MERGE_SIDE2; s++) {
2382+
struct diff_queue_struct *side_pairs;
2383+
int i;
2384+
2385+
side_pairs = &renames->pairs[s];
2386+
for (i = 0; i < side_pairs->nr; ++i) {
2387+
struct diff_filepair *p = side_pairs->queue[i];
2388+
diff_free_filepair(p);
2389+
}
2390+
}
2391+
2392+
simple_cleanup:
23482393
/* Free memory for renames->pairs[] and combined */
23492394
for (s = MERGE_SIDE1; s <= MERGE_SIDE2; s++) {
23502395
free(renames->pairs[s].queue);

0 commit comments

Comments
 (0)