Skip to content

fix(index): bound searchPrefix allocation by max_results#295

Merged
justrach merged 1 commit intomainfrom
fix/searchprefix-bound
Apr 18, 2026
Merged

fix(index): bound searchPrefix allocation by max_results#295
justrach merged 1 commit intomainfrom
fix/searchprefix-bound

Conversation

@justrach
Copy link
Copy Markdown
Owner

Summary

  • Add max_results: usize parameter to WordIndex.searchPrefix (src/index.zig:271) so the prefix-key scan stops once the cap is reached, instead of collecting every deduplicated hit and relying on the caller to truncate.
  • Pre-size the result list and dedup map to the cap, switch the append to appendAssumeCapacity, and break out of both the inner hits loop and outer keyIterator once result.items.len >= max_results.
  • Update the only caller, Tier 0.5 in Explorer.searchContent (src/explore.zig:1314), to pass the user-requested max_results.

Addresses Codex's P2 review on #293: on large indexes a broad 3-char prefix could allocate a huge hit set before the post-call truncation in searchContent, causing latency spikes / OOM despite a small caller limit.

Test plan

  • zig build test — 388/388 pass (387 baseline + 1 new word-index: searchPrefix respects max_results cap).
  • New test indexes 50 distinct files with the fooBar prefix and asserts searchPrefix("foobar", a, 5) returns at most 5 hits.
  • Existing two searchPrefix tests updated to pass an explicit cap (32) and continue to pass.

🤖 Generated with Claude Code

Prefix expansion in WordIndex.searchPrefix appended every deduplicated
hit for every matching key with no upper bound. The Tier 0.5 search flow
in explore.zig only enforced max_results AFTER searchPrefix returned, so
a broad 3-char prefix on a large index could allocate a huge hit set
before truncation — causing latency spikes / OOM despite callers asking
for a small limit.

Fix: thread max_results through searchPrefix. Pre-size the result list
and dedup map to the cap, append with appendAssumeCapacity, and
short-circuit both the inner hits loop and the outer key iteration once
the cap is reached.

Addresses Codex P2 review feedback on PR #293.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@justrach justrach force-pushed the fix/searchprefix-bound branch from 8f2fc19 to b70548d Compare April 18, 2026 15:31
@justrach justrach merged commit edd7914 into main Apr 18, 2026
1 check passed
@justrach justrach deleted the fix/searchprefix-bound branch April 18, 2026 15:32
@github-actions
Copy link
Copy Markdown

Benchmark Regression Report

Threshold: 10.00%

Tool Base (ns) Head (ns) Delta Status
codedb_bundle 519685 526987 +1.41% OK
codedb_changes 90129 86340 -4.20% OK
codedb_deps 44071 41834 -5.08% OK
codedb_edit 17027 17271 +1.43% OK
codedb_find 80138 80976 +1.05% OK
codedb_hot 134605 130104 -3.34% OK
codedb_outline 313358 313875 +0.16% OK
codedb_read 133522 121252 -9.19% OK
codedb_search 224262 221994 -1.01% OK
codedb_snapshot 3749475 3756895 +0.20% OK
codedb_status 230676 230695 +0.01% OK
codedb_symbol 92570 91019 -1.68% OK
codedb_tree 88555 88527 -0.03% OK
codedb_word 120527 118252 -1.89% OK

@chatgpt-codex-connector
Copy link
Copy Markdown

💡 Codex Review

codedb/src/watcher.zig

Lines 602 to 603 in 8f2fc19

for (extractors[extractors_done..]) |*r| r.deinit(allocator);
allocator.free(extractors);

P2 Badge Track initialized extractors before deferred cleanup

In buildTrigramsFromCache, the deferred cleanup iterates extractors[extractors_done..], but extractors_done is only incremented after successful post-join teardown, not after initialization. If std.Thread.spawn fails partway through the setup loop, this defer runs and calls deinit on uninitialized TriExtractResults entries, which can crash or corrupt memory during an otherwise recoverable error path.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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