perf(reseed): neighbour-LCP scan for SMEM truncation (byte-identical, +13.5%) - #48
Conversation
…ts corpus Replace the O(lmax-L*) per-length walk in forward_truncate_below_maximal with an O(min_intv) neighbor-LCP scan: read the LCP of the query with the SA suffixes just outside the interval and extend the larger-LCP side until occ>=min_intv, then recover the exact interval via find_boundary (span-only for want_interval=false). Byte-identical to the old walk / naive oracle, proven by the existing forward_truncate_below_maximal_equals_oracle proptest plus a new repeats/ties corpus test exercising shared-L* ties and occ(maximal) in [2,min_intv), both want_interval modes. Probe budget on long-unique reads: 264 -> 18.
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughReplaces per-base downward walks in ChangesNeighbor-LCP truncation algorithm and tests
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
Times the full per-read SMEM driver (ns/read) over a FASTQ; built at two commits (pre/post #48) it measures the reseed-neighbor-scan wall win on a large ref.
Times the full per-read SMEM driver (ns/read) over a FASTQ; built at two commits (pre/post #48) it measures the reseed-neighbor-scan wall win on a large ref.
…t_wall bench (#49) * perf(spectrum): forward reseed truncate via neighbor-LCP scan + repeats corpus Replace the O(lmax-L*) per-length walk in forward_truncate_below_maximal with an O(min_intv) neighbor-LCP scan: read the LCP of the query with the SA suffixes just outside the interval and extend the larger-LCP side until occ>=min_intv, then recover the exact interval via find_boundary (span-only for want_interval=false). Byte-identical to the old walk / naive oracle, proven by the existing forward_truncate_below_maximal_equals_oracle proptest plus a new repeats/ties corpus test exercising shared-L* ties and occ(maximal) in [2,min_intv), both want_interval modes. Probe budget on long-unique reads: 264 -> 18. * perf(spectrum): RC reseed span via neighbor-LCP scan (byte-identical, O(min_intv)) * test(spectrum): deterministic neighbor-scan boundary cases Adversarial review of the reseed-neighbor-scan flagged three reasoned-correct but unexecuted branches. Add forward_truncate_boundary_cases covering: (a) lmax==1 (lcap=0 -> zero), and (b) SA-end exhaustion where min_intv exceeds any achievable occ, so the scan walks both neighbours off the SA ends and breaks on llo==0 && lhi==0 -> zero (not via the lmax cap). Both modes (want_interval true/false) and an oracle cross-check. No production-code change. * test(bench): collect_wall — per-read collect_smems wall harness Times the full per-read SMEM driver (ns/read) over a FASTQ; built at two commits (pre/post #48) it measures the reseed-neighbor-scan wall win on a large ref.
Summary
Replace the per-length linear length-walk in the reseed truncation primitives —
forward_truncate_below_maximalandmem_search_backward_truncated_span_rc(src/index/spectrum.rs) — with an O(min_intv) neighbour-LCP scan. Signatures are unchanged, so the production fused seeding path (collect_smems→ these primitives) benefits directly.Correctness is defined as byte-identity to the existing walk (not a re-derivation of the result): the converged
L*/interval and emitted SMEMs are unchanged.What changed
forward_truncate_below_maximal: the O(lmax−L*) per-length walk becomes an O(min_intv) scan over neighbouring SA entries' LCPs.mem_search_backward_truncated_span_rc: the same neighbour-axis scan applied to the reverse-complement span.Validation (all green)
forward_truncate_below_maximal_equals_oracle,mem_search_backward_truncated_span_rc_equals_oracle,span_rc_zero_occ_floors_to_anchor_len) plus a new repeats/ties corpus (24,130 cases incl. shared-L*ties and occ(maximal) ∈ [2, min_intv)).(rid,m,n,occ)parity: 0 differences vs current on E. coli K12 and phiX (fwd+revcomp) across the seeding param grid (msl 17/19/31, max_mem_intv 0, split_width 5 — counts genuinely vary).Performance
Warm hg38, 200k WGS reads, single-thread, load-excluded (the fused
collect_smemspath): 76,459 → 66,119 ns/read (−13.5%), tight variance, identical SMEM count.Test plan
cargo test(oracle + proptests, feature on/off)cargo clippy --all-features --all-targets -- -D warnings,cargo fmt --checkSummary by CodeRabbit
Refactor
Tests