feat(bench): phase 4 — run-queue bench harness + shootout driver
- benches/rq_micro.rs: raw-structure microbench, threads x producer:consumer ratio sweep. Benches all three queue types in one binary (they compile in every build; only the runtime alias is feature-selected), so no rebuild dance. Queues sized to the op count so the occupancy contract is met. - benches/rq_runtime.rs: whole-runtime benches with the selected variant: yield-storm (pure queue churn), ping-pong-pairs (park/unpark latency), spawn-storm (slab + free list + queue under churn). Scheduler-count sweep. - scripts/bench_rq.sh: rebuilds rq_runtime per rq-* feature, runs rq_micro once, aggregates RQCSV lines into bench_results/summary.csv. - All knobs via SMARM_BENCH_* env vars; house table format + machine lines. - run_queue module is now #[doc(hidden)] pub (types + push/pop/len + MpmcRing::with_capacity) solely so the external bench binary can drive the raw structures. docs(roadmap): phase 4 ticked (harness done; numbers from the 20-core box). New fast-follow per review: assert the invariants we lean on — debug_assert! on hot paths, loud assert!/panic on cold ones, at the point of reliance; sweep existing code during the phase-5 audit, adopt as house style. Validated end-to-end at smoke scale on the 1-core sandbox: full driver run, 24-row summary.csv across micro (3 structures x sweeps) and runtime (3 variants x 3 benches x thread sweep).
This commit is contained in:
+22
-8
@@ -86,14 +86,17 @@ Make slot lookup lock-free and per-slot state independently mutable.
|
||||
(`live == 0` alone implies the queue holds nothing actionable; argument
|
||||
rewritten at the `schedule_loop` site).
|
||||
|
||||
## Phase 4 — Bench harness
|
||||
- [ ] Raw-structure microbench: N threads, push/pop throughput vs thread count,
|
||||
sweeping producer:consumer ratios. Isolates the data structure.
|
||||
- [ ] Runtime-level: yield-storm, ping-pong-pairs, spawn-storm, all sweeping
|
||||
scheduler count. Reuses existing `benches/` harness style.
|
||||
- [ ] Driver script rebuilding per `rq-*` feature to compare variants in one go.
|
||||
- [ ] Sandbox validates correctness via oversubscribed `Config::exact(N)` on 1
|
||||
core; real contention numbers come from the 20-core box.
|
||||
## Phase 4 — Bench harness ✅ DONE (harness; real numbers from the 20-core box)
|
||||
- [x] `benches/rq_micro.rs`: raw structures, threads × p:c ratio sweep. One
|
||||
binary covers all three structures (types compile in every build).
|
||||
- [x] `benches/rq_runtime.rs`: yield-storm, ping-pong-pairs, spawn-storm,
|
||||
sweeping scheduler count; variant baked in by feature.
|
||||
- [x] `scripts/bench_rq.sh`: rebuilds per `rq-*` feature, aggregates RQCSV
|
||||
lines into `bench_results/summary.csv`. Knobs via SMARM_BENCH_* env;
|
||||
e.g. `SMARM_BENCH_THREADS="1 2 4 8 16 20" ./scripts/bench_rq.sh`.
|
||||
- [x] Harness validated end-to-end at smoke scale on the 1-core sandbox;
|
||||
contention curves and the actual variant decision come from the
|
||||
20-core box.
|
||||
|
||||
## Phase 5 — Safety hardening & model checking
|
||||
- [ ] `loom` (dev-dependency only, x86 Linux) model tests for the slot state
|
||||
@@ -104,6 +107,17 @@ Make slot lookup lock-free and per-slot state independently mutable.
|
||||
---
|
||||
|
||||
## Fast follow (post-v0.5, written down so it isn't lost)
|
||||
- **Assert the invariants we lean on.** This cycle accumulated load-bearing
|
||||
invariants: at-most-once-enqueued, queue-ops-under-NoPreempt, never two
|
||||
cold locks, cold-path generation re-verify under the lock, finalize's
|
||||
decrement-last, pushes-pair-with-Queued-transitions, thread-local guards
|
||||
never crossing a switch point. Whenever code RELIES on one and a cheap
|
||||
check exists, assert it at the point of reliance — `debug_assert!` on hot
|
||||
paths, full `assert!`/loud panic on cold ones — so a violation fails at
|
||||
the breakage site, not three modules downstream (the slab-overflow panic
|
||||
and the queue-op preemption debug_assert are the pattern). Sweep the
|
||||
existing code for missed spots; new code adopts it as house style. The
|
||||
phase-5 audit is the natural vehicle for the sweep.
|
||||
- **Channel mutex migration.** `channel::Inner<T>` is `Arc<Mutex<_>>` of the
|
||||
same poison class as the old shared lock; `recv_match` even runs a user
|
||||
predicate under it. The Phase-1 `check_cancelled` gating already removes the
|
||||
|
||||
Reference in New Issue
Block a user