Skip to content

feat(prmi-sys): prmi_mem_search_lean — guards-removed FFI twin for per-call overhead - #24

Merged
nh13 merged 1 commit into
mainfrom
feat/v0.3-lean-ffi
Jun 11, 2026
Merged

feat(prmi-sys): prmi_mem_search_lean — guards-removed FFI twin for per-call overhead#24
nh13 merged 1 commit into
mainfrom
feat/v0.3-lean-ffi

Conversation

@nh13

@nh13 nh13 commented Jun 11, 2026

Copy link
Copy Markdown

First PR of the v0.3 perf series (carved from the consumer-collaboration branch onto the merged v0.2 foundation).

What

Adds prmi_mem_search_lean, a diagnostic twin of prmi_mem_search with the per-call FFI wrapper overhead removed — no clear_last_error/set_last_error, no catch_unwind — to A/B the fixed cost the consumer pays on every seeding call. The correctness guards (null/range checks, packed_pac_bytes narrowing) are kept, so outputs and return codes are byte-identical to prmi_mem_search. Intended for measurement, or for panic=abort builds where catch_unwind is already a no-op and this matches the production path.

Also adds examples/ffi_overhead.rs to measure the FFI boundary cost vs the direct Rust idx.mem_search.

Tests

mem_search_lean_matches_mem_search asserts byte-identical (rc, match_len, sa_start, occ) vs prmi_mem_search across model-launch (est_hint == 0) and ISA-launch (est_hint > 0), with and without WANT_INTERVAL.

Notes

Authored fresh against main (the merged v0.2 O(log) foundation), not cherry-picked — the perf branch diverged from the foundation's internals, so the series is re-derived rather than replayed. The original perf-branch version computed the pac length with a raw div_ceil(4) as usize; this uses the foundation's packed_pac_bytes() narrowing guard for consistency and to avoid u64→usize truncation.

Summary by CodeRabbit

  • New Features

    • Added a benchmarking example that measures per-call overhead across the native/FFI boundary, comparing direct and cross-boundary invocations.
    • Introduced a lean diagnostic variant of the search API that omits extra thread-local/error handling and unwind protection to reduce measurement overhead.
  • Tests

    • Added a regression test ensuring identical outputs between the standard and diagnostic search paths across modes.

@coderabbitai

coderabbitai Bot commented Jun 11, 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: 11f700b7-f162-4ef3-81c4-183cfdc1b370

📥 Commits

Reviewing files that changed from the base of the PR and between f04310d and bad847a.

📒 Files selected for processing (3)
  • prmi-sys/examples/ffi_overhead.rs
  • prmi-sys/src/lib.rs
  • prmi-sys/tests/spectrum_ffi.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • prmi-sys/examples/ffi_overhead.rs
  • prmi-sys/src/lib.rs
  • prmi-sys/tests/spectrum_ffi.rs

📝 Walkthrough

Walkthrough

The PR adds prmi_mem_search_lean (a low-overhead FFI twin of prmi_mem_search), a regression test asserting output parity between the full and lean FFI entrypoints, and an example binary that benchmarks direct Rust vs full-FFI vs lean-FFI per-call timings.

Changes

FFI Lean Variant for Overhead Measurement

Layer / File(s) Summary
Lean FFI entry point definition
prmi-sys/src/lib.rs
prmi_mem_search_lean exported as C ABI function performing identical search selection (model-launch when est_hint == 0, hint-based otherwise) and output writes (including optional PRMI_MEM_WANT_INTERVAL interval outputs), but omits clear_last_error/set_last_error and catch_unwind.
Regression test validating lean variant outputs
prmi-sys/tests/spectrum_ffi.rs
Test mem_search_lean_matches_mem_search compares prmi_mem_search and prmi_mem_search_lean on identical queries for model-launch and hint-based modes, asserting matching return codes and byte-identical outputs, and optionally verifying interval outputs when PRMI_MEM_WANT_INTERVAL is set.
FFI overhead benchmark setup
prmi-sys/examples/ffi_overhead.rs (setup)
Benchmark setup: opens index via both direct Rust API and FFI, loads .pac, constructs PacEncoding, and defines representative queries from a hardcoded DNA read.
Benchmark measurement loops and results
prmi-sys/examples/ffi_overhead.rs (timing, results, close)
Runs warm-up and timed loops for direct idx.mem_search, full prmi_mem_search, and prmi_mem_search_lean; computes per-call ns, overhead deltas, prints scaled estimates, and closes the FFI handle.

Sequence Diagram(s)

(see hidden artifact for a sequence diagram of the lean FFI execution path)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • fg-labs/prmi#17: Implements prmi_mem_search FFI behavior and PRMI_MEM_WANT_INTERVAL semantics that the lean variant mirrors.

Poem

🐰 A lean FFI hops light and keen,
Skipping errors, swift and clean,
Benchmark ticks the race,
Nanoseconds mark its pace,
Rabbit claps for faster scenes.

🚥 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 a lean FFI variant of prmi_mem_search with removed guards (error handling and panic catching) for measuring per-call overhead.
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 commented Jun 11, 2026

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 11, 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
prmi-sys/tests/spectrum_ffi.rs (1)

1240-1242: ⚡ Quick win

Ensure ISA-launch parity is always exercised.

