Files
git-mirror/t/perf/p3904-stash-patch.sh
Adam Johnson 48513e05e2 stash: reuse cached index entries in --patch temporary index
`git stash -p` prepares the interactive selection by creating a
temporary index at HEAD, switching `GIT_INDEX_FILE` to it, and then
running the `add -p` machinery.

That temporary index was created by running `git read-tree HEAD`.  The
resulting index had no useful cached stat data or fsmonitor-valid bits
from the real index.  When `run_add_p()` refreshed that temporary index
before showing the first prompt, it could end up lstat(2)-ing every
tracked file, even in a repository where `git diff` and `git restore -p`
can use fsmonitor to avoid that work.

Create the temporary index in-process instead.  Use `unpack_trees()` to
reset the real index contents to HEAD while writing the result to the
temporary index path.  For paths whose index entries already match HEAD,
`oneway_merge()` reuses the existing cache entries, preserving their
cached stat data and `CE_FSMONITOR_VALID` state.

This makes the refresh performed by `run_add_p()` behave like the one
used by `git restore -p`: unchanged paths can be skipped via fsmonitor
instead of being scanned again.

In a 206k file repository with `core.fsmonitor` enabled and a one-line
change in one file, time to first prompt dropped from 34.774 seconds to
0.659 seconds. The new perf test file demonstrates similar improvements,
with maen times for without- and with-fsmonitor cases dropping from 6.90
and 6.83 seconds to 0.55 and 0.28 seconds, respectively.

Signed-off-by: Adam Johnson <me@adamj.eu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-05-24 18:43:22 +09:00

44 lines
962 B
Bash
Executable File

#!/bin/sh
test_description="Performance tests for git stash -p"
. ./perf-lib.sh
test_perf_fresh_repo
test_expect_success "setup" '
mkdir files &&
test_seq 1 100000 | while read i; do
echo "content $i" >files/$i.txt || return 1
done &&
git add files/ &&
git commit -q -m "add tracked files" &&
echo modified >files/1.txt
'
test_perf "stash -p, no fsmonitor" \
--setup 'echo modified >files/1.txt' '
printf "q\n" | git stash -p >/dev/null 2>&1 || true
'
if test_have_prereq FSMONITOR_DAEMON
then
test_expect_success "enable builtin fsmonitor" '
git config core.fsmonitor true &&
git fsmonitor--daemon start &&
git update-index --fsmonitor &&
git status >/dev/null 2>&1
'
test_perf "stash -p, builtin fsmonitor" \
--setup 'echo modified >files/1.txt && git status >/dev/null 2>&1' '
printf "q\n" | git stash -p >/dev/null 2>&1 || true
'
test_expect_success "stop builtin fsmonitor" '
git fsmonitor--daemon stop
'
fi
test_done