⚡ Bolt: Path Bitflags for Fuzzy Matching Early-Exit#573
Conversation
Introduces `itemPathBitflags` to the `SearchEngine`'s struct-of-arrays architecture to track character bitmasks specifically for relative file paths. This allows `tryFuzzyMatchPath` to bypass expensive `Fuzzysort.single()` evaluations when the required query characters are not present in the path string, avoiding wasted cycles when falling back to path matching. Co-authored-by: AhmmedSamier <17784876+AhmmedSamier@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
📝 WalkthroughWalkthroughSearchEngine now maintains per-item path bitflags derived from relative paths and uses them to skip impossible fuzzy path evaluations before invoking fuzzysort. ChangesPath Bitflag Search Optimization
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
language-server/src/core/search-engine.ts (1)
586-589: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winAvoid object allocations in the indexing hot loop.
Returning an object from
computeItemBitflagsallocates memory for every item duringsetItemsandaddItems. Passing theindexdirectly into the method to populate the parallel arrays eliminates this per-item allocation, reducing GC pressure and adhering to the indexing performance guidelines.
language-server/src/core/search-engine.ts#L586-L589: Replace the destructuring assignment with a direct call to the method, passing theindex.language-server/src/core/search-engine.ts#L603-L608: Change the method signature to acceptindex: numberand returnvoid.language-server/src/core/search-engine.ts#L618-L622: Remove thereturnstatement and assign the computed flags directly to the parallel arrays (this.itemNameBitflags[index] = nameFlags, etc.).⚡ Proposed refactor
- private prepareItemAtIndex(item: SearchableItem, index: number): void { - this.itemTypeIds[index] = TYPE_TO_ID[item.type]; - - const { nameFlags, fullNameFlags, pathFlags, aggregateFlags } = this.computeItemBitflags(item); - this.itemNameBitflags[index] = nameFlags; - this.itemFullNameBitflags[index] = fullNameFlags; - this.itemPathBitflags[index] = pathFlags; - this.itemBitflags[index] = aggregateFlags; - this.itemNameLengths[index] = item.name.length; + private prepareItemAtIndex(item: SearchableItem, index: number): void { + this.itemTypeIds[index] = TYPE_TO_ID[item.type]; + + this.computeAndStoreItemBitflags(item, index); + this.itemNameLengths[index] = item.name.length;- private computeItemBitflags(item: SearchableItem): { - nameFlags: number; - fullNameFlags: number; - pathFlags: number; - aggregateFlags: number; - } { + private computeAndStoreItemBitflags(item: SearchableItem, index: number): void {if (item.relativeFilePath) { // Optimization: Skip normalization as calculateBitflags maps both \ and / to same bitflag (bit 30) pathFlags = this.calculateBitflags(item.relativeFilePath); aggregateFlags |= pathFlags; } - return { nameFlags, fullNameFlags, pathFlags, aggregateFlags }; + this.itemNameBitflags[index] = nameFlags; + this.itemFullNameBitflags[index] = fullNameFlags; + this.itemPathBitflags[index] = pathFlags; + this.itemBitflags[index] = aggregateFlags; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@language-server/src/core/search-engine.ts` around lines 586 - 589, Update language-server/src/core/search-engine.ts#L586-L589 to replace the destructuring assignment with a direct computeItemBitflags call that passes index. Change computeItemBitflags at language-server/src/core/search-engine.ts#L603-L608 to accept index: number and return void, then at language-server/src/core/search-engine.ts#L618-L622 remove the returned object and write nameFlags, fullNameFlags, pathFlags, and aggregateFlags directly into the parallel arrays at index; apply these changes consistently for both setItems and addItems callers.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@language-server/src/core/search-engine.ts`:
- Around line 586-589: Update
language-server/src/core/search-engine.ts#L586-L589 to replace the destructuring
assignment with a direct computeItemBitflags call that passes index. Change
computeItemBitflags at language-server/src/core/search-engine.ts#L603-L608 to
accept index: number and return void, then at
language-server/src/core/search-engine.ts#L618-L622 remove the returned object
and write nameFlags, fullNameFlags, pathFlags, and aggregateFlags directly into
the parallel arrays at index; apply these changes consistently for both setItems
and addItems callers.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4432fe42-81ac-49b1-9544-f2f672078cde
📒 Files selected for processing (2)
.jules/bolt.mdlanguage-server/src/core/search-engine.ts
💡 What
Implemented an O(1) early-exit check in
tryFuzzyMatchPathby trackingitemPathBitflagsfor relative file paths, parallel to existing name bitflags.🎯 Why
When
tryFuzzyMatchNameandtryFuzzyMatchFullNamefail to yield high scores, the search engine falls back totryFuzzyMatchPath. Previously, this fallback unconditionally evaluatedFuzzysort.single(), which is expensive. If the query characters were present in the aggregateitemBitflagsbut not in the path itself, this resulted in wasted fuzzy sorting cycles.📊 Impact
Measurably reduces the number of
Fuzzysort.single()executions during deep fallback path matching, particularly for longer file paths and queries, dropping CPU overhead and GC pauses in the hot loop.🔬 Measurement
Run
bun run testin thelanguage-serverdirectory. Code paths have been verified via existing stream search and fuzzy matching regression tests. Benchmark improvements would be observed in large workspaces querying characters spread across different entity names that force fallback evaluations.PR created automatically by Jules for task 3868954251576606181 started by @AhmmedSamier
Summary by CodeRabbit