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`
This commit is contained in:
Junio C Hamano 2020-11-09 14:06:25 -08:00
Родитель b3ae46a936 2bfa953e5d
Коммит bf69da56c9
6 изменённых файлов: 82 добавлений и 51 удалений

Просмотреть файл

@ -98,6 +98,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
diff_set_mnemonic_prefix(&revs->diffopt, "i/", "w/");
refresh_fsmonitor(istate);
if (diff_unmerged_stage < 0)
diff_unmerged_stage = 2;
entries = istate->cache_nr;
@ -198,8 +200,17 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
if (ce_uptodate(ce) || ce_skip_worktree(ce))
continue;
/* If CE_VALID is set, don't look at workdir for file removal */
if (ce->ce_flags & CE_VALID) {
/*
* When CE_VALID is set (via "update-index --assume-unchanged"
* or via adding paths while core.ignorestat is set to true),
* the user has promised that the working tree file for that
* path will not be modified. When CE_FSMONITOR_VALID is true,
* the fsmonitor knows that the path hasn't been modified since
* we refreshed the cached stat information. In either case,
* we do not have to stat to see if the path has been removed
* or modified.
*/
if (ce->ce_flags & (CE_VALID | CE_FSMONITOR_VALID)) {
changed = 0;
newmode = ce->ce_mode;
} else {

Просмотреть файл

@ -34,6 +34,7 @@ CHAINLINTTMP_SQ = $(subst ','\'',$(CHAINLINTTMP))
T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
TGITWEB = $(sort $(wildcard t95[0-9][0-9]-*.sh))
THELPERS = $(sort $(filter-out $(T),$(wildcard *.sh)))
TPERF = $(sort $(wildcard perf/p[0-9][0-9][0-9][0-9]-*.sh))
CHAINLINTTESTS = $(sort $(patsubst chainlint/%.test,%,$(wildcard chainlint/*.test)))
CHAINLINT = sed -f chainlint.sed
@ -81,17 +82,17 @@ test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax \
test-lint-filenames
test-lint-duplicates:
@dups=`echo $(T) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \
@dups=`echo $(T) $(TPERF) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \
test -z "$$dups" || { \
echo >&2 "duplicate test numbers:" $$dups; exit 1; }
test-lint-executable:
@bad=`for i in $(T); do test -x "$$i" || echo $$i; done` && \
@bad=`for i in $(T) $(TPERF); do test -x "$$i" || echo $$i; done` && \
test -z "$$bad" || { \
echo >&2 "non-executable tests:" $$bad; exit 1; }
test-lint-shell-syntax:
@'$(PERL_PATH_SQ)' check-non-portable-shell.pl $(T) $(THELPERS)
@'$(PERL_PATH_SQ)' check-non-portable-shell.pl $(T) $(THELPERS) $(TPERF)
test-lint-filenames:
@# We do *not* pass a glob to ls-files but use grep instead, to catch

Просмотреть файл

@ -1,7 +1,7 @@
-include ../../config.mak
export GIT_TEST_OPTIONS
all: perf
all: test-lint perf
perf: pre-clean
./run
@ -12,4 +12,7 @@ pre-clean:
clean:
rm -rf build "trash directory".* test-results
test-lint:
$(MAKE) -C .. test-lint
.PHONY: all perf pre-clean clean

Просмотреть файл

@ -28,6 +28,8 @@ the tests on the current git repository.
7810.3: grep --cached, cheap regex 3.07(3.02+0.25)
7810.4: grep --cached, expensive regex 9.39(30.57+0.24)
Output format is in seconds "Elapsed(User + System)"
You can compare multiple repositories and even git revisions with the
'run' script:

Просмотреть файл

@ -9,16 +9,16 @@ test_expect_success 'setup rebasing on top of a lot of changes' '
git checkout -f -B base &&
git checkout -B to-rebase &&
git checkout -B upstream &&
for i in $(seq 100)
for i in $(test_seq 100)
do
# simulate huge diffs
echo change$i >unrelated-file$i &&
seq 1000 >>unrelated-file$i &&
test_seq 1000 >>unrelated-file$i &&
git add unrelated-file$i &&
test_tick &&
git commit -m commit$i unrelated-file$i &&
echo change$i >unrelated-file$i &&
seq 1000 | tac >>unrelated-file$i &&
test_seq 1000 | tac >>unrelated-file$i &&
git add unrelated-file$i &&
test_tick &&
git commit -m commit$i-reverse unrelated-file$i ||

Просмотреть файл

@ -114,32 +114,68 @@ test_expect_success "setup for fsmonitor" '
fi &&
git config core.fsmonitor "$INTEGRATION_SCRIPT" &&
git update-index --fsmonitor
git update-index --fsmonitor &&
mkdir 1_file 10_files 100_files 1000_files 10000_files &&
for i in $(test_seq 1 10); do touch 10_files/$i; done &&
for i in $(test_seq 1 100); do touch 100_files/$i; done &&
for i in $(test_seq 1 1000); do touch 1000_files/$i; done &&
for i in $(test_seq 1 10000); do touch 10000_files/$i; done &&
git add 1_file 10_files 100_files 1000_files 10000_files &&
git commit -m "Add files" &&
git status # Warm caches
'
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
test-tool drop-caches
fi
test_perf_w_drop_caches () {
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
test-tool drop-caches
fi
test_perf "status (fsmonitor=$INTEGRATION_SCRIPT)" '
git status
'
test_perf "$@"
}
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
test-tool drop-caches
fi
test_fsmonitor_suite() {
test_perf_w_drop_caches "status (fsmonitor=$INTEGRATION_SCRIPT)" '
git status
'
test_perf "status -uno (fsmonitor=$INTEGRATION_SCRIPT)" '
git status -uno
'
test_perf_w_drop_caches "status -uno (fsmonitor=$INTEGRATION_SCRIPT)" '
git status -uno
'
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
test-tool drop-caches
fi
test_perf_w_drop_caches "status -uall (fsmonitor=$INTEGRATION_SCRIPT)" '
git status -uall
'
test_perf "status -uall (fsmonitor=$INTEGRATION_SCRIPT)" '
git status -uall
'
test_perf_w_drop_caches "diff (fsmonitor=$INTEGRATION_SCRIPT)" '
git diff
'
test_perf_w_drop_caches "diff -- 0_files (fsmonitor=$INTEGRATION_SCRIPT)" '
git diff -- 1_file
'
test_perf_w_drop_caches "diff -- 10_files (fsmonitor=$INTEGRATION_SCRIPT)" '
git diff -- 10_files
'
test_perf_w_drop_caches "diff -- 100_files (fsmonitor=$INTEGRATION_SCRIPT)" '
git diff -- 100_files
'
test_perf_w_drop_caches "diff -- 1000_files (fsmonitor=$INTEGRATION_SCRIPT)" '
git diff -- 1000_files
'
test_perf_w_drop_caches "diff -- 10000_files (fsmonitor=$INTEGRATION_SCRIPT)" '
git diff -- 10000_files
'
test_perf_w_drop_caches "add (fsmonitor=$INTEGRATION_SCRIPT)" '
git add --all
'
}
test_fsmonitor_suite
test_expect_success "setup without fsmonitor" '
unset INTEGRATION_SCRIPT &&
@ -147,29 +183,7 @@ test_expect_success "setup without fsmonitor" '
git update-index --no-fsmonitor
'
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
test-tool drop-caches
fi
test_perf "status (fsmonitor=$INTEGRATION_SCRIPT)" '
git status
'
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
test-tool drop-caches
fi
test_perf "status -uno (fsmonitor=$INTEGRATION_SCRIPT)" '
git status -uno
'
if test -n "$GIT_PERF_7519_DROP_CACHE"; then
test-tool drop-caches
fi
test_perf "status -uall (fsmonitor=$INTEGRATION_SCRIPT)" '
git status -uall
'
test_fsmonitor_suite
if test_have_prereq WATCHMAN
then