Line 1240 can skip the est_hint > 0 branch entirely (e.g., ss == 0 && occ == 1), so this test may pass without validating the hinted path.

Proposed test hardening
-    if ss > 0 && occ > 0 {
-        both(&query, ss, PRMI_MEM_WANT_INTERVAL); // est_hint = in-interval SA index
-    }
+    let hinted = if occ == 0 {
+        None
+    } else if ss > 0 {
+        Some(ss)
+    } else if occ > 1 {
+        Some(ss + 1) // still in-interval, and > 0 sentinel
+    } else {
+        None
+    };
+    if let Some(hint) = hinted {
+        both(&query, hint, PRMI_MEM_WANT_INTERVAL);
+    } else {
+        panic!("test query produced no representable est_hint > 0; choose another query");
+    }
🤖 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 `@prmi-sys/tests/spectrum_ffi.rs` around lines 1240 - 1242, The current
conditional (if ss > 0 && occ > 0) can skip exercising the est_hint > 0 branch;
when occ > 0 but ss == 0 the hinted path is never tested. Modify the test to
always exercise the hinted/ISA-launch path: keep the existing call to
both(&query, ss, PRMI_MEM_WANT_INTERVAL) when ss > 0, and add a fallback case
when occ > 0 and ss == 0 that invokes both(&query, 1, PRMI_MEM_WANT_INTERVAL)
(or otherwise supply a positive est_hint) so the est_hint > 0 branch inside
both/est_hint logic is exercised; reference the variables ss, occ and the
both(...) call to locate where to add the fallback.
🤖 Prompt for all review comments with 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.

Inline comments:
In `@prmi-sys/examples/ffi_overhead.rs`:
- Around line 92-107: The benchmark loop currently uses debug_assert_eq!(rc, 0)
after calling prmi_mem_search, which is compiled out in --release and can let
non-zero rc silently corrupt results; replace the debug-only assertion with a
release-visible check (e.g., use assert_eq!(rc, 0) or an explicit if rc != 0 {
panic!(...); }) wherever debug_assert_eq! is used (notably the rc variable after
prmi_mem_search in the loop and the other occurrence around lines 116–131) so
the return code is validated at runtime in release builds and includes a clear
error message identifying prmi_mem_search and rc.
- Around line 27-29: Replace the machine-specific hardcoded fallback for
PRMI_HANDOFF: remove the local absolute path stored in bundle and instead derive
a portable default (e.g. a project-relative reports directory using
env!("CARGO_MANIFEST_DIR") or current working directory) or require PRMI_HANDOFF
to be set and return an error if not; update the hoff variable assignment (the
std::env::var("PRMI_HANDOFF").unwrap_or_else(...) call) and pac_path
construction (format!("{hoff}/chr22_A.fa.pac") ) accordingly so the code no
longer uses the absolute "/Users/nhomer/…" path.

---

Nitpick comments:
In `@prmi-sys/tests/spectrum_ffi.rs`:
- Around line 1240-1242: The current conditional (if ss > 0 && occ > 0) can skip
exercising the est_hint > 0 branch; when occ > 0 but ss == 0 the hinted path is
never tested. Modify the test to always exercise the hinted/ISA-launch path:
keep the existing call to both(&query, ss, PRMI_MEM_WANT_INTERVAL) when ss > 0,
and add a fallback case when occ > 0 and ss == 0 that invokes both(&query, 1,
PRMI_MEM_WANT_INTERVAL) (or otherwise supply a positive est_hint) so the
est_hint > 0 branch inside both/est_hint logic is exercised; reference the
variables ss, occ and the both(...) call to locate where to add the fallback.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ddfde074-6ace-49d7-9b2c-7123895fabd6

📥 Commits

Reviewing files that changed from the base of the PR and between 98e6715 and f04310d.

📒 Files selected for processing (3)
  • prmi-sys/examples/ffi_overhead.rs
  • prmi-sys/src/lib.rs
  • prmi-sys/tests/spectrum_ffi.rs

Comment thread prmi-sys/examples/ffi_overhead.rs Outdated
Comment thread prmi-sys/examples/ffi_overhead.rs
…r-call overhead

Adds prmi_mem_search_lean, a diagnostic twin of prmi_mem_search that drops the
per-call FFI WRAPPER overhead (no clear_last_error/set_last_error, no
catch_unwind) while keeping the correctness guards (null/range checks +
packed_pac_bytes narrowing). Outputs and return codes are byte-identical to
prmi_mem_search; intended for measurement or panic=abort builds (where
catch_unwind is already a no-op and this matches the production path).

Adds examples/ffi_overhead.rs to A/B the FFI boundary cost vs the direct Rust
idx.mem_search, and mem_search_lean_matches_mem_search asserting byte-identical
(rc, match_len, sa_start, occ) across model/ISA launch and both flag modes.

First PR of the v0.3 perf series, authored fresh against the merged v0.2
foundation (the perf branch diverged from the foundation internals, so it is
re-derived rather than cherry-picked).
@nh13
nh13 force-pushed the feat/v0.3-lean-ffi branch from f04310d to bad847a Compare June 11, 2026 14:29
@nh13
nh13 merged commit f314d85 into main Jun 11, 2026
4 checks passed
@nh13
nh13 deleted the feat/v0.3-lean-ffi branch June 11, 2026 14:36
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