Skip to content

Commit 38f8805

Browse files
rscharfegitster
authored andcommitted
diff-index: don't queue unchanged filepairs with diff_change()
diff_cache() queues unchanged filepairs if the flag find_copies_harder is set, and uses diff_change() for that. This function allocates a filespec for each side, does a few other things that are unnecessary for unchanged filepairs and always sets the diff_flag has_changes, which is simply misleading in this case. Add a new streamlined function for queuing unchanged filepairs and use it in show_modified(), which is called by diff_cache() via oneway_diff() and do_oneway_diff(). It allocates only a single filespec for each filepair and uses it twice with reference counting. This has a measurable effect if there are a lot of them, like in the Linux repo: Benchmark 1: ./git_v2.52.0 -C ../linux diff --cached --find-copies-harder Time (mean ± σ): 31.8 ms ± 0.2 ms [User: 24.2 ms, System: 6.3 ms] Range (min … max): 31.5 ms … 32.3 ms 85 runs Benchmark 2: ./git -C ../linux diff --cached --find-copies-harder Time (mean ± σ): 23.9 ms ± 0.2 ms [User: 18.1 ms, System: 4.6 ms] Range (min … max): 23.5 ms … 24.4 ms 111 runs Summary ./git -C ../linux diff --cached --find-copies-harder ran 1.33 ± 0.01 times faster than ./git_v2.52.0 -C ../linux diff --cached --find-copies-harder Signed-off-by: René Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 9a2fb14 commit 38f8805

File tree

3 files changed

+31
-7
lines changed

3 files changed

+31
-7
lines changed

diff-lib.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -418,13 +418,12 @@ static int show_modified(struct rev_info *revs,
418418
}
419419

420420
oldmode = old_entry->ce_mode;
421-
if (mode == oldmode && oideq(oid, &old_entry->oid) && !dirty_submodule &&
422-
!revs->diffopt.flags.find_copies_harder)
423-
return 0;
424-
425-
diff_change(&revs->diffopt, oldmode, mode,
426-
&old_entry->oid, oid, 1, !is_null_oid(oid),
427-
old_entry->name, 0, dirty_submodule);
421+
if (mode != oldmode || !oideq(oid, &old_entry->oid) || dirty_submodule)
422+
diff_change(&revs->diffopt, oldmode, mode,
423+
&old_entry->oid, oid, 1, !is_null_oid(oid),
424+
old_entry->name, 0, dirty_submodule);
425+
else if (revs->diffopt.flags.find_copies_harder)
426+
diff_same(&revs->diffopt, mode, oid, old_entry->name);
428427
return 0;
429428
}
430429

diff.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7347,6 +7347,26 @@ void diff_change(struct diff_options *options,
73477347
concatpath, old_dirty_submodule, new_dirty_submodule);
73487348
}
73497349

7350+
void diff_same(struct diff_options *options,
7351+
unsigned mode,
7352+
const struct object_id *oid,
7353+
const char *concatpath)
7354+
{
7355+
struct diff_filespec *one;
7356+
7357+
if (S_ISGITLINK(mode) && is_submodule_ignored(concatpath, options))
7358+
return;
7359+
7360+
if (options->prefix &&
7361+
strncmp(concatpath, options->prefix, options->prefix_length))
7362+
return;
7363+
7364+
one = alloc_filespec(concatpath);
7365+
fill_filespec(one, oid, 1, mode);
7366+
one->count++;
7367+
diff_queue(&diff_queued_diff, one, one);
7368+
}
7369+
73507370
struct diff_filepair *diff_unmerge(struct diff_options *options, const char *path)
73517371
{
73527372
struct diff_filepair *pair;

diff.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,11 @@ void diff_change(struct diff_options *,
572572
const char *fullpath,
573573
unsigned dirty_submodule1, unsigned dirty_submodule2);
574574

575+
void diff_same(struct diff_options *,
576+
unsigned mode,
577+
const struct object_id *oid,
578+
const char *fullpath);
579+
575580
struct diff_filepair *diff_unmerge(struct diff_options *, const char *path);
576581

577582
void compute_diffstat(struct diff_options *options, struct diffstat_t *diffstat,

0 commit comments

Comments
 (0)