From 601be0d480b36e62ca60c8241a659c657f1fb09f Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Tue, 28 Nov 2023 10:41:02 +0900 Subject: [PATCH] working_copy: narrow file_states recursively while visiting directories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This saves another ~10ms. Without watchman: ``` % hyperfine --sort command --warmup 3 --runs 20 -L bin jj-1,jj-2 \ "target/release-with-debug/{bin} -R ~/mirrors/linux files ~/mirrors/linux/no-match" Benchmark 2: target/release-with-debug/jj-1 -R ~/mirrors/linux files ~/mirrors/linux/no-match Time (mean ± σ): 327.7 ms ± 24.9 ms [User: 1059.1 ms, System: 654.3 ms] Range (min … max): 296.0 ms … 385.4 ms 20 runs Benchmark 3: target/release-with-debug/jj-2 -R ~/mirrors/linux files ~/mirrors/linux/no-match Time (mean ± σ): 311.0 ms ± 24.8 ms [User: 960.0 ms, System: 643.1 ms] Range (min … max): 274.9 ms … 358.5 ms 20 runs ``` --- lib/src/local_working_copy.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/src/local_working_copy.rs b/lib/src/local_working_copy.rs index 256cab3b4..53135e5dc 100644 --- a/lib/src/local_working_copy.rs +++ b/lib/src/local_working_copy.rs @@ -467,10 +467,11 @@ struct FsmonitorMatcher { watchman_clock: Option, } -struct DirectoryToVisit { +struct DirectoryToVisit<'a> { dir: RepoPathBuf, disk_dir: PathBuf, git_ignore: Arc, + file_states: FileStates<'a>, } #[derive(Debug, Error)] @@ -749,6 +750,7 @@ impl TreeState { dir: RepoPathBuf::root(), disk_dir: self.working_copy_path.clone(), git_ignore: base_ignores, + file_states: self.file_states.all(), }; self.visit_directory( &matcher, @@ -837,14 +839,13 @@ impl TreeState { dir, disk_dir, git_ignore, + file_states, } = directory_to_visit; if matcher.visit(&dir).is_nothing() { return Ok(()); } - // TODO: maybe file_states can be narrowed by the dir path? - let file_states = self.file_states.all(); let git_ignore = git_ignore.chain_with_file(&dir.to_internal_dir_string(), disk_dir.join(".gitignore")); let dir_entries = disk_dir @@ -881,11 +882,11 @@ impl TreeState { } if file_type.is_dir() { + let file_states = file_states.prefixed(&path); if git_ignore.matches(&path.to_internal_dir_string()) { // If the whole directory is ignored, visit only paths we're already // tracking. - let tracked_paths = file_states.prefixed(&path); - for (tracked_path, current_file_state) in tracked_paths { + for (tracked_path, current_file_state) in file_states { if !matcher.matches(tracked_path) { continue; } @@ -931,6 +932,7 @@ impl TreeState { dir: path, disk_dir: entry.path(), git_ignore: git_ignore.clone(), + file_states, }; self.visit_directory( matcher,