Files
smarm/benches/baseline.json
T
smarm 72f5d38e5d perf: reduce scheduler mutex contention + stack pool
Three changes, each independently measured, landed together.

Fuse pre-resume mutex acquisitions
-----------------------------------
The schedule loop previously took the shared lock three separate times
per actor resume: once to pop the run queue, once to read the stack
pointer, and once to pop the first-resume closure. These are now a
single acquisition that returns everything needed to resume the actor.

As a side effect, pending_closures was changed from a Vec<(Pid, Closure)>
with O(n) linear scan to a Vec<Option<Closure>> indexed by slot index,
making first-closure lookup O(1).

Move stack allocation outside the shared lock
----------------------------------------------
Stack::new() (mmap + mprotect) was previously called inside with_shared,
stalling every other scheduler thread for the duration of two syscalls on
every spawn. It now runs before the lock is acquired.

Stack pool
----------
Rather than munmap-ing a stack when an actor finishes and mmap-ing a fresh
one on the next spawn, stacks are now recycled through a per-Runtime pool
(Mutex<Vec<Stack>>). finalize_actor extracts the stack from the Actor
before clearing the slot and pushes it to the pool outside the shared lock.
spawn_under pops from the pool before falling back to Stack::new().

The pool is unbounded for now (shrink policy TBD) but capped at
stack_pool_cap stacks on return, defaulting to thread_count * 4.
The cap is configurable via Config::stack_pool_cap(n).

Results (24-thread, against stored baseline)
--------------------------------------------
chained_spawn      smarm 1-thread:   9763 → 261 µs   (-97%)
chained_spawn      smarm 24-thread: 23562 → 838 µs   (-96%)
ping_pong_oneshot  smarm 1-thread:  18409 → 742 µs   (-96%)
ping_pong_oneshot  smarm 24-thread: 44596 → 1425 µs  (-97%)
catch_unwind_panics smarm 24-thread: 267812 → 124094 µs (-54%)
fan_out_compute    smarm 24-thread:   2839 → 2226 µs  (-22%)

Tokio regressions in the checker output are baseline measurement drift;
no tokio code was changed.
2026-05-25 23:28:11 +02:00

186 lines
3.4 KiB
JSON

{
"chained_spawn": {
"smarm 1-thread": {
"result": 1000,
"median": 273,
"min": 261,
"max": 292
},
"smarm 24-thread": {
"result": 1000,
"median": 837,
"min": 788,
"max": 913
},
"tokio current_thread": {
"result": 1000,
"median": 68,
"min": 61,
"max": 113
},
"tokio multi-thread": {
"result": 1000,
"median": 200,
"min": 176,
"max": 230
}
},
"yield_many": {
"smarm 1-thread": {
"result": 200000,
"median": 19465,
"min": 19299,
"max": 20007
},
"smarm 24-thread": {
"result": 200000,
"median": 163921,
"min": 155700,
"max": 167921
},
"tokio current_thread": {
"result": 200000,
"median": 5022,
"min": 5001,
"max": 5530
},
"tokio multi-thread": {
"result": 200000,
"median": 8341,
"min": 7412,
"max": 9199
}
},
"fan_out_compute": {
"smarm 1-thread": {
"result": 33860,
"median": 14096,
"min": 13982,
"max": 17406
},
"smarm 24-thread": {
"result": 33860,
"median": 2475,
"min": 2264,
"max": 2589
},
"tokio current_thread": {
"result": 33860,
"median": 12640,
"min": 12548,
"max": 15881
},
"tokio multi-thread": {
"result": 33860,
"median": 1483,
"min": 1395,
"max": 1710
}
},
"ping_pong_oneshot": {
"smarm 1-thread": {
"result": 1000,
"median": 801,
"min": 720,
"max": 929
},
"smarm 24-thread": {
"result": 1000,
"median": 1449,
"min": 1292,
"max": 1530
},
"tokio current_thread": {
"result": 1000,
"median": 398,
"min": 369,
"max": 407
},
"tokio multi-thread": {
"result": 1000,
"median": 10497,
"min": 9238,
"max": 11961
}
},
"deep_recursion": {
"smarm 1-thread": {
"result": 1,
"median": 136,
"min": 117,
"max": 163
},
"smarm 24-thread": {
"result": 1,
"median": 743,
"min": 654,
"max": 845
},
"tokio current_thread": {
"result": 1,
"median": 14,
"min": 14,
"max": 16
},
"tokio multi-thread": {
"result": 1,
"median": 61,
"min": 47,
"max": 94
}
},
"yield_in_hot_loop": {
"smarm 1-thread": {
"result": 1000000,
"median": 83281,
"min": 80264,
"max": 85697
},
"tokio current_thread": {
"result": 1000000,
"median": 75538,
"min": 69842,
"max": 78823
}
},
"uncontended_channel": {
"smarm 1-thread": {
"result": 1000000,
"median": 9440,
"min": 9393,
"max": 13168
},
"tokio current_thread": {
"result": 1000000,
"median": 17817,
"min": 16926,
"max": 18572
}
},
"catch_unwind_panics": {
"smarm 1-thread": {
"result": 10000,
"median": 133840,
"min": 130425,
"max": 139709
},
"smarm 24-thread": {
"result": 10000,
"median": 128729,
"min": 108091,
"max": 132700
},
"tokio current_thread": {
"result": 10000,
"median": 10681,
"min": 10158,
"max": 11644
},
"tokio multi-thread": {
"result": 10000,
"median": 6700,
"min": 2778,
"max": 7453
}
}
}