diff --git a/src/serve.rs b/src/serve.rs index e6c0d25..2124ad2 100644 --- a/src/serve.rs +++ b/src/serve.rs @@ -65,6 +65,12 @@ pub struct Config { /// Default: 256 KiB. The reserve is virtual/demand-paged, so raising it /// costs address space, not RSS, until a handler actually uses it. pub conn_stack_reserve: usize, + /// Maximum concurrently-live actors — smarm's fixed slot slab, allocated + /// once at init. Each connection is one actor, so this is also the hard + /// cap on concurrent connections. `None` uses smarm's default (16_384). + /// Slots are ~256 B, so raising this is cheap relative to per-connection + /// stacks; size it to peak concurrent connections. + pub max_actors: Option, } /// Default per-connection actor stack reserve (see [`Config::conn_stack_reserve`]). @@ -90,6 +96,7 @@ impl Config { max_message_bytes: 4 * 1024 * 1024, scheduler_threads: None, conn_stack_reserve: DEFAULT_CONN_STACK_RESERVE, + max_actors: None, } } @@ -326,10 +333,13 @@ pub fn serve_with_shutdown( let conn_stack_reserve = config.conn_stack_reserve; let drain_timeout = config.drain_timeout; - let smarm_cfg = match config.scheduler_threads { + let mut smarm_cfg = match config.scheduler_threads { Some(n) => smarm::Config::exact(n), None => smarm::Config::default(), }; + if let Some(m) = config.max_actors { + smarm_cfg = smarm_cfg.max_actors(m); + } let rt = smarm::init(smarm_cfg); // Listener self-termination flag — see the shutdown sequence below. let shutdown_flag = Arc::new(AtomicBool::new(false));