use docopt::Docopt; use std::io; use std::process; const USAGE: &str = " Usage: cpu_monitor [options] cpu_monitor --help A test for monitoring how much CPU usage Rayon consumes under various scenarios. This test is intended to be executed interactively, like so: cargo run --example cpu_monitor -- tasks_ended The list of scenarios you can try are as follows: - tasks_ended: after all tasks have finished, go to sleep - task_stall_root: a root task stalls for a very long time - task_stall_scope: a task in a scope stalls for a very long time Options: -h, --help Show this message. -d N, --depth N Control how hard the dummy task works [default: 27] "; #[derive(serde::Deserialize)] pub struct Args { arg_scenario: String, flag_depth: usize, } fn main() { let args: &Args = &Docopt::new(USAGE) .and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); match &args.arg_scenario[..] { "tasks_ended" => tasks_ended(args), "task_stall_root" => task_stall_root(args), "task_stall_scope" => task_stall_scope(args), _ => { println!("unknown scenario: `{}`", args.arg_scenario); println!("try --help"); process::exit(1); } } } fn wait_for_user() { let mut input = String::new(); io::stdin().read_line(&mut input).unwrap(); } fn task(args: &Args) { fn join_recursively(n: usize) { if n == 0 { return; } rayon::join(|| join_recursively(n - 1), || join_recursively(n - 1)); } println!("Starting heavy work at depth {}...wait.", args.flag_depth); join_recursively(args.flag_depth); println!("Heavy work done; check top. You should see CPU usage drop to zero soon."); println!("Press to quit..."); } fn tasks_ended(args: &Args) { task(args); wait_for_user(); } fn task_stall_root(args: &Args) { rayon::join(|| task(args), wait_for_user); } fn task_stall_scope(args: &Args) { rayon::scope(|scope| { scope.spawn(move |_| task(args)); scope.spawn(move |_| wait_for_user()); }); }