swactor/src/worker.rs
Zachery Aaron Shores-Chmielewski ed26f0c080 feat(wip): rewrite
Our first implementation is incredibly slow, and failed to scale with increased threads. In order to fix this, we
are implementing cache-aware batching of message processing, and an epoch-based actor rebalancing using shard pools.
2026-01-30 22:52:38 +07:00

46 lines
1.3 KiB
Rust

type WorkerId = usize;
type ActorId = usize;
struct Actor(u8);
const MESSAGE_RING_BUFFER_SIZE: usize = 4096;
const LOCAL_ARENA_BUFFER_SIZE: usize = 262144;
// hitting the maximum would imply reading nothing but length prefixes from the ring channel
const MAX_MESSAGES_PER_DRAIN: usize = MESSAGE_RING_BUFFER_SIZE / 4;
use crate::channel::spsc::Consumer as RingBuffer;
#[repr(align(64))]
struct LocalArena {
data: [u8; LOCAL_ARENA_BUFFER_SIZE],
offsets: [u32; MAX_MESSAGES_PER_DRAIN],
}
struct Worker {
id: WorkerId,
inbox_rings: Vec<RingBuffer<MESSAGE_RING_BUFFER_SIZE>>,
arena: LocalArena,
actor_table: Vec<Actor>,
}
impl Worker {
pub fn run(&mut self) {
// cannot overflow the arena buffer
debug_assert!(self.inbox_rings.len() * MESSAGE_RING_BUFFER_SIZE < LOCAL_ARENA_BUFFER_SIZE);
loop {
// drain messages into our local memory arena buffer
for ring in &self.inbox_rings {
// logic here
}
}
}
}
struct BucketBuffer {
// Pre-allocated array of slices. Max 64K actors, resize if needed.
// bucket[i] contains indices of messages for actor i.
buckets: Vec<Vec<u8>>, // Or flat Vec with head/tail if arena-allocated
actor_order: Vec<ActorId>, // Which actors have messages (for iteration)
}