perf(explore): ranked-search materialization via LineOffsetCache#653
Conversation
…ineOffsetCache The BM25 top-k materialization loop called extractLineByNumber per result — a scan from byte 0 of the whole file — up to max_results times per ranked query. Resolve the hit line through the line-offset cache (O(log n)) exactly like the exact-recall tiers (#611) and the context sites phase (#646) already do, keeping the scanning path as the fallback when the offset table can't be built. Same-session gated bench: codedb_context 129.0µs -> 113.6µs (-12%, context's keyword loop materializes ranked hits); codedb_search flat on the tiny hit-cached bench corpus — the win scales with file size on real repos, where each materialized hit was a whole-file walk. Full suite 23/23 steps, 869/873 (4 platform skips). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 05e7b50b2e
ℹ️ 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".
| var span1: [1]LineOffsetCache.Span = undefined; | ||
| const lines1 = [1]u32{c.best_line}; | ||
| const line_text = blk: { | ||
| if (self.line_offsets.lineSpans(path, ref.data, lines1[0..], span1[0..])) |n| { |
There was a problem hiding this comment.
Avoid building full offsets for one ranked hit
When the offset cache is cold, lineSpans builds the complete newline table for ref.data before it can return this single span. This ranked loop passes only the one-element lines1 array, so for a top hit near the beginning of a large file the new path scans and allocates for the entire file, whereas the previous extractLineByNumber stopped as soon as it reached c.best_line. This can regress cold ranked searches or codedb_context on large/generated files; consider keeping the early scan for single-line cold lookups or only using the cache when an entry already exists.
Useful? React with 👍 / 👎.
Benchmark Regression ReportThresholds: 10.00% and 50,000 ns absolute delta
|
Bump semver + npm to 0.2.5828 and round out the changelog entry with the six commits that landed after the draft was written: searchSymbols binary-insert + total-order tiebreak (#647, #649), word-index persist integer remap + chunked writes (#650), call-graph reverse adjacency precompute (#651), snapshot dual-write clone (#652), ranked-search line-offset resolution (#653), and scripts/bench-ab.sh (#654). No code changes beyond the version strings + CHANGELOG. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Third of the round-2 items. The BM25 top-k materialization called
extractLineByNumber— a whole-file scan from byte 0 — once per result, up tomax_resultstimes per ranked query. Same fix the exact-recall tiers got in #611 and the context sites phase got in #646: resolve hit lines through theLineOffsetCachein O(log n), scanning fallback retained.Measured (same-session A/B):
codedb_context129.0µs → 113.6µs (−12%) (its keyword loop materializes ranked hits);codedb_searchflat on the tiny hit-cached corpus — on real repos each materialized hit was a whole-file walk, so the win scales with file size. Line-slice semantics verified identical (span end-before-newline, final-line-to-EOF, out-of-range → skip, exactly matchingextractLineByNumber). Full suite 23/23, 869/873.🤖 Generated with Claude Code