fuzzy_nucleo: Optimize path matching with CharBag prefilter and add benchmarks - #54112
Merged
yara-blue merged 1 commit intoApr 17, 2026
Merged
Conversation
feitreim
force-pushed
the
feat-fuzzy-paths-optimization
branch
from
April 16, 2026 19:44
1cd815a to
cb19df1
Compare
This was referenced Apr 16, 2026
Collaborator
Author
|
hey @yara-blue heres Part A from the larger PR, just the path optimizations. |
feitreim
force-pushed
the
feat-fuzzy-paths-optimization
branch
2 times, most recently
from
April 17, 2026 00:09
ccdfeab to
16b790a
Compare
…enchmarks - Add a CharBag prefilter on path candidates to skip irrelevant entries before invoking nucleo's matcher. - Use total_cmp for score ordering and binary_search on sorted matched char indices when reconstructing byte positions. - Make the internal matcher pool robust to a poisoned mutex. - Add a criterion benchmark comparing fuzzy_nucleo path matching against the existing fuzzy crate. Release Notes: - N/A
feitreim
force-pushed
the
feat-fuzzy-paths-optimization
branch
from
April 17, 2026 03:14
16b790a to
85c4650
Compare
Collaborator
Author
|
While I was implementing the string matching into some of the existing pickers, I realized a major source of regressions was the SmartCase handling, I explain this better in #54123 but I did think it made sense to backport these changes to the path matching as well. this change is better parity with |
yara-blue
reviewed
Apr 17, 2026
yara-blue
approved these changes
Apr 17, 2026
yara-blue
added a commit
that referenced
this pull request
Apr 20, 2026
…#54123) Stacked on top of #54112 This is part 2 of 3 towards #51197 More details from the original PR #53551 This PR includes the changes from #54112 , im not sure how to avoid that, my understanding is that after that one is merged, this PR can be rebased onto main and everything will be correct. You can also view the version of this that does reflect the changes more directly here: feitreim#1 ## Changes In this PR I added a more general string matching functionality to `fuzzy_nucleo`, in order to have proper testing for this, I also changed the command palette, tab switching picker, branch picker, and recent projects picker to use this new implementation. I think the command palette change in particular is awesome, just super nice to vaguely gesture at the command i want and have it pop right up. The main change here and departure from #37123 is realizing that the primary reason for the regressions is actually how nucleo handles smart case, the old `fuzzy` crate only uses the smart case argument to score things differently, while nucleo actually filters on the case, eg. with smart case query "Apple" wouldnt match "apple". To get around this we always pass `CaseMatching::Ignore` to nucleo and implement the same score modifications from fuzzy in our code. There is a performance cost to that, of course, but from my testing it is fairly static, not growing as the size increases, so maybe a query takes 35 µs instead of 25 µs, but a query that takes 800 µs will only take 820 µs. Benchmark: | kind | query | size | nucleo | fuzzy | nucleo/fuzzy | |---|---|---:|---:|---:|---:| | string | 1-word | 100 | 9.15 µs | 24.6 µs | 0.37× | | string | 1-word | 1000 | 150.2 µs | 207.2 µs | 0.72× | | string | 1-word | 10000 | 1.34 ms | 2.07 ms | 0.65× | | string | 2-word | 100 | 5.16 µs | 2.94 µs | 1.75× | | string | 2-word | 1000 | 29.0 µs | 11.0 µs | 2.63× | | string | 2-word | 10000 | 210.6 µs | 55.5 µs | 3.79× | | string | 4-word | 100 | 2.57 µs | 2.33 µs | 1.10× | | string | 4-word | 1000 | 6.98 µs | 5.85 µs | 1.19× | | string | 4-word | 10000 | 20.0 µs | 12.0 µs | 1.66× | When I added the 4-word queries to the benchmarks I was actually really concerned that the performance would be awful, making it unsuitable for the command palette especially. However, I think due to the CharBag pre-filtering when the query is longer, the performance is actually way better than the 2 word case. Video: https://github.com/user-attachments/assets/3cd7221b-424f-4fd3-8df1-5543dcc340a3 Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Improved fuzzy matching in the command palette, branch picker, tab switcher, and recent projects picker to support multi-word queries. --------- Co-authored-by: Yara <git@yara.blue>
14 tasks
kathbigra
pushed a commit
to kathbigra/zed
that referenced
this pull request
May 10, 2026
…enchmarks (zed-industries#54112) This PR was originally a part of zed-industries#53551 so theres more info about its motivation there. - Add a CharBag prefilter on path candidates to skip irrelevant entries before invoking nucleo's matcher. - Use binary_search on sorted matched char indices when reconstructing byte positions (perf improvement). - Add a criterion benchmark comparing `fuzzy_nucleo` path matching against the existing fuzzy crate. Performance Chart: | Benchmark | Size | Nucleo (before) | Nucleo (after) | Fuzzy | Before/Fuzzy | After/Fuzzy | |-----------|-----:|----------------:|---------------:|------:|-------------:|------------:| | 1-word | 100 | 14.14 µs | 9.12 µs | 9.06 µs | 1.56x | 1.01x | | 1-word | 1,000 | 164.37 µs | 114.11 µs | 110.43 µs | 1.49x | 1.03x | | 1-word | 10,000 | 1.83 ms | 1.39 ms | 1.41 ms | 1.30x | 0.99x | | 2-word | 100 | 12.83 µs | 3.51 µs | 979 ns | 13.10x | 3.59x | | 2-word | 1,000 | 131.65 µs | 33.46 µs | 6.37 µs | 20.67x | 5.25x | | 2-word | 10,000 | 1.24 ms | 338.84 µs | 52.46 µs | 23.64x | 6.46x |o Exact Current State: | query | size | nucleo | fuzzy | nucleo/fuzzy | |---|---:|---:|---:|---:| | 1-word | 100 | 8.62 µs | 9.22 µs | 0.93× | | 1-word | 1000 | 102 µs | 111 µs | 0.92× | | 1-word | 10000 | 1.13 ms | 1.28 ms | 0.88× | | 2-word | 100 | 3.48 µs | 0.98 µs | 3.55× | | 2-word | 1000 | 29.9 µs | 6.39 µs | 4.68× | | 2-word | 10000 | 271 µs | 53.4 µs | 5.08× | | 4-word | 100 | 0.85 µs | 0.53 µs | 1.60× | | 4-word | 1000 | 2.99 µs | 1.66 µs | 1.80× | | 4-word | 10000 | 20.1 µs | 9.14 µs | 2.20× | Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - fuzzy_nucleo: improved the performance of path matching
kathbigra
pushed a commit
to kathbigra/zed
that referenced
this pull request
May 10, 2026
…zed-industries#54123) Stacked on top of zed-industries#54112 This is part 2 of 3 towards zed-industries#51197 More details from the original PR zed-industries#53551 This PR includes the changes from zed-industries#54112 , im not sure how to avoid that, my understanding is that after that one is merged, this PR can be rebased onto main and everything will be correct. You can also view the version of this that does reflect the changes more directly here: feitreim#1 ## Changes In this PR I added a more general string matching functionality to `fuzzy_nucleo`, in order to have proper testing for this, I also changed the command palette, tab switching picker, branch picker, and recent projects picker to use this new implementation. I think the command palette change in particular is awesome, just super nice to vaguely gesture at the command i want and have it pop right up. The main change here and departure from zed-industries#37123 is realizing that the primary reason for the regressions is actually how nucleo handles smart case, the old `fuzzy` crate only uses the smart case argument to score things differently, while nucleo actually filters on the case, eg. with smart case query "Apple" wouldnt match "apple". To get around this we always pass `CaseMatching::Ignore` to nucleo and implement the same score modifications from fuzzy in our code. There is a performance cost to that, of course, but from my testing it is fairly static, not growing as the size increases, so maybe a query takes 35 µs instead of 25 µs, but a query that takes 800 µs will only take 820 µs. Benchmark: | kind | query | size | nucleo | fuzzy | nucleo/fuzzy | |---|---|---:|---:|---:|---:| | string | 1-word | 100 | 9.15 µs | 24.6 µs | 0.37× | | string | 1-word | 1000 | 150.2 µs | 207.2 µs | 0.72× | | string | 1-word | 10000 | 1.34 ms | 2.07 ms | 0.65× | | string | 2-word | 100 | 5.16 µs | 2.94 µs | 1.75× | | string | 2-word | 1000 | 29.0 µs | 11.0 µs | 2.63× | | string | 2-word | 10000 | 210.6 µs | 55.5 µs | 3.79× | | string | 4-word | 100 | 2.57 µs | 2.33 µs | 1.10× | | string | 4-word | 1000 | 6.98 µs | 5.85 µs | 1.19× | | string | 4-word | 10000 | 20.0 µs | 12.0 µs | 1.66× | When I added the 4-word queries to the benchmarks I was actually really concerned that the performance would be awful, making it unsuitable for the command palette especially. However, I think due to the CharBag pre-filtering when the query is longer, the performance is actually way better than the 2 word case. Video: https://github.com/user-attachments/assets/3cd7221b-424f-4fd3-8df1-5543dcc340a3 Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Improved fuzzy matching in the command palette, branch picker, tab switcher, and recent projects picker to support multi-word queries. --------- Co-authored-by: Yara <git@yara.blue>
Zenor27
pushed a commit
to Zenor27/zed
that referenced
this pull request
Jul 4, 2026
…enchmarks (zed-industries#54112) This PR was originally a part of zed-industries#53551 so theres more info about its motivation there. - Add a CharBag prefilter on path candidates to skip irrelevant entries before invoking nucleo's matcher. - Use binary_search on sorted matched char indices when reconstructing byte positions (perf improvement). - Add a criterion benchmark comparing `fuzzy_nucleo` path matching against the existing fuzzy crate. Performance Chart: | Benchmark | Size | Nucleo (before) | Nucleo (after) | Fuzzy | Before/Fuzzy | After/Fuzzy | |-----------|-----:|----------------:|---------------:|------:|-------------:|------------:| | 1-word | 100 | 14.14 µs | 9.12 µs | 9.06 µs | 1.56x | 1.01x | | 1-word | 1,000 | 164.37 µs | 114.11 µs | 110.43 µs | 1.49x | 1.03x | | 1-word | 10,000 | 1.83 ms | 1.39 ms | 1.41 ms | 1.30x | 0.99x | | 2-word | 100 | 12.83 µs | 3.51 µs | 979 ns | 13.10x | 3.59x | | 2-word | 1,000 | 131.65 µs | 33.46 µs | 6.37 µs | 20.67x | 5.25x | | 2-word | 10,000 | 1.24 ms | 338.84 µs | 52.46 µs | 23.64x | 6.46x |o Exact Current State: | query | size | nucleo | fuzzy | nucleo/fuzzy | |---|---:|---:|---:|---:| | 1-word | 100 | 8.62 µs | 9.22 µs | 0.93× | | 1-word | 1000 | 102 µs | 111 µs | 0.92× | | 1-word | 10000 | 1.13 ms | 1.28 ms | 0.88× | | 2-word | 100 | 3.48 µs | 0.98 µs | 3.55× | | 2-word | 1000 | 29.9 µs | 6.39 µs | 4.68× | | 2-word | 10000 | 271 µs | 53.4 µs | 5.08× | | 4-word | 100 | 0.85 µs | 0.53 µs | 1.60× | | 4-word | 1000 | 2.99 µs | 1.66 µs | 1.80× | | 4-word | 10000 | 20.1 µs | 9.14 µs | 2.20× | Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - fuzzy_nucleo: improved the performance of path matching
Zenor27
pushed a commit
to Zenor27/zed
that referenced
this pull request
Jul 4, 2026
…zed-industries#54123) Stacked on top of zed-industries#54112 This is part 2 of 3 towards zed-industries#51197 More details from the original PR zed-industries#53551 This PR includes the changes from zed-industries#54112 , im not sure how to avoid that, my understanding is that after that one is merged, this PR can be rebased onto main and everything will be correct. You can also view the version of this that does reflect the changes more directly here: feitreim#1 ## Changes In this PR I added a more general string matching functionality to `fuzzy_nucleo`, in order to have proper testing for this, I also changed the command palette, tab switching picker, branch picker, and recent projects picker to use this new implementation. I think the command palette change in particular is awesome, just super nice to vaguely gesture at the command i want and have it pop right up. The main change here and departure from zed-industries#37123 is realizing that the primary reason for the regressions is actually how nucleo handles smart case, the old `fuzzy` crate only uses the smart case argument to score things differently, while nucleo actually filters on the case, eg. with smart case query "Apple" wouldnt match "apple". To get around this we always pass `CaseMatching::Ignore` to nucleo and implement the same score modifications from fuzzy in our code. There is a performance cost to that, of course, but from my testing it is fairly static, not growing as the size increases, so maybe a query takes 35 µs instead of 25 µs, but a query that takes 800 µs will only take 820 µs. Benchmark: | kind | query | size | nucleo | fuzzy | nucleo/fuzzy | |---|---|---:|---:|---:|---:| | string | 1-word | 100 | 9.15 µs | 24.6 µs | 0.37× | | string | 1-word | 1000 | 150.2 µs | 207.2 µs | 0.72× | | string | 1-word | 10000 | 1.34 ms | 2.07 ms | 0.65× | | string | 2-word | 100 | 5.16 µs | 2.94 µs | 1.75× | | string | 2-word | 1000 | 29.0 µs | 11.0 µs | 2.63× | | string | 2-word | 10000 | 210.6 µs | 55.5 µs | 3.79× | | string | 4-word | 100 | 2.57 µs | 2.33 µs | 1.10× | | string | 4-word | 1000 | 6.98 µs | 5.85 µs | 1.19× | | string | 4-word | 10000 | 20.0 µs | 12.0 µs | 1.66× | When I added the 4-word queries to the benchmarks I was actually really concerned that the performance would be awful, making it unsuitable for the command palette especially. However, I think due to the CharBag pre-filtering when the query is longer, the performance is actually way better than the 2 word case. Video: https://github.com/user-attachments/assets/3cd7221b-424f-4fd3-8df1-5543dcc340a3 Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Improved fuzzy matching in the command palette, branch picker, tab switcher, and recent projects picker to support multi-word queries. --------- Co-authored-by: Yara <git@yara.blue>
jonx
pushed a commit
to jonx/zed-aros
that referenced
this pull request
Jul 17, 2026
…enchmarks (zed-industries#54112) This PR was originally a part of zed-industries#53551 so theres more info about its motivation there. - Add a CharBag prefilter on path candidates to skip irrelevant entries before invoking nucleo's matcher. - Use binary_search on sorted matched char indices when reconstructing byte positions (perf improvement). - Add a criterion benchmark comparing `fuzzy_nucleo` path matching against the existing fuzzy crate. Performance Chart: | Benchmark | Size | Nucleo (before) | Nucleo (after) | Fuzzy | Before/Fuzzy | After/Fuzzy | |-----------|-----:|----------------:|---------------:|------:|-------------:|------------:| | 1-word | 100 | 14.14 µs | 9.12 µs | 9.06 µs | 1.56x | 1.01x | | 1-word | 1,000 | 164.37 µs | 114.11 µs | 110.43 µs | 1.49x | 1.03x | | 1-word | 10,000 | 1.83 ms | 1.39 ms | 1.41 ms | 1.30x | 0.99x | | 2-word | 100 | 12.83 µs | 3.51 µs | 979 ns | 13.10x | 3.59x | | 2-word | 1,000 | 131.65 µs | 33.46 µs | 6.37 µs | 20.67x | 5.25x | | 2-word | 10,000 | 1.24 ms | 338.84 µs | 52.46 µs | 23.64x | 6.46x |o Exact Current State: | query | size | nucleo | fuzzy | nucleo/fuzzy | |---|---:|---:|---:|---:| | 1-word | 100 | 8.62 µs | 9.22 µs | 0.93× | | 1-word | 1000 | 102 µs | 111 µs | 0.92× | | 1-word | 10000 | 1.13 ms | 1.28 ms | 0.88× | | 2-word | 100 | 3.48 µs | 0.98 µs | 3.55× | | 2-word | 1000 | 29.9 µs | 6.39 µs | 4.68× | | 2-word | 10000 | 271 µs | 53.4 µs | 5.08× | | 4-word | 100 | 0.85 µs | 0.53 µs | 1.60× | | 4-word | 1000 | 2.99 µs | 1.66 µs | 1.80× | | 4-word | 10000 | 20.1 µs | 9.14 µs | 2.20× | Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - fuzzy_nucleo: improved the performance of path matching
jonx
pushed a commit
to jonx/zed-aros
that referenced
this pull request
Jul 17, 2026
…zed-industries#54123) Stacked on top of zed-industries#54112 This is part 2 of 3 towards zed-industries#51197 More details from the original PR zed-industries#53551 This PR includes the changes from zed-industries#54112 , im not sure how to avoid that, my understanding is that after that one is merged, this PR can be rebased onto main and everything will be correct. You can also view the version of this that does reflect the changes more directly here: feitreim#1 ## Changes In this PR I added a more general string matching functionality to `fuzzy_nucleo`, in order to have proper testing for this, I also changed the command palette, tab switching picker, branch picker, and recent projects picker to use this new implementation. I think the command palette change in particular is awesome, just super nice to vaguely gesture at the command i want and have it pop right up. The main change here and departure from zed-industries#37123 is realizing that the primary reason for the regressions is actually how nucleo handles smart case, the old `fuzzy` crate only uses the smart case argument to score things differently, while nucleo actually filters on the case, eg. with smart case query "Apple" wouldnt match "apple". To get around this we always pass `CaseMatching::Ignore` to nucleo and implement the same score modifications from fuzzy in our code. There is a performance cost to that, of course, but from my testing it is fairly static, not growing as the size increases, so maybe a query takes 35 µs instead of 25 µs, but a query that takes 800 µs will only take 820 µs. Benchmark: | kind | query | size | nucleo | fuzzy | nucleo/fuzzy | |---|---|---:|---:|---:|---:| | string | 1-word | 100 | 9.15 µs | 24.6 µs | 0.37× | | string | 1-word | 1000 | 150.2 µs | 207.2 µs | 0.72× | | string | 1-word | 10000 | 1.34 ms | 2.07 ms | 0.65× | | string | 2-word | 100 | 5.16 µs | 2.94 µs | 1.75× | | string | 2-word | 1000 | 29.0 µs | 11.0 µs | 2.63× | | string | 2-word | 10000 | 210.6 µs | 55.5 µs | 3.79× | | string | 4-word | 100 | 2.57 µs | 2.33 µs | 1.10× | | string | 4-word | 1000 | 6.98 µs | 5.85 µs | 1.19× | | string | 4-word | 10000 | 20.0 µs | 12.0 µs | 1.66× | When I added the 4-word queries to the benchmarks I was actually really concerned that the performance would be awful, making it unsuitable for the command palette especially. However, I think due to the CharBag pre-filtering when the query is longer, the performance is actually way better than the 2 word case. Video: https://github.com/user-attachments/assets/3cd7221b-424f-4fd3-8df1-5543dcc340a3 Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Improved fuzzy matching in the command palette, branch picker, tab switcher, and recent projects picker to support multi-word queries. --------- Co-authored-by: Yara <git@yara.blue>
jolutz
pushed a commit
to jolutz/zed
that referenced
this pull request
Aug 8, 2026
…enchmarks (zed-industries#54112) This PR was originally a part of zed-industries#53551 so theres more info about its motivation there. - Add a CharBag prefilter on path candidates to skip irrelevant entries before invoking nucleo's matcher. - Use binary_search on sorted matched char indices when reconstructing byte positions (perf improvement). - Add a criterion benchmark comparing `fuzzy_nucleo` path matching against the existing fuzzy crate. Performance Chart: | Benchmark | Size | Nucleo (before) | Nucleo (after) | Fuzzy | Before/Fuzzy | After/Fuzzy | |-----------|-----:|----------------:|---------------:|------:|-------------:|------------:| | 1-word | 100 | 14.14 µs | 9.12 µs | 9.06 µs | 1.56x | 1.01x | | 1-word | 1,000 | 164.37 µs | 114.11 µs | 110.43 µs | 1.49x | 1.03x | | 1-word | 10,000 | 1.83 ms | 1.39 ms | 1.41 ms | 1.30x | 0.99x | | 2-word | 100 | 12.83 µs | 3.51 µs | 979 ns | 13.10x | 3.59x | | 2-word | 1,000 | 131.65 µs | 33.46 µs | 6.37 µs | 20.67x | 5.25x | | 2-word | 10,000 | 1.24 ms | 338.84 µs | 52.46 µs | 23.64x | 6.46x |o Exact Current State: | query | size | nucleo | fuzzy | nucleo/fuzzy | |---|---:|---:|---:|---:| | 1-word | 100 | 8.62 µs | 9.22 µs | 0.93× | | 1-word | 1000 | 102 µs | 111 µs | 0.92× | | 1-word | 10000 | 1.13 ms | 1.28 ms | 0.88× | | 2-word | 100 | 3.48 µs | 0.98 µs | 3.55× | | 2-word | 1000 | 29.9 µs | 6.39 µs | 4.68× | | 2-word | 10000 | 271 µs | 53.4 µs | 5.08× | | 4-word | 100 | 0.85 µs | 0.53 µs | 1.60× | | 4-word | 1000 | 2.99 µs | 1.66 µs | 1.80× | | 4-word | 10000 | 20.1 µs | 9.14 µs | 2.20× | Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - fuzzy_nucleo: improved the performance of path matching
jolutz
pushed a commit
to jolutz/zed
that referenced
this pull request
Aug 8, 2026
…zed-industries#54123) Stacked on top of zed-industries#54112 This is part 2 of 3 towards zed-industries#51197 More details from the original PR zed-industries#53551 This PR includes the changes from zed-industries#54112 , im not sure how to avoid that, my understanding is that after that one is merged, this PR can be rebased onto main and everything will be correct. You can also view the version of this that does reflect the changes more directly here: feitreim#1 ## Changes In this PR I added a more general string matching functionality to `fuzzy_nucleo`, in order to have proper testing for this, I also changed the command palette, tab switching picker, branch picker, and recent projects picker to use this new implementation. I think the command palette change in particular is awesome, just super nice to vaguely gesture at the command i want and have it pop right up. The main change here and departure from zed-industries#37123 is realizing that the primary reason for the regressions is actually how nucleo handles smart case, the old `fuzzy` crate only uses the smart case argument to score things differently, while nucleo actually filters on the case, eg. with smart case query "Apple" wouldnt match "apple". To get around this we always pass `CaseMatching::Ignore` to nucleo and implement the same score modifications from fuzzy in our code. There is a performance cost to that, of course, but from my testing it is fairly static, not growing as the size increases, so maybe a query takes 35 µs instead of 25 µs, but a query that takes 800 µs will only take 820 µs. Benchmark: | kind | query | size | nucleo | fuzzy | nucleo/fuzzy | |---|---|---:|---:|---:|---:| | string | 1-word | 100 | 9.15 µs | 24.6 µs | 0.37× | | string | 1-word | 1000 | 150.2 µs | 207.2 µs | 0.72× | | string | 1-word | 10000 | 1.34 ms | 2.07 ms | 0.65× | | string | 2-word | 100 | 5.16 µs | 2.94 µs | 1.75× | | string | 2-word | 1000 | 29.0 µs | 11.0 µs | 2.63× | | string | 2-word | 10000 | 210.6 µs | 55.5 µs | 3.79× | | string | 4-word | 100 | 2.57 µs | 2.33 µs | 1.10× | | string | 4-word | 1000 | 6.98 µs | 5.85 µs | 1.19× | | string | 4-word | 10000 | 20.0 µs | 12.0 µs | 1.66× | When I added the 4-word queries to the benchmarks I was actually really concerned that the performance would be awful, making it unsuitable for the command palette especially. However, I think due to the CharBag pre-filtering when the query is longer, the performance is actually way better than the 2 word case. Video: https://github.com/user-attachments/assets/3cd7221b-424f-4fd3-8df1-5543dcc340a3 Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Improved fuzzy matching in the command palette, branch picker, tab switcher, and recent projects picker to support multi-word queries. --------- Co-authored-by: Yara <git@yara.blue>
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.
This PR was originally a part of #53551 so theres more info about its motivation there.
fuzzy_nucleopath matching against the existing fuzzy crate.Performance Chart:
Exact Current State:
Self-Review Checklist:
Release Notes: