Repository navigation
Fix significant-duration benchmark to feed cumulative Arias intensity - #247
Merged
Merged
Conversation
Closes #237 ## What was wrong `significant_duration::significant_duration` expects a **cumulative Arias intensity** array (non-decreasing along each row, total in the last element) — `threshold_search` binary-searches it. The Python binding (`_significant_duration` in `src-rust/lib.rs`) always computes `cumulative_arias_intensity` first. `bench_significant_duration` in `benches/intensity_benchmarks.rs` instead passed the raw sinusoidal output of `generate_waveforms` straight into `significant_duration`. Those rows go negative and are not monotonic, so: - for stations whose last sample is negative or below `1e-10`, `threshold_search` took its early `0.0` return and did no work; - for the rest, the binary search ran over unsorted data. The benchmark therefore measured neither the real workload nor a meaningful path, and left out the cumulative-integration cost that dominates `_significant_duration` in practice. ## The fix Extracted the waveform generator and a new `significant_duration_from_waveforms` helper (integrate, then search — the same two steps the Python binding runs) into `benches/common.rs`, shared between the benchmark and a new test. `bench_significant_duration` now calls the helper inside `b.iter`, so it measures the full Ds pipeline as Python uses it, and the benchmark group is renamed to `Significant_Duration_Full_Pipeline` to say so. ## How the new test shows it `tests/significant_duration_benchmark.rs` calls the shared helper on synthetic waveforms (same generator as the benchmark) and asserts every station's Ds duration is in `(0, total_duration]`. Before the fix (i.e. with the helper calling `significant_duration` directly on raw waveforms, as the benchmark used to), this test fails — reproducing exactly the `0.0`-duration degeneracy the issue describes: ``` station 3: expected a Ds duration in (0, 9.995...], got 0; feeding raw waveforms directly into significant_duration (instead of their cumulative Arias intensity) collapses this to 0.0 for most stations ``` After computing `cumulative_arias_intensity` first, it passes. ## What to check - `benches/common.rs` is a new file included into both the bench binary (`#[path = "common.rs"] mod common;`) and the test (`#[path = "../benches/common.rs"] mod common;`) — this is the only way to get a real (non-smoke) pass/fail check on benchmark-only code, since `cargo test --benches` just runs criterion's panic-only smoke pass and doesn't check output values. - No production (`src-rust`) code changed; this is benchmark/test-only. _Cost $1.59, 15 turns._ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
lispandfound
approved these changes
Oct 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #237
What was wrong
significant_duration::significant_durationexpects a cumulative Ariasintensity array (non-decreasing along each row, total in the last
element) —
threshold_searchbinary-searches it. The Python binding(
_significant_durationinsrc-rust/lib.rs) always computescumulative_arias_intensityfirst.bench_significant_durationinbenches/intensity_benchmarks.rsinsteadpassed the raw sinusoidal output of
generate_waveformsstraight intosignificant_duration. Those rows go negative and are not monotonic, so:1e-10,threshold_searchtook its early0.0return and did no work;The benchmark therefore measured neither the real workload nor a
meaningful path, and left out the cumulative-integration cost that
dominates
_significant_durationin practice.The fix
Extracted the waveform generator and a new
significant_duration_from_waveformshelper (integrate, then search — thesame two steps the Python binding runs) into
benches/common.rs, sharedbetween the benchmark and a new test.
bench_significant_durationnowcalls the helper inside
b.iter, so it measures the full Ds pipeline asPython uses it, and the benchmark group is renamed to
Significant_Duration_Full_Pipelineto say so.How the new test shows it
tests/significant_duration_benchmark.rscalls the shared helper onsynthetic waveforms (same generator as the benchmark) and asserts every
station's Ds duration is in
(0, total_duration]. Before the fix (i.e.with the helper calling
significant_durationdirectly on raw waveforms,as the benchmark used to), this test fails — reproducing exactly the
0.0-duration degeneracy the issue describes:After computing
cumulative_arias_intensityfirst, it passes.What to check
benches/common.rsis a new file included into both the bench binary(
#[path = "common.rs"] mod common;) and the test(
#[path = "../benches/common.rs"] mod common;) — this is the only wayto get a real (non-smoke) pass/fail check on benchmark-only code, since
cargo test --benchesjust runs criterion's panic-only smoke pass anddoesn't check output values.
src-rust) code changed; this is benchmark/test-only.Cost $1.59, 15 turns.
🤖 Generated with Claude Code