llam 0.1.3

Safe, Go-style Rust bindings for the LLAM runtime
use std::time::{Duration, Instant};

fn main() {
    let iters = std::env::args()
        .nth(1)
        .and_then(|value| value.parse::<usize>().ok())
        .unwrap_or(20_000);

    llam::Runtime::builder()
        .profile(llam::Profile::ReleaseFast)
        .run(move || {
            bench_spawn_join(iters)?;
            bench_channel_pingpong(iters)?;
            bench_select_default(iters)?;
            Ok(())
        })
        .expect("LLAM-rs benchmark failed");
}

fn report(name: &str, iters: usize, elapsed: Duration) {
    let seconds = elapsed.as_secs_f64().max(1e-9);
    let ops = iters as f64 / seconds;
    println!("{name:20} {ops:12.2} ops/s  elapsed={elapsed:?}");
}

fn bench_spawn_join(iters: usize) -> llam::Result<()> {
    let start = Instant::now();
    for _ in 0..iters {
        let handle = llam::spawn!({ 1usize });
        assert_eq!(handle.join().expect("join failed"), 1);
    }
    report("spawn_join", iters, start.elapsed());
    Ok(())
}

fn bench_channel_pingpong(iters: usize) -> llam::Result<()> {
    let (tx_a, rx_a) = llam::channel::bounded::<usize>(1)?;
    let (tx_b, rx_b) = llam::channel::bounded::<usize>(1)?;
    let peer = llam::spawn!(move {
        for _ in 0..iters {
            let value = rx_a.recv().unwrap();
            tx_b.send(value + 1).unwrap();
        }
    });

    let start = Instant::now();
    for i in 0..iters {
        tx_a.send(i).expect("send failed");
        assert_eq!(rx_b.recv()?, i + 1);
    }
    peer.join().expect("peer join failed");
    report("channel_pingpong", iters, start.elapsed());
    Ok(())
}

fn bench_select_default(iters: usize) -> llam::Result<()> {
    let (_tx, rx) = llam::channel::bounded::<usize>(1)?;
    let start = Instant::now();
    let mut hits = 0usize;
    for _ in 0..iters {
        let defaulted = llam::select! {
            recv(rx) -> value => {
                let _ = value;
                false
            },
            default => {
                true
            },
        };
        hits += usize::from(defaulted);
    }
    assert_eq!(hits, iters);
    report("select_default", iters, start.elapsed());
    Ok(())
}