Skip to content

Commit bf69da5

Browse files
committed
Merge branch 'nk/diff-files-vs-fsmonitor'
"git diff" and other commands that share the same machinery to compare with working tree files have been taught to take advantage of the fsmonitor data when available. * nk/diff-files-vs-fsmonitor: p7519-fsmonitor: add a git add benchmark p7519-fsmonitor: refactor to avoid code duplication perf lint: add make test-lint to perf tests t/perf: add fsmonitor perf test for git diff t/perf/p7519-fsmonitor.sh: warm cache on first git status t/perf/README: elaborate on output format fsmonitor: use fsmonitor data in `git diff`
2 parents b3ae46a + 2bfa953 commit bf69da5

File tree

6 files changed

+81
-50
lines changed

6 files changed

+81
-50
lines changed

diff-lib.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
9898

9999
diff_set_mnemonic_prefix(&revs->diffopt, "i/", "w/");
100100

101+
refresh_fsmonitor(istate);
102+
101103
if (diff_unmerged_stage < 0)
102104
diff_unmerged_stage = 2;
103105
entries = istate->cache_nr;
@@ -198,8 +200,17 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
198200
if (ce_uptodate(ce) || ce_skip_worktree(ce))
199201
continue;
200202

201-
/* If CE_VALID is set, don't look at workdir for file removal */
202-
if (ce->ce_flags & CE_VALID) {
203+
/*
204+
* When CE_VALID is set (via "update-index --assume-unchanged"
205+
* or via adding paths while core.ignorestat is set to true),
206+
* the user has promised that the working tree file for that
207+
* path will not be modified. When CE_FSMONITOR_VALID is true,
208+
* the fsmonitor knows that the path hasn't been modified since
209+
* we refreshed the cached stat information. In either case,
210+
* we do not have to stat to see if the path has been removed
211+
* or modified.
212+
*/
213+
if (ce->ce_flags & (CE_VALID | CE_FSMONITOR_VALID)) {
203214
changed = 0;
204215
newmode = ce->ce_mode;
205216
} else {

t/Makefile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ CHAINLINTTMP_SQ = $(subst ','\'',$(CHAINLINTTMP))
3434
T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
3535
TGITWEB = $(sort $(wildcard t95[0-9][0-9]-*.sh))
3636
THELPERS = $(sort $(filter-out $(T),$(wildcard *.sh)))
37+
TPERF = $(sort $(wildcard perf/p[0-9][0-9][0-9][0-9]-*.sh))
3738
CHAINLINTTESTS = $(sort $(patsubst chainlint/%.test,%,$(wildcard chainlint/*.test)))
3839
CHAINLINT = sed -f chainlint.sed
3940

@@ -81,17 +82,17 @@ test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax \
8182
test-lint-filenames
8283

8384
test-lint-duplicates:
84-
@dups=`echo $(T) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \
85+
@dups=`echo $(T) $(TPERF) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \
8586
test -z "$$dups" || { \
8687
echo >&2 "duplicate test numbers:" $$dups; exit 1; }
8788

8889
test-lint-executable:
89-
@bad=`for i in $(T); do test -x "$$i" || echo $$i; done` && \
90+
@bad=`for i in $(T) $(TPERF); do test -x "$$i" || echo $$i; done` && \
9091
test -z "$$bad" || { \
9192
echo >&2 "non-executable tests:" $$bad; exit 1; }
9293

9394
test-lint-shell-syntax:
94-
@'$(PERL_PATH_SQ)' check-non-portable-shell.pl $(T) $(THELPERS)
95+
@'$(PERL_PATH_SQ)' check-non-portable-shell.pl $(T) $(THELPERS) $(TPERF)
9596

9697
test-lint-filenames:
9798
@# We do *not* pass a glob to ls-files but use grep instead, to catch

t/perf/Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
-include ../../config.mak
22
export GIT_TEST_OPTIONS
33

4-
all: perf
4+
all: test-lint perf
55

66
perf: pre-clean
77
./run
@@ -12,4 +12,7 @@ pre-clean:
1212
clean:
1313
rm -rf build "trash directory".* test-results
1414

15+
test-lint:
16+
$(MAKE) -C .. test-lint
17+
1518
.PHONY: all perf pre-clean clean

t/perf/README

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ the tests on the current git repository.
2828
7810.3: grep --cached, cheap regex 3.07(3.02+0.25)
2929
7810.4: grep --cached, expensive regex 9.39(30.57+0.24)
3030

31+
Output format is in seconds "Elapsed(User + System)"
32+
3133
You can compare multiple repositories and even git revisions with the
3234
'run' script:
3335

t/perf/p3400-rebase.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ test_expect_success 'setup rebasing on top of a lot of changes' '
99
git checkout -f -B base &&
1010
git checkout -B to-rebase &&
1111
git checkout -B upstream &&
12-
for i in $(seq 100)
12+
for i in $(test_seq 100)
1313
do
1414
# simulate huge diffs
1515
echo change$i >unrelated-file$i &&
16-
seq 1000 >>unrelated-file$i &&
16+
test_seq 1000 >>unrelated-file$i &&
1717
git add unrelated-file$i &&
1818
test_tick &&
1919
git commit -m commit$i unrelated-file$i &&
2020
echo change$i >unrelated-file$i &&
21-
seq 1000 | tac >>unrelated-file$i &&
21+
test_seq 1000 | tac >>unrelated-file$i &&
2222
git add unrelated-file$i &&
2323
test_tick &&
2424
git commit -m commit$i-reverse unrelated-file$i ||

t/perf/p7519-fsmonitor.sh

Lines changed: 55 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -114,63 +114,77 @@ test_expect_success "setup for fsmonitor" '
114114
fi &&
115115
116116
git config core.fsmonitor "$INTEGRATION_SCRIPT" &&
117-
git update-index --fsmonitor
117+
git update-index --fsmonitor &&
118+
mkdir 1_file 10_files 100_files 1000_files 10000_files &&
119+
for i in $(test_seq 1 10); do touch 10_files/$i; done &&
120+
for i in $(test_seq 1 100); do touch 100_files/$i; done &&
121+
for i in $(test_seq 1 1000); do touch 1000_files/$i; done &&
122+
for i in $(test_seq 1 10000); do touch 10000_files/$i; done &&
123+
git add 1_file 10_files 100_files 1000_files 10000_files &&
124+
git commit -m "Add files" &&
125+
git status # Warm caches
118126
'
119127

120-
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
121-
test-tool drop-caches
122-
fi
128+
test_perf_w_drop_caches () {
129+
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
130+
test-tool drop-caches
131+
fi
123132

124-
test_perf "status (fsmonitor=$INTEGRATION_SCRIPT)" '
125-
git status
126-
'
133+
test_perf "$@"
134+
}
127135

128-
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
129-
test-tool drop-caches
130-
fi
136+
test_fsmonitor_suite() {
137+
test_perf_w_drop_caches "status (fsmonitor=$INTEGRATION_SCRIPT)" '
138+
git status
139+
'
131140

132-
test_perf "status -uno (fsmonitor=$INTEGRATION_SCRIPT)" '
133-
git status -uno
134-
'
141+
test_perf_w_drop_caches "status -uno (fsmonitor=$INTEGRATION_SCRIPT)" '
142+
git status -uno
143+
'
135144

136-
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
137-
test-tool drop-caches
138-
fi
145+
test_perf_w_drop_caches "status -uall (fsmonitor=$INTEGRATION_SCRIPT)" '
146+
git status -uall
147+
'
139148

140-
test_perf "status -uall (fsmonitor=$INTEGRATION_SCRIPT)" '
141-
git status -uall
142-
'
149+
test_perf_w_drop_caches "diff (fsmonitor=$INTEGRATION_SCRIPT)" '
150+
git diff
151+
'
143152

144-
test_expect_success "setup without fsmonitor" '
145-
unset INTEGRATION_SCRIPT &&
146-
git config --unset core.fsmonitor &&
147-
git update-index --no-fsmonitor
148-
'
153+
test_perf_w_drop_caches "diff -- 0_files (fsmonitor=$INTEGRATION_SCRIPT)" '
154+
git diff -- 1_file
155+
'
149156

150-
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
151-
test-tool drop-caches
152-
fi
157+
test_perf_w_drop_caches "diff -- 10_files (fsmonitor=$INTEGRATION_SCRIPT)" '
158+
git diff -- 10_files
159+
'
153160

154-
test_perf "status (fsmonitor=$INTEGRATION_SCRIPT)" '
155-
git status
156-
'
161+
test_perf_w_drop_caches "diff -- 100_files (fsmonitor=$INTEGRATION_SCRIPT)" '
162+
git diff -- 100_files
163+
'
157164

158-
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
159-
test-tool drop-caches
160-
fi
165+
test_perf_w_drop_caches "diff -- 1000_files (fsmonitor=$INTEGRATION_SCRIPT)" '
166+
git diff -- 1000_files
167+
'
161168

162-
test_perf "status -uno (fsmonitor=$INTEGRATION_SCRIPT)" '
163-
git status -uno
164-
'
169+
test_perf_w_drop_caches "diff -- 10000_files (fsmonitor=$INTEGRATION_SCRIPT)" '
170+
git diff -- 10000_files
171+
'
165172

166-
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
167-
test-tool drop-caches
168-
fi
173+
test_perf_w_drop_caches "add (fsmonitor=$INTEGRATION_SCRIPT)" '
174+
git add --all
175+
'
176+
}
177+
178+
test_fsmonitor_suite
169179

170-
test_perf "status -uall (fsmonitor=$INTEGRATION_SCRIPT)" '
171-
git status -uall
180+
test_expect_success "setup without fsmonitor" '
181+
unset INTEGRATION_SCRIPT &&
182+
git config --unset core.fsmonitor &&
183+
git update-index --no-fsmonitor
172184
'
173185

186+
test_fsmonitor_suite
187+
174188
if test_have_prereq WATCHMAN
175189
then
176190
watchman watch-del "$GIT_WORK_TREE" >/dev/null 2>&1 &&

0 commit comments

Comments
 (0)