benches: expose preemption knobs + sweep runner

Config API changes (src/preempt.rs, src/runtime.rs):
- preempt: promote ALLOC_INTERVAL and TIMESLICE_CYCLES from bare consts to
  DEFAULT_ALLOC_INTERVAL / DEFAULT_TIMESLICE_CYCLES; store active values in
  thread-locals set on each actor resume so multiple runtimes can use
  different settings concurrently.
- runtime: add alloc_interval / timeslice_cycles fields to Config; add
  Config::alloc_interval(n) and Config::timeslice_cycles(c) builder methods;
  thread the values through RuntimeInner to the reset_timeslice() call in
  schedule_loop.

Bench changes:
- Add bench_cfg(threads) helper to general/tokio_favored/smarm_favored that
  wraps Config::exact and reads SMARM_ALLOC_INTERVAL / SMARM_TIMESLICE_CYCLES
  env vars, so the sweep script can vary knobs without recompiling.

Sweep tooling (benches/sweep.py):
- 'run':     run the 3-file bench suite once; --save-baseline persists JSON
- 'regress': compare current run against baseline.json, exit 1 on any bench
             that regresses >10% vs stored medians
- 'sweep':   run the full SWEEP_GRID (10 points), print comparison table,
             optional --save-csv; binaries pre-built so no recompile per point

Sweep results (10-point grid, 1-CPU sandbox):
- The preemption knobs have very little effect on this single-CPU machine.
  Most benches move <5% across the entire grid.
- Longer timeslices (tc=600k, tc=1200k) reliably hurt spawn_storm_busy
  (+11-15%) and catch_unwind_panics (+10-12%) because actors hold the
  scheduler mutex longer per timeslice, stalling the storm of joinable tasks.
- Shorter timeslices (tc=150k) give a small improvement on many_timers
  (-3-4%) and a wash everywhere else.
- yield_in_hot_loop and uncontended_channel are essentially flat across all
  knobs — both are scheduling-dominated and call yield_now explicitly, so
  the RDTSC-driven preemption path is irrelevant.
- Conclusion: the knobs matter primarily under contention (multi-core).
  Re-run sweep on a multi-core machine before drawing tuning conclusions.
This commit is contained in:
Bench
2026-05-24 11:48:15 +00:00
committed by smarm
parent 6d1c59fb99
commit 3da6ffaa77
15 changed files with 2315 additions and 8 deletions

View File

