//! Actor creation benchmark. //! //! For more info, see `print_help`. use std::env; use std::process; use std::time::SystemTime; use aktrs::actor::{self, Behavior, Behaviors, Pid, SpawnOptions}; use anyhow::Context; fn print_help() { println!( r#"aktrs-example-actor-creation Times how long it takes to create a certain number of actors. USAGE: cargo run --release --example actor_creation ARGUMENTS: N Raises 2 to the power of this number and creates that many actors "# ); } fn main() -> aktrs::Result<()> { let n = if let Some(n) = env::args().nth(1) { n } else { print_help(); process::exit(0); }; let n: u32 = n.parse().with_context(|| format!("failed to parse '{}' as a u32", n))?; if n == 0 { eprintln!("Error: N must be non-zero"); process::exit(1); } let mut sys = actor::System::new()?; sys.spawn(coordinator(n), SpawnOptions::default()); let now = SystemTime::now(); sys.run()?; let elapsed = now.elapsed()?; println!("Time taken: {}.{:06} seconds", elapsed.as_secs(), elapsed.subsec_micros()); Ok(()) } // Creates a coordinator actor that will spawn workers. pub fn coordinator(n: u32) -> Behavior { Behaviors::with_context(move |cx| { cx.spawn(worker(n, cx.this()), SpawnOptions::default()); // Verify that the worker spawned the correct number of actors and exit. let b = Behaviors::receive_message(move |_, result: u32| { debug_assert_eq!(1 << n, result + 1); Ok(Behaviors::stopped()) }); Ok(b.into()) }) } // A worker that spawns 2^n -1 actors. fn worker(spread: u32, mut parent: Pid) -> Behavior { Behaviors::with_context(move |cx| { if spread == 1 { let _ = parent.try_tell(1); Ok(Behaviors::stopped()) } else { cx.spawn(worker(spread - 1, cx.this()), SpawnOptions::default()); cx.spawn(worker(spread - 1, cx.this()), SpawnOptions::default()); let mut first = None; let b = Behaviors::receive_message(move |_, result: u32| { if let Some(first) = first { let _ = parent.try_tell(1 + first + result); Ok(Behaviors::stopped()) } else { first = Some(result); Ok(Behaviors::same()) } }); Ok(b.into()) } }) }