perf(cascade): measure the flight cascade — 1.2413 µs/tick, estimator is 91% (PERF-P01) - #361
Merged
Merged
Conversation
… is 91% (PERF-P01)
Performance was the ONE axis on which this project could make no claim at all.
`engine-throughput` has guarded the cFS engines since v1.56; the control path
that actually flies had no timing baseline of any kind. The examples/*-bench
binaries measure estimator ACCURACY, not time. A compositional WCET proof exists
in Lean and had never been confronted with a measurement.
MEASURED (cargo bench, Apple-silicon dev host, release, 2026-08-25):
iekf_propagate [1.1249 1.1256 1.1263] us 91.0 % of the cascade
position_tick [73.359 73.403 73.451] ns 5.9 %
attitude_tick [15.456 15.465 15.476] ns 1.2 %
rate_tick [10.245 10.252 10.261] ns 0.8 %
mixer_mix [ 9.4437 9.4491 9.4549] ns 0.8 %
full_cascade_tick [1.2406 1.2413 1.2421] us <- per-tick control loop
CI spread < 0.1 % — stable measurements, not noise.
TWO FINDINGS.
(i) THE ESTIMATOR IS THE CASCADE. IEKF is 91 %; the other four together are
~108 ns. Any cascade performance work that is not estimator work is rounding
error. Independently corroborated: jess's scry STATIC stack bounds put iekf at
4192 B against 16-112 B for the others. Dynamic timing here, static analysis
there, neither derived from the other, same conclusion.
(ii) THE 1 kHz BUDGET IS NOT CLOSE. 1.2413 us against a 1 ms period is 0.12 %
of budget, ~806x margin on this host. Even allowing an order of magnitude for a
Cortex-M7 at a fraction of the clock, the control math will not bound the loop —
the HAL, scheduler and sensor I/O will.
`full_cascade_tick` is the honest per-tick figure, not a synthetic sum: the
cascade is single-rate, `cascade.step()` runs every stage once per tick with no
divider (wasm/cm/cascade/src/lib.rs).
WHAT THIS DOES NOT ESTABLISH, stated because the limits are the point:
- not on-silicon (aarch64 host, warm cache, a branch predictor an M7 lacks)
- not a comparison — the PX4 head-to-head on the same board is criterion (d)
and is NOT done. We can say what our cascade costs, not that it costs less.
- not a tight SLA — no persisted history, so ceilings are coarse ~10x
catastrophic guards, same limitation FV-FALCON-PERF-001 records.
PERF-P01 and FV-FALCON-PERF-002 therefore land at `implemented`, not `verified`.
Criterion (d) is what would promote them, and nobody has taken that measurement.
Also: the `cargo bench` step is NOT marked bench-only, because `cargo bench` is
not in BENCH_PATTERNS and the marker would claim something untrue — it genuinely
runs in the gate (62s), which is better evidence than a skip.
gate (has-tag "performance"): 7 steps PASS, 0 FAIL
rivet validate: PASS, exit 0
Refs #8.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvusAXYbHLyv3uTzfBcMbG
avrabe
enabled auto-merge (squash)
August 25, 2026 19:36
avrabe
added a commit
that referenced
this pull request
Aug 26, 2026
…363) v1.135 ships the cascade timing baseline and nothing else. WHY: performance was the ONE axis on which this project could make no claim at all. `engine-throughput` guarded the cFS engines since v1.56; the control path that actually flies had no timing baseline of any kind, and the WCET proof in Lean had never been confronted with a measurement. That was the highest-value gap in the standing assessment, and PERF-P01 (#361) closes it: full_cascade_tick 1.2413 us <- all five stages, one tick iekf_propagate 1.1256 us 91 % of the cascade the other four ~108 ns combined Deferred out, each with the reason recorded in the artifact rather than moved silently: TRACE-P02 -> v1.136 next, and now precisely sized MATHF32-P06 -> v1.139 not blocked, just lower value than the four ahead OCI-P03 -> v1.139 parked pending REWRITE, do not implement as written TRACE-P02 is no longer one undifferentiated sweep. Measured 2026-08-25: 155 of 236 verification artifacts have >=1 CI-runnable step -> promotable MECHANICALLY from the gate's own per-artifact result 36 are bench-only -> named waiver or a real step (judgement) 45 have NO steps at all -> cannot be evidence; write steps or demote And ZERO `implemented` requirements lack a verifier — the 22/247 verified figure is entirely UNPROMOTED verifiers, not missing evidence. That makes the bulk of it far cheaper than it looked, and isolates the 45 as the real work. OCI-P03's restated warning matters because it is easy to pick up by release order: upstream wit-bindgen 0.60 already generates `[u8; 8]`, so the fixed-length-list case for the fork is gone; the fork is three minors stale (0.58 vs upstream 0.61.1) and NOTHING in relay depends on it. The drift that actually matters is in the flight path — components pin wit-bindgen-rt 0.41 while the workspace is on 0.60, a 19-minor spread, and 0.41 generates the bindings in every published artifact. Rewrite around that migration; it needs no fork. PERF-P01's criterion (d) — the PX4 head-to-head — is NOT discharged and is now filed as #362 rather than left as an unmet criterion nobody re-reads. We can say what our cascade costs; we cannot yet say it costs less. rivet validate: PASS, exit 0. Claude-Session: https://claude.ai/code/session_01HvusAXYbHLyv3uTzfBcMbG Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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.
Verify-Filter: (has-tag "performance")
Performance was the one axis on which this project could make no claim at all.
engine-throughputhas guarded the cFS engines since v1.56; the control path that actually flies had no timing baseline of any kind. Theexamples/*-benchbinaries measure estimator accuracy, not time. A compositional WCET proof has existed in Lean and had never been confronted with a measurement.Measured
cargo bench, Apple-silicon dev host, release profile:iekf_propagateposition_tickattitude_tickrate_tickmixer_mixfull_cascade_tickCI spread < 0.1 % — stable, not noise.
Two findings
The estimator is the cascade. IEKF is 91 %; the other four together are ~108 ns. Any cascade performance work that isn't estimator work is rounding error.
Independently corroborated: jess's scry static stack bounds put
iekfat 4192 B against 16–112 B for the others. Dynamic timing here, static analysis there, neither derived from the other, same conclusion about which stage carries the mass.The 1 kHz budget is not close. 1.2413 µs against a 1 ms period is 0.12 % of budget, ~806× margin on this host. Even allowing an order of magnitude for a Cortex-M7 at a fraction of the clock, the control math will not bound the loop — the HAL, scheduler and sensor I/O will.
full_cascade_tickis the honest per-tick figure rather than a synthetic sum: the cascade is single-rate,cascade.step()runs every stage once per tick with no divider.What this does NOT establish
The limits are the point, so they are in the artifact and the baseline file:
FV-FALCON-PERF-001records.PERF-P01andFV-FALCON-PERF-002land atimplemented, notverified. Criterion (d) is what would promote them.One honesty note
The
cargo benchstep is deliberately not marked# bench-only.cargo benchis not inBENCH_PATTERNS, so that marker would claim something untrue — it genuinely runs in the gate (62 s), which is better evidence than a skip.Evidence: gate
(has-tag "performance")→ 7 steps PASS, 0 FAIL.rivet validatePASS, exit 0.Refs #8.
🤖 Generated with Claude Code