perf(picker): stream and cache file discovery - #352
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Find Files waits for the entire workspace scan before showing results, and filtering large file lists can block input. On a checkout with more than a million eligible files, this leaves the picker looking stuck on “Loading files…”.
This PR streams discovery results into the picker and moves matching and sorting off the UI thread. Typing, navigation, and cancellation remain responsive while files arrive. Existing ignore rules, filename/path ranking, previews, and
file:linenavigation are preserved without a file-count cutoff.Completed indexes are reused within the editor.
Ctrl+rrefreshes the index;Ctrl+eswitches hidden/ignored visibility. Refresh keeps the previous complete results searchable, including after cancellation. Automatic selection follows the best match until the user navigates, after which updates preserve the selected path. Enter cannot accept a result from an older query, and discovery errors end with an explicit incomplete status.The cache is keyed by canonical root and visibility. It refreshes on reopening after 30 seconds or after known file-list changes; ordinary saves of indexed source files do not rescan. External changes require refresh or expiry. Unused indexes are evicted beyond four entries or 1 GiB of estimated row storage. Active indexes remain complete, so this is not a process-memory limit and refresh can temporarily retain two snapshots. The behavior and benchmark are documented in
docs/performance.md.Validation
Validated the pushed head
45a65a2c: 3,549 tests passed, 3 ignored, with formatting and Clippy clean across all targets and features. Seven TUI smoke scenarios passed, including cancelled refresh, visibility rules, rapid query changes, and line navigation.On a local checkout with 1,252,204 eligible files, two final release benchmark runs produced the same complete path hash as the serial walker:
The final TUI pass showed initial results in 122 ms; full discovery took 4.96 s initially and 13.24 s during refresh. These are local measurements, not CI thresholds: filesystem caches were not flushed and host load was not controlled. LSP and AI were disabled in the isolated smoke profiles.
How to Test
Build with
cargo build --release --bin red, then runtarget/release/red --root /path/to/large-workspace /path/to/large-workspace/existing-file. PressCtrl+pand type a known filename while scanning. Results should appear before scanning completes, input should remain responsive, and better matches should rise to the top until you navigate the list. After navigating, the selected path should remain stable as more files arrive.After discovery completes, close and reopen the picker within 30 seconds. Results should appear from the cache. Search for a file with at least 20 lines using
filename:20, wait for matching to finish, then press Enter; it should open at line 20.Press
Ctrl+r, close the picker while it reports refreshing, then reopen it. The previous complete results should remain searchable while the replacement scan runs. Add a file externally and refresh again; the new file should appear. In a fixture with hidden and ignored files,Ctrl+eshould expose those files while still excluding.gitand.baremetadata.Run
cargo test --release --lib ui::file_pickerandcargo test --release --lib workspace_paths::tests. These cover stale-query acceptance, manual selection, refresh cancellation, cache invalidation, missing roots, and parallel/serial file-set parity. For a large-workspace measurement with full parity checking, run:RED_FILE_PICKER_BENCH_ROOT=/path/to/large-workspace RED_FILE_PICKER_VERIFY_PARITY=1 \ cargo test --release --lib file_picker_streaming_large_workspace_performance \ -- --ignored --nocapture --test-threads=1Expect the complete file count and hash to match the serial walker, with separate timings for first results, complete discovery, queries, cached reopening, and cancellation.