Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,6 @@
## 2024-05-28 - Accurate Fast Git Status Parsing
**Learning:** Using `git status --porcelain -z` without the `-uall` flag causes it to omit untracked files inside untracked directories, breaking parity with `git ls-files --others`. Also, when handling 'R' and 'C' rename statuses in porcelain v1, you must evaluate both the X (index) and Y (working tree) characters of the status prefix, and then ensure the old path string is also captured and added.
**Action:** Always use `-uall` with `git status --porcelain -z` when tracking modified/untracked files, and correctly verify `statusX` and `statusY` before extracting the old path segment.
## 2025-07-22 - [Hoist Allocations Out of Search Hot Loops]
**Learning:** Creating `new Set` and `new Uint8Array(256)` dynamically within `searchRemainingItems` during burst searches adds redundant GC overhead.
**Action:** Hoist constant priority scope sets and type ID mappings to module-level precomputed constants to eliminate allocation during hot loops.
Comment on lines +106 to +108

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

πŸ“ Maintainability & Code Quality | 🟑 Minor | ⚑ Quick win

Correct the optimization entry date or ordering.

This section is dated July 22, 2025, but follows entries dated May 3, 2026 and May 6, 2026. Use the actual change dateβ€”likely July 22, 2026β€”or move the entry to preserve chronological order.

πŸ€– 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 @.jules/bolt.md around lines 106 - 108, Correct the changelog entry date for
β€œHoist Allocations Out of Search Hot Loops” to the actual change date, likely
2026-07-22, or relocate the entry so the surrounding entries remain in
chronological order.

32 changes: 14 additions & 18 deletions language-server/src/core/search-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ const ID_TO_SCOPE = [
SearchScope.ENDPOINTS,
];

const BURST_PRIORITY_SCOPES = [SearchScope.TYPES, SearchScope.SYMBOLS, SearchScope.ENDPOINTS, SearchScope.FILES];
const IS_BURST_PRIORITY_TYPE_ID = new Uint8Array(256);
{
const prioritySet = new Set(BURST_PRIORITY_SCOPES);
for (let i = 0; i < ID_TO_SCOPE.length; i++) {
if (prioritySet.has(ID_TO_SCOPE[i])) {
IS_BURST_PRIORITY_TYPE_ID[i] = 1;
}
}
}

// Precompute bitflags table for O(1) lookup for the Basic Multilingual Plane (BMP)
// Maps char code (0-65535) to a bitmask.
const CHAR_TO_BITFLAG = new Uint32Array(65536);
Expand Down Expand Up @@ -2528,13 +2539,11 @@ export class SearchEngine implements ISearchProvider {
results: SearchResult[],
token?: CancellationToken,
): void {
const priorityScopes = [SearchScope.TYPES, SearchScope.SYMBOLS, SearchScope.ENDPOINTS, SearchScope.FILES];

this.searchPriorityScopes(priorityScopes, maxResults, processItem, results, token);
this.searchPriorityScopes(BURST_PRIORITY_SCOPES, maxResults, processItem, results, token);

// Pass 5: Everything else (e.g. Properties, Variables, Commands)
if (results.length < maxResults && !token?.isCancellationRequested) {
this.searchRemainingItems(priorityScopes, maxResults, processItem, results, token);
this.searchRemainingItems(maxResults, processItem, results, token);
}
}

Expand All @@ -2558,30 +2567,17 @@ export class SearchEngine implements ISearchProvider {
}

private searchRemainingItems(
priorityScopes: SearchScope[],
maxResults: number,
processItem: (i: number) => void,
results: SearchResult[],
token?: CancellationToken,
): void {
// ⚑ Bolt: Fast Remaining Scopes Iteration Optimization
// Instead of allocating a Uint8Array of size N to track already processed items,
// we precompute which type IDs belong to priority scopes and iterate sequentially.
// This avoids the large allocation while preserving the exact iteration order of the fallback pass.
const prioritySet = new Set(priorityScopes);
const isPriorityTypeId = new Uint8Array(256);
for (let i = 0; i < ID_TO_SCOPE.length; i++) {
if (prioritySet.has(ID_TO_SCOPE[i])) {
isPriorityTypeId[i] = 1;
}
}

const itemsLength = this.items.length;
const itemTypeIds = this.itemTypeIds;

for (let i = 0; i < itemsLength; i++) {
if (results.length >= maxResults || token?.isCancellationRequested) break;
if (isPriorityTypeId[itemTypeIds[i]] === 0) {
if (IS_BURST_PRIORITY_TYPE_ID[itemTypeIds[i]] === 0) {
processItem(i);
}
}
Expand Down
Loading