Skip to content

perf(fuzzy): match only the previous results when the query gets longer - #914

Open
dmtrKovalenko wants to merge 2 commits into
mainfrom
perf/fuzzy-search-pool-incremental
Open

dmtrKovalenko wants to merge 2 commits into
mainfrom
perf/fuzzy-search-pool-incremental

Conversation

@dmtrKovalenko

@dmtrKovalenko dmtrKovalenko commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner

Fuzzy file search keeps the set of files that the last plain-text query matched. When the next query extends that query and the typo budget (len / 4, clamped to 2..=6) stays the same, the search matches only that set instead of all files. Adding, restoring or replacing files clears the set.


A path that matches a needle within k typos also matches every prefix of that needle within k typos, so the reduced set gives the same results. Scoring, filename fallback, sorting and pagination run unchanged on the matched files.

Chromium, ~500k files, max_threads = 4 main this PR
typing, p50 per keystroke (2 runs) 28.4 / 31.3 ms 19.4 / 19.6 ms
typing, p90 54.0 / 55.8 ms 41.4 / 40.6 ms
typing, p99 99.9 / 81.4 ms 66.4 / 65.8 ms
single query, p50 (no previous query) 35.4 / 36.5 ms 36.3 / 35.2 ms

Typing = each of 60 file names typed one character at a time with a 40 ms gap. Single queries do not change, because they have no previous query to reuse.

Note

The cache applies only to plain-text queries without constraints. Multi-part queries (dir name) and queries with constraints (*.rs, status:modified) use the full search as before.

Correctness

  • New test incremental_typing_matches_full_search: 40k paths, typing with typos, backspace and a typo budget change. Each keystroke must give the same items, order and scores as a full search.
  • Chromium check: 11,163 keystrokes over 450 typing sessions, each compared with a full search on the same picker: 0 mismatches.
  • make test-rust and make lint-rust pass.

Cache invalidation

Event Cache
file appended (watcher) cleared
file restored after delete cleared
full rescan / commit_new_sync / collect_files cleared
get_file_mut (public) cleared
file deleted kept: deleted files are skipped when matching
file count or base count changed cache not used

Summary by CodeRabbit

  • Performance
    • Improved responsiveness when refining plain-text file searches by reusing relevant matches from earlier queries.
    • Search results continue to be scored and paginated as before.
    • Other search types and queries that cannot reuse prior matches continue to use the standard search behavior.

When a plain-text query extends the previous query and the typo budget stays
the same, fuzzy file search matches only the files that the previous query
matched. Adding, restoring or replacing files clears the cached match set.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b1c98421-04af-44a1-a827-4df83320c0a6
📥 Commits

Reviewing files that changed from the base of the PR and between 616787f and be2acdd.

📒 Files selected for processing (1)
  • crates/fff-core/src/score.rs

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📝 Walkthrough

The fuzzy scorer reuses cached candidate matches for eligible incremental text queries. FilePicker stores the cache and clears it when indexed files change.

Changes: Fuzzy-search cache

Layer / File(s) Summary
Cache eligibility and candidate scoring
crates/fff-core/src/score.rs
The scorer reuses candidates when the query and file counts meet cache conditions. Tests compare cached results with full matching, including result identities and scores.
FilePicker cache lifecycle
crates/fff-core/src/file_picker.rs
FilePicker passes the cache to scoring and clears it when mutable file access or file updates can change indexed data.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Refactor

Suggested reviewers: gustav-fff

Merge Risk: ⚪ Minimal · up to be2ac

The cache appears to preserve incremental search results and reflect current indexed-file state. No actionable merge-blocking risk is established; the change is ready for normal checks.

Pre-merge checks · Passed 4 · Failed 1

Failed Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 51.85% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 27 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks (4 passed)
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main performance change: reusing previous fuzzy-match results for longer queries.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔇 Additional comments (3)
crates/fff-core/src/score.rs (1)

160-203: LGTM!

Also applies to: 685-757, 1199-1264, 1452-1454, 1484-1527, 1529-1574, 2029-2029, 2108-2108, 2350-2350, 2438-2439, 2549-2549, 2600-2600

crates/fff-core/src/file_picker.rs (1)

41-43: LGTM!

Also applies to: 611-612, 725-725, 937-937, 1042-1042, 1152-1161, 1533-1533, 1780-1780, 1816-1816

crates/fff-core/src/score.rs-1528-1528 (1)

1528-1528: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

⚠️ Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.

The "Spell Check with Typos" check flags "omnibx_veiw".

The typo is on purpose and the test needs it. The check reports veiw, so it will keep firing. Exclude this word in the typos config, or build the string so the checker does not see it (for example, concat!("omnibx_v", "eiw")).

Source: Linters/SAST tools


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ba059de0-006f-4a8d-ab3f-ba1caabbeccd
📥 Commits

Reviewing files that changed from the base of the PR and between f64bab2 and 616787f.

📒 Files selected for processing (2)
  • crates/fff-core/src/file_picker.rs
  • crates/fff-core/src/score.rs

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant