Parent issue
Part of #156 (performance audit findings).
Problem
threads/actor.rs uses rx.recv_timeout(Duration::from_millis(100)) in the message loop to periodically check cancellation_token.is_cancelled():
match rx.recv_timeout(Duration::from_millis(100)) {
Ok(mut envelope) => { /* handle message */ }
Err(RecvTimeoutError::Timeout) => {
if cancellation_token.is_cancelled() { break; }
}
Err(RecvTimeoutError::Disconnected) => break,
}
This causes:
- Up to 100ms shutdown latency after
stop() is called
- 10 wakeups/sec per idle actor (constant CPU churn)
- Unnecessary overhead for applications with many idle actors
Proposed fix
Replace the timeout-based polling with a poison-pill approach:
- Wrap mailbox messages:
enum MailboxItem<A> { Message(Box<dyn Envelope<A>>), Shutdown }
- When
stop() is called, send MailboxItem::Shutdown through the channel
- Replace
recv_timeout with blocking rx.recv()
- On
Shutdown, break the loop — instant cancellation, zero polling
This keeps CancellationToken for timers/streams but removes the polling loop from the core message path.
Files to change
concurrency/src/threads/actor.rs — message loop, stop() impl
- Possibly
rt/src/threads/mod.rs — if channel type changes
Testing
- Existing thread actor tests should pass unchanged
- Add test verifying shutdown latency < 10ms
- Add test verifying idle actor has no CPU wakeups
Parent issue
Part of #156 (performance audit findings).
Problem
threads/actor.rsusesrx.recv_timeout(Duration::from_millis(100))in the message loop to periodically checkcancellation_token.is_cancelled():This causes:
stop()is calledProposed fix
Replace the timeout-based polling with a poison-pill approach:
enum MailboxItem<A> { Message(Box<dyn Envelope<A>>), Shutdown }stop()is called, sendMailboxItem::Shutdownthrough the channelrecv_timeoutwith blockingrx.recv()Shutdown, break the loop — instant cancellation, zero pollingThis keeps
CancellationTokenfor timers/streams but removes the polling loop from the core message path.Files to change
concurrency/src/threads/actor.rs— message loop,stop()implrt/src/threads/mod.rs— if channel type changesTesting