diff --git a/.jules/bolt.md b/.jules/bolt.md index 5fa7b6a..f6795d2 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -32,3 +32,6 @@ ## 2026-05-04 - [Fix CI SIGTRAP Failure] **Learning:** `xvfb-run` crashes with `SIGTRAP` in GitHub Actions for `vscode-extension` integration tests if they run too soon after `dbus` services start or fail, likely due to missing display configurations in the headless agent environment for Electron integration testing via `@vscode/test-electron`. Wait! No, that's from my past memory. Let me see what I just fixed. I fixed `indexer-worker.ts` with `pLimit`. Let's just submit. +## 2024-05-18 - Lazy Evaluation of Pre-computed Full Names in Search Engine +**Learning:** In the `SearchEngine.burstSearch` hot loop, calling `fullName.toLowerCase()` for every item when no fast-path exact or prefix match is found creates a significant amount of redundant string allocations, leading to performance bottlenecks during exhaustive scans. +**Action:** Implemented lazy evaluation of `_targetLower` from the parallel `this.preparedFullNames` array in `calculateMatchScore`. By passing the pre-computed Fuzzysort prepared object down, we only extract its lowercased string if the fast paths fail, avoiding unnecessary O(N) evaluations and memory allocations. diff --git a/language-server/src/core/search-engine.ts b/language-server/src/core/search-engine.ts index 2a18cdd..d73d18a 100644 --- a/language-server/src/core/search-engine.ts +++ b/language-server/src/core/search-engine.ts @@ -2230,7 +2230,7 @@ export class SearchEngine implements ISearchProvider { ? (prepared as unknown as ExtendedPrepared)._targetLower : item.name.toLowerCase(); - const score = this.calculateMatchScore(nameLower, item.fullName, queryLower); + const score = this.calculateMatchScore(nameLower, item.fullName, this.preparedFullNames[i], queryLower); if (score > 0) { addResult(item, this.itemTypeIds[i], score); } @@ -2248,7 +2248,7 @@ export class SearchEngine implements ISearchProvider { return results; } - private calculateMatchScore(nameLower: string, fullName: string | undefined, queryLower: string): number { + private calculateMatchScore(nameLower: string, fullName: string | undefined, preparedFullName: Fuzzysort.Prepared | null, queryLower: string): number { // Fast path: Exact match or prefix match if (nameLower === queryLower || nameLower.indexOf(queryLower) === 0) { return 1.0; @@ -2259,9 +2259,13 @@ export class SearchEngine implements ISearchProvider { return 0.8; } - // Check fullName if it exists and is different from name + // Check fullName if it exists if (fullName) { - const fullLower = fullName.toLowerCase(); + // ⚡ Bolt: Lazy retrieval of pre-computed lowercased fullName to avoid redundant string allocations + const fullLower = preparedFullName + ? (preparedFullName as unknown as ExtendedPrepared)._targetLower + : fullName.toLowerCase(); + if (fullLower !== nameLower) { if (fullLower === queryLower || fullLower.indexOf(queryLower) === 0) { return 0.9;