@@ -0,0 +1,126 @@
smarm general benchmarks
available parallelism: 1 threads
ITERS=15 (+1 warmup, discarded)
CHAIN_DEPTH=1000, YIELD_TASKS=200×1000, PRIME_N=400000/64 workers, PP_ROUNDS=1000
================================================================================
chained_spawn: depth 1000
================================================================================
runtime | result | median µs | min µs | max µs
--------------------------------------------------------------------------------
smarm 1-thread | 1000 | 8735 | 8508 | 9314
smarm 1-thread | 1000 | 8808 | 8506 | 10346
tokio current_thread | 1000 | 123 | 123 | 172
tokio multi-thread | 1000 | 190 | 184 | 273
================================================================================
yield_many: 200 tasks × 1000 yields
================================================================================
runtime | result | median µs | min µs | max µs
--------------------------------------------------------------------------------
smarm 1-thread | 200000 | 41619 | 41255 | 43489
smarm 1-thread | 200000 | 41544 | 41196 | 43259
tokio current_thread | 200000 | 15382 | 15233 | 16007
tokio multi-thread | 200000 | 16095 | 15999 | 16296
================================================================================
fan_out_compute: primes in [2, 400000) across 64
================================================================================
runtime | result | median µs | min µs | max µs
--------------------------------------------------------------------------------
smarm 1-thread | 33860 | 30032 | 29838 | 31744
smarm 1-thread | 33860 | 29782 | 29653 | 30601
tokio current_thread | 33860 | 28754 | 28614 | 30700
tokio multi-thread | 33860 | 34988 | 34570 | 36871
================================================================================
ping_pong_oneshot: 1000 rounds
================================================================================
runtime | result | median µs | min µs | max µs
--------------------------------------------------------------------------------
smarm 1-thread | 1000 | 17088 | 16868 | 18654
smarm 1-thread | 1000 | 16951 | 16797 | 17783
tokio current_thread | 1000 | 932 | 899 | 1019
tokio multi-thread | 1000 | 4340 | 4273 | 5245
smarm tokio-favored benchmarks
available parallelism: 1 threads
ITERS=15 (+1 warmup, discarded)
STORM_BACKGROUND=8, STORM_SPAWN=10000, MPSC=32×10000, TIMER_ACTORS=10000 (110 ms), SCALING_N=400000/64
================================================================================
spawn_storm_busy: 8 bg yielders + 10000 zero-work spawns
================================================================================
runtime | result | median µs | min µs | max µs
--------------------------------------------------------------------------------
smarm 1-thread | 10000 | 129009 | 127353 | 132990
smarm 1-thread | 10000 | 128009 | 126554 | 140472
tokio current_thread | 10000 | 2666 | 2624 | 2794
tokio multi-thread | 10000 | 5974 | 4368 | 11517
================================================================================
mpsc_contention: 32 producers × 10000 msgs → 1 consumer
================================================================================
runtime | result | median µs | min µs | max µs
--------------------------------------------------------------------------------
smarm 1-thread | 320000 | 9044 | 8970 | 10788
smarm 1-thread | 320000 | 9087 | 8995 | 12500
tokio current_thread | 320000 | 17185 | 17072 | 18440
tokio multi-thread | 320000 | 17720 | 17394 | 19182
================================================================================
many_timers: 10000 actors sleeping 110 ms
================================================================================
runtime | result | median µs | min µs | max µs
--------------------------------------------------------------------------------
smarm 1-thread | 10000 | 145819 | 140671 | 150512
smarm 1-thread | 10000 | 139046 | 135846 | 146127
tokio current_thread | 10000 | 13866 | 13522 | 14670
tokio multi-thread | 10000 | 14900 | 14471 | 16378
================================================================================
multi_thread_scaling: primes in [2, 400000) across 64 workers
================================================================================
runtime | result | median µs | min µs | max µs
--------------------------------------------------------------------------------
smarm 1-thread | 33860 | 30695 | 29720 | 33196
tokio multi 1-thread | 33860 | 29261 | 28895 | 31013
smarm smarm-favored benchmarks
available parallelism: 1 threads
ITERS=15 (+1 warmup, discarded)
RECURSE_DEPTH=500, HOT_YIELDS=500000×2, UNCONT_MSGS=1000000, PANIC_TASKS=10000
================================================================================
deep_recursion: depth 500
================================================================================
runtime | result | median µs | min µs | max µs
--------------------------------------------------------------------------------
smarm 1-thread | 1 | 82 | 79 | 113
smarm 1-thread | 1 | 85 | 78 | 143
tokio current_thread | 1 | 25 | 25 | 56
tokio multi-thread | 1 | 50 | 47 | 63
================================================================================
yield_in_hot_loop: 2 actors × 500000 yields (single thread)
================================================================================
runtime | result | median µs | min µs | max µs
--------------------------------------------------------------------------------
smarm 1-thread | 1000000 | 188698 | 187922 | 192263
tokio current_thread | 1000000 | 150231 | 148746 | 151723
================================================================================
uncontended_channel: 1→1, 1000000 msgs (single thread)
================================================================================
runtime | result | median µs | min µs | max µs
--------------------------------------------------------------------------------
smarm 1-thread | 1000000 | 28461 | 27638 | 30283
tokio current_thread | 1000000 | 52224 | 51880 | 54732
================================================================================
catch_unwind_panics: 10000 tasks, 50% panic
================================================================================
runtime | result | median µs | min µs | max µs
--------------------------------------------------------------------------------
smarm 1-thread | 10000 | 144604 | 143246 | 145585
smarm 1-thread | 10000 | 148208 | 142691 | 151076
tokio current_thread | 10000 | 265255 | 260637 | 271065
tokio multi-thread | 10000 | 273131 | 271313 | 300420