Skip to content

perf(spectrum): software-prefetch SA entries in the boundary-search and forward/tabled probe loops - #21

Merged
nh13 merged 1 commit into
mainfrom
feat/v0.2-prefetch
Jun 10, 2026
Merged

perf(spectrum): software-prefetch SA entries in the boundary-search and forward/tabled probe loops#21
nh13 merged 1 commit into
mainfrom
feat/v0.2-prefetch

Conversation

@nh13

@nh13 nh13 commented Jun 8, 2026

Copy link
Copy Markdown

PR #8 of the v0.2 stack (carries 6c5abb3, with d77b83b folded in). Base is feat/v0.2-benches (#20).

Software-prefetches SA entries in the boundary-search probe loop, extended to the forward + tabled binary searches (d77b83b folded). Pure perf — byte-identical (oracle proptests unchanged). Clean cherry-pick onto #7.

Green-pass: build / clippy -D warnings / nightly fmt / cargo test --workspace all ✅ (162 lib + all FFI; only Plan-3 deferrals ignored).

Summary by CodeRabbit

  • Chores
    • Optimized internal memory access patterns to improve lookup performance latency through prefetching enhancements.

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 29d54953-abcd-4bf7-b2bd-50f0991cd37c

📥 Commits

Reviewing files that changed from the base of the PR and between fdedec3 and 16f99ff.

📒 Files selected for processing (3)
  • prmi/src/index/mod.rs
  • prmi/src/index/spectrum.rs
  • prmi/src/sidecar/sa_file.rs

📝 Walkthrough

Walkthrough

This PR adds software prefetch hints for suffix array cache optimization in binary search operations. A new SaFileReader::prefetch() method issues CPU-specific prefetch instructions, wrapped through LearnedIndex::prefetch_sa(), and integrated into forward spectrum and boundary-finding search loops via a prefetch_bsearch() helper to overlap DRAM reads with ongoing key comparisons.

Changes

SA Prefetching Cache Optimization

Layer / File(s) Summary
Low-level SA file prefetch implementation
prmi/src/sidecar/sa_file.rs
SaFileReader::prefetch(i) with inline(always), bounds checking, byte-offset calculation from file header, and architecture-specific prefetch directives on x86_64 and aarch64.
LearnedIndex prefetch wrapper
prmi/src/index/mod.rs
LearnedIndex::prefetch_sa(i) inlined pub(crate) method delegates to underlying SA reader prefetch for use by binary search loops.
Binary search loop prefetch integration
prmi/src/index/spectrum.rs
New prefetch_bsearch(lo, hi) helper computes and prefetches both next potential child midpoints; wired into forward spectrum lower/upper-bound loops, tabled forward deep-band search, and find_boundary iteration to overlap next SA entry loads with current key comparisons.

🎯 2 (Simple) | ⏱️ ~12 minutes

🐰 Cache whispers sweet as clover—
Binary search hops the bounds,
Prefetch tips before you leap,
Memories bloom on CPU rounds, 🌾✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding software prefetching of SA entries in binary-search loops (boundary-search, forward, and tabled probe loops).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nh13
nh13 force-pushed the feat/v0.2-benches branch from 942bf0d to 31e38ab Compare June 8, 2026 04:15
@nh13
nh13 force-pushed the feat/v0.2-prefetch branch from a87d557 to 8d4efbf Compare June 8, 2026 04:15
@nh13
nh13 force-pushed the feat/v0.2-benches branch from 31e38ab to 407e2c5 Compare June 8, 2026 18:42
@nh13
nh13 force-pushed the feat/v0.2-prefetch branch from 8d4efbf to 5cf77bc Compare June 8, 2026 18:43
@nh13
nh13 force-pushed the feat/v0.2-benches branch from 407e2c5 to e81a7b7 Compare June 8, 2026 21:11
@nh13
nh13 force-pushed the feat/v0.2-prefetch branch from 5cf77bc to 2dff648 Compare June 8, 2026 21:12
@nh13
nh13 force-pushed the feat/v0.2-benches branch from e81a7b7 to 02c42c9 Compare June 8, 2026 22:44
@nh13
nh13 force-pushed the feat/v0.2-prefetch branch from 2dff648 to 82270b3 Compare June 8, 2026 22:45
@nh13
nh13 force-pushed the feat/v0.2-benches branch from 02c42c9 to 15c3da2 Compare June 9, 2026 15:52
@nh13
nh13 force-pushed the feat/v0.2-prefetch branch from 82270b3 to fb058e1 Compare June 9, 2026 15:52
@nh13
nh13 force-pushed the feat/v0.2-benches branch 2 times, most recently from 185815b to 6a15607 Compare June 9, 2026 19:54
@nh13
nh13 force-pushed the feat/v0.2-prefetch branch from fb058e1 to 8b38e55 Compare June 9, 2026 19:55
@nh13
nh13 force-pushed the feat/v0.2-benches branch from 6a15607 to 06416f5 Compare June 10, 2026 00:20
@nh13
nh13 force-pushed the feat/v0.2-prefetch branch from 8b38e55 to 0d0b4d6 Compare June 10, 2026 00:20
@nh13
nh13 force-pushed the feat/v0.2-benches branch from 06416f5 to 98c34e3 Compare June 10, 2026 02:25
@nh13
nh13 force-pushed the feat/v0.2-prefetch branch from 0d0b4d6 to 4695361 Compare June 10, 2026 02:25
@nh13
nh13 force-pushed the feat/v0.2-benches branch from 98c34e3 to 70224eb Compare June 10, 2026 03:40
@nh13
nh13 force-pushed the feat/v0.2-prefetch branch from 4695361 to 4c278fc Compare June 10, 2026 03:41
Base automatically changed from feat/v0.2-benches to main June 10, 2026 16:41
…robe loop

find_boundary's binary search is the backward-extension hot loop, and every
go_right(mid) is a cold DRAM read of SA entry mid (position + key, one cache
line). Prefetch both possible next-probe entries before the compare so the
next iteration's miss is already in flight — the prefetch-discipline BWA-MEME
uses (_mm_prefetch before each binary-search step) that prmi was missing.

- SaFileReader::prefetch(i): cfg-gated x86_64 _mm_prefetch(T0) / aarch64 prfm
  pldl1keep, no-op elsewhere; lives in the sa_file unsafe island, exposed as a
  safe LearnedIndex::prefetch_sa for the deny(unsafe_code) search code.
- Advisory only: it never changes the boundary returned, just its latency
  (verified byte-identical — all 156 lib proptests pass). The win shows only on
  a genomic-scale, cache-cold SA; on the laptop synthetic the SA fits in cache.

Covers the backward bottleneck; the cold-forward inline searches and the gallop
phase can take the same treatment as a follow-up.
@nh13
nh13 force-pushed the feat/v0.2-prefetch branch from 4c278fc to 16f99ff Compare June 10, 2026 16:42
@nh13

nh13 commented Jun 10, 2026

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nh13
nh13 merged commit 942787e into main Jun 10, 2026
4 checks passed
@nh13
nh13 deleted the feat/v0.2-prefetch branch June 10, 2026 18:27
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