RFC 016 Chunk 2b: per-actor messages-received counter
Tally each dequeued message against the receiving actor, surfaced as
ActorInfo.messages_received (the 'is this actor draining slower than its
mailbox fills' signal).
- messages-received, not sent (D4): the receiver counts on its own
thread, so it's a single-writer Relaxed load+store on a hot Slot
AtomicU64, no atomic RMW (D5); reuses the stashed *const Slot from 2a.
- Incremented at all six channel dequeue-success sites (recv,
recv_timeout x2, recv_match, try_recv_match, try_recv) via
preempt::note_message_received; no-op outside an actor (null slot).
- Resets with overruns in reset_counters across the three lifecycle
sites (D7).
Matrix: debug default + rq-mpmc + rq-striped + release green; loom
slot_state/run_queue models pass (the 3 send_after_to loom failures are
pre-existing at fc014c4 — plain #[test]s under --cfg loom, not Chunk 2).
This commit is contained in:
@@ -434,6 +434,11 @@ pub(crate) struct Slot {
|
||||
/// than `SlotCold` so the increment needs no lock; reset across reuse like
|
||||
/// every other slot field (`vacant` / `reclaim_slot` / `install_actor`).
|
||||
overruns: AtomicU64,
|
||||
/// RFC 016 Chunk 2 — messages this actor has received (dequeued). Same
|
||||
/// single-writer discipline as `overruns`: only the receiving actor, on its
|
||||
/// own thread, increments it on the receive path (D4/D5), Relaxed load+store
|
||||
/// with no RMW; snapshot reads Relaxed.
|
||||
messages_received: AtomicU64,
|
||||
/// Cold lifecycle data. See [`SlotCold`].
|
||||
pub(crate) cold: RawMutex<SlotCold>,
|
||||
}
|
||||
@@ -446,6 +451,7 @@ impl Slot {
|
||||
stop_ptr: AtomicPtr::new(std::ptr::null_mut()),
|
||||
closure: AtomicPtr::new(std::ptr::null_mut()),
|
||||
overruns: AtomicU64::new(0),
|
||||
messages_received: AtomicU64::new(0),
|
||||
cold: RawMutex::new(SlotCold {
|
||||
actor: None,
|
||||
waiters: Vec::new(),
|
||||
@@ -490,6 +496,21 @@ impl Slot {
|
||||
self.overruns.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Tally one received (dequeued) message. Same single-writer Relaxed
|
||||
/// discipline as `record_overrun`; called by the receiving actor on its own
|
||||
/// thread, so no RMW.
|
||||
#[inline]
|
||||
pub(crate) fn record_message(&self) {
|
||||
let v = self.messages_received.load(Ordering::Relaxed);
|
||||
self.messages_received.store(v.wrapping_add(1), Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// Read the received-message tally (Relaxed; cross-thread snapshot read).
|
||||
#[inline]
|
||||
pub(crate) fn messages_received(&self) -> u64 {
|
||||
self.messages_received.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Zero the per-actor introspection counters. Called at every point a slot
|
||||
/// is recycled or freshly occupied (`reclaim_slot`, `install_actor`) so a
|
||||
/// reused slot never carries a previous incarnation's counts — the standing
|
||||
@@ -497,6 +518,7 @@ impl Slot {
|
||||
#[inline]
|
||||
pub(crate) fn reset_counters(&self) {
|
||||
self.overruns.store(0, Ordering::Relaxed);
|
||||
self.messages_received.store(0, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// A pid's-eye snapshot of the slot. Cold paths re-read this under the
|
||||
|
||||
Reference in New Issue
Block a user