atap 0.1.0

Threadsafe futureless async runtime for macOS
//! # Idle CPU Usage
//! What the runtime costs while it has nothing to do but wait

mod common;

use atap::{Runtime, sleep::Sleep};
use common::cpu_time;
use std::{
    thread,
    time::{Duration, Instant},
};

/// A runtime with every task parked in a long sleep uses
/// almost no cpu
#[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,
    );

    // Given a moment to get everything parked, so the threads
    // starting up aren't charged to the idling
    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;

    // Against one core, since a single spinning thread is the
    // thing worth catching
    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,
    );

    // No sleep came back early
    assert!(
        shortest >= waiting,
        "a sleep asked for {:?} came back after {:?}, which is early",
        waiting,
        shortest,
    );

    // A thread spinning out the whole wait would be 100% of a core
    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,
    );
}