mod common;
use atap::{Runtime, sleep::Sleep};
use common::cpu_time;
use std::{
thread,
time::{Duration, Instant},
};
#[test]
fn idle_cpu_usage() {
let _ = Runtime::init();
let tasks = 20;
let waiting = Duration::from_secs(5);
println!(
"pid {} idling {} tasks for {:?}",
std::process::id(),
tasks,
waiting,
);
let handles: Vec<_> = (0..tasks)
.map(|_| Runtime::task(Sleep::sleep(waiting)).spawn())
.collect();
thread::sleep(Duration::from_millis(200));
let before = cpu_time();
let started = Instant::now();
let mut shortest = Duration::MAX;
let mut longest = Duration::ZERO;
for handle in handles {
let slept = handle
.join()
.expect("every idling task finishes, rather than failing instantly");
shortest = shortest.min(slept);
longest = longest.max(slept);
}
let window = started.elapsed();
let burnt = cpu_time() - before;
let share = burnt.as_secs_f64() / window.as_secs_f64() * 100.0;
println!(
"{} tasks asked for {:?} and slept {:?} to {:?}, \
burning {:?} of cpu over a {:?} window, {:.3}% of one core",
tasks, waiting, shortest, longest, burnt, window, share,
);
assert!(
shortest >= waiting,
"a sleep asked for {:?} came back after {:?}, which is early",
waiting,
shortest,
);
assert!(
share < 5.0,
"idling {} tasks over a {:?} window burnt {:?} of cpu, {:.3}% of a core, \
so something was awake that should have been parked",
tasks,
window,
burnt,
share,
);
}