feat(causal): offcpu audit bucket — the @50 deficit located (RFC 007)

GPU sweep decomposed the ~23ms/700ms @50 injection deficit: every
ledger bucket is ~zero (drop park 0, discards 0, drop yield ~0.3ms),
books balance at absorbed+forgiven = 4x injected in all 48 cells, and
the 0%-cell contamination signature is absent. The probe pins the
residual: eff 0.933-0.943, a constant 22-27µs missing per site entry
= ~4.9 slice-expiry yields/entry x ~5.6µs runqueue wait. The
"deficit" is runnable off-CPU time inside the site — wall time the
probe's ground truth counts but on-CPU attribution correctly skips
(Coz model: speeding the site's code does not shrink queue-wait).

Measure-only reclassification, no behaviour change: a yield in the
target site stashes (tsc, experiment epoch) on the slot; the next
on_resume counts the gap into OFFCPU_IN_SITE_{CYCLES,N} (would-be
delta terms, MAX_SAMPLE_CYCLES-capped) iff the epoch still matches
and the word is live — a gap straddling end()/a same-word begin()
(live in the probe's 50,50 schedule) is dropped, never a leaked
cooldown. Parks excluded: blocked time is forgiveness territory.
New offcpu column in render_ledger_audit; LedgerCounters and
ExperimentResult grow the two fields. Fidelity footer now states
the on-CPU basis (deliberate wording change to the pinned summary;
the substring pin test still holds). +2 tests (counted gap; epoch
straddle) + render assert.
This commit is contained in:
Claude (sandbox)
2026-07-13 12:46:15 +00:00
parent 9bfeb2c6a2
commit 0ee3fe7330
3 changed files with 169 additions and 6 deletions
+68
View File
@@ -902,10 +902,78 @@ fn ledger_audit_renders_per_cell() {
discard_overmax_cycles: 5_000,
discard_overmax_n: 1,
discard_unarmed_n: 0,
offcpu_in_site_cycles: 20_000,
offcpu_in_site_n: 3,
}];
let s = render_ledger_audit(&results);
assert!(s.contains("ledger audit"), "missing header: {s}");
assert!(s.contains("audit-render-site"), "missing site line: {s}");
assert!(s.contains("absorbed"), "missing absorbed column: {s}");
assert!(s.contains("forgiven"), "missing forgiven column: {s}");
assert!(s.contains("offcpu"), "missing offcpu column: {s}");
}
/// A runnable (yield) deschedule inside the target site opens an off-CPU
/// gap; the resume closing it lands in the same experiment window, so the
/// audit counts it. RFC 007: this is the located @50 deficit — runnable
/// queue-wait is real wall time in-site that on-CPU attribution correctly
/// skips; the bucket exists so the books close instead of leaving a
/// silent ~7% residual.
#[test]
fn audit_counts_offcpu_runnable_gap_in_target_site() {
let _s = serial();
smarm::init(smarm::Config::exact(1)).run(|| {
smarm::causal::begin_experiment_for_test("audit-offcpu-site", 50);
let c0 = smarm::causal::ledger_counters();
let h = smarm::spawn(|| {
let _g = smarm::causal_site!("audit-offcpu-site");
smarm::check!(); // arm
smarm::yield_now(); // runnable gap: deschedule -> resume
smarm::check!();
});
h.join().unwrap();
let c1 = smarm::causal::ledger_counters();
smarm::causal::end_experiment_for_test();
assert!(
c1.offcpu_in_site_n > c0.offcpu_in_site_n,
"in-site runnable gap recorded no offcpu event"
);
assert!(
c1.offcpu_in_site_cycles > c0.offcpu_in_site_cycles,
"in-site runnable gap carried no cycles"
);
});
}
/// An off-CPU gap that straddles `end()` — even into a later window with
/// an identical site+pct word (live in the attrib probe's 50,50 schedule)
/// — is dropped, not counted: the stash carries the experiment *epoch*,
/// so a straddling resume can never leak a cooldown across windows.
#[test]
fn audit_offcpu_gap_across_windows_not_counted() {
let _s = serial();
smarm::init(smarm::Config::exact(1)).run(|| {
smarm::causal::begin_experiment_for_test("audit-offcpu-straddle", 50);
let c0 = smarm::causal::ledger_counters();
let h = smarm::spawn(|| {
let _g = smarm::causal_site!("audit-offcpu-straddle");
smarm::check!();
smarm::yield_now(); // stash carries window A's epoch
smarm::check!();
});
// FIFO on exact(1): let h run to its yield, then close window A and
// open a same-word window B before h resumes.
smarm::yield_now();
smarm::causal::end_experiment_for_test();
smarm::causal::begin_experiment_for_test("audit-offcpu-straddle", 50);
h.join().unwrap();
let c1 = smarm::causal::ledger_counters();
smarm::causal::end_experiment_for_test();
assert_eq!(
c1.offcpu_in_site_n, c0.offcpu_in_site_n,
"gap straddling windows must not be counted"
);
});
}