energy tests: the load-sensitive tick floor in proof-cascade and sandbox-meter #181
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/energy-tick-floor-proof-sandbox"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follow-on to #166, not a duplicate of it. #166 fixed this class of defect in
eoc-meterandjouleclaw-energy; its versions are untouched here. The samecode exists in two more crates, with the same assertion.
The defect
A probe tick spins until the thread's CPU clock advances 25 ms or a 500 ms
wall cap passes. Both copies asserted a floor on thread CPU per tick, and both
carried a comment asserting the opposite:
The sentence contains its own refutation — the wall cap is how load shortens a
tick. CI surfaced
proof-cascadeby failing an unrelated PR (#177); sweepingfor the pattern found
sandbox-metertoo, rather than waiting for anotherround.
Why not a threshold
The two outcomes that matter are not separable by time: a spin the host starved
into the cap and a tick that simply slept both show a long wall span against
little CPU.
I tried a per-turn CPU floor first — a turn is fixed work, so starvation should
lower turns-per-second rather than the cost of a turn. Measuring refuted it:
A blocking body's context switch is charged to the thread, so it costs more
per turn than arithmetic. Even the direction was wrong.
What they assert now
Each tick reports what it did.
spin_tick/spin_forreturn aTickOutcome—the CPU it saw itself burn, and how many turns of the spin loop it ran — and
each probe collects one per tick, with the interval's wall span recorded beside
its CPU span. Per tick: the loop ran at all (a tick that never span did not
burn CPU, at any load), and the tick stopped for one of its two stated
reasons rather than early. The tests' own clocks still bound it from above and
keep CPU under wall.
assert_sampling'sper-interval floor, an aggregate floor over a whole scripted call, and a
per-interval floor in the live-rail test.
ProbeRungainsinterval_wallandthe per-tick outcomes;
burn_thread_cpureports the CPU it was alreadycomputing.
PROBE_TICK / 2floor. This crate alreadyhad
assert_tickusing the either-condition rule for the tick itself, so theinterval check now matches the crate's own convention, and both get stronger
for the spin count: that rule alone admits a tick that slept through its cap.
TickOutcomebecomes public because it already appears in a public signature —RaplPackages::live_inandcounter_livenesstake a tick that returns it, sosandbox-exec-microvmhas to name it and build one.Where a scripted tick stands in for the burn (fake powercap trees, the MSR
fakes, the hardware test's oracle) it reports a turn, with a comment saying that
this is the test declaring a real spin ran and not a figure chosen to clear a
threshold. The hardware test keeps using
oracle::burn, so the oracle staysindependent of what it checks.
Three doc comments asserting "a tick burns a full tick however loaded the
machine is" are corrected in place. Leaving that beside a fixed assertion would
reinvite the mistake.
Two Linux-gated sites this host cannot see
sandbox-meter/tests/rapl_hardware.rsis#![cfg(target_os = "linux")]. CI'sjetson-hub job caught it.
probe::counter_liveness_tick, reached on the Linux side throughMsrRaplMeter::host.cargo check --target aarch64-unknown-linux-gnu --all-targetscaught it.That cross-check is a weak oracle — it runs nothing — but it is exactly the
shape for a type mismatch in code the host platform never compiles.
CARGO_FEATURE_NO_NEON=1is required, or blake3's build script wants Linux Cheaders. The whole sandbox workspace cannot cross-check (
zstd-sysneeds a realcross compiler), so instead I confirmed nothing outside these crates references
the changed entry points, which makes the per-crate checks exhaustive for
callers.
Verification
proof-rs139 passed,sandbox-rs324 passed. All five touched crates checkclean for
aarch64-unknown-linux-gnu. The two clippy warnings inproof-cascadeare in untouched code — the same pair that predates the changein
eoc-meter, these files being copies of one another, which is why the defectwas in four places.
Falsifications:
spins > 0, both crates. Not caught by the weaker intermediate version I tried — which is how I found that version was wrongspins > 0One sleep falsification initially looked like a pass and turned out to be a
compile error. Checked, not assumed.
🤖 Generated with Claude Code