yring 0.3.3

Bounded SPSC ring with ypipe-style batched flush/prefetch
Documentation
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::thread;
use std::time::{Duration, Instant};

const DURATION: Duration = Duration::from_secs(2);

fn bench<T: Copy + Send + 'static>(cap: usize, batch_size: usize, val: T) {
    let size = std::mem::size_of::<T>();
    let stop = Arc::new(AtomicBool::new(false));
    let sent = Arc::new(AtomicU64::new(0));

    let (mut producer, mut consumer) = yring::spsc::<T>(cap);

    let stop2 = stop.clone();
    let sent2 = sent.clone();
    let sender = thread::spawn(move || {
        let mut count = 0u64;
        let mut pending = 0u64;
        while !stop2.load(Ordering::Relaxed) {
            if producer.push(val).is_ok() {
                count += 1;
                pending += 1;
                if pending >= batch_size as u64 {
                    producer.flush();
                    pending = 0;
                }
            } else {
                producer.flush();
                thread::yield_now();
            }
        }
        producer.flush();
        sent2.store(count, Ordering::Relaxed);
    });

    let start = Instant::now();
    let mut received = 0u64;
    while start.elapsed() < DURATION {
        if consumer.prefetch() > 0 {
            while consumer.pop().is_some() {
                received += 1;
            }
            consumer.release();
        } else {
            thread::yield_now();
        }
    }
    stop.store(true, Ordering::Relaxed);
    sender.join().unwrap();

    let elapsed = start.elapsed();
    let items_per_sec = received as f64 / elapsed.as_secs_f64();
    let mb_per_sec = received as f64 * size as f64 / elapsed.as_secs_f64() / 1_000_000.0;

    println!(
        "  cap={cap:<6} batch={batch_size:<4} {:>7.1}M items/s  {:>5.0} MB/s",
        items_per_sec / 1_000_000.0,
        mb_per_sec,
    );
}

fn main() {
    println!("yring throughput (2s per config)\n");

    println!("--- u64 (8 bytes) ---");
    for cap in [1024, 4096] {
        for batch in [1, 16, 64, 256] {
            bench(cap, batch, 0u64);
        }
        println!();
    }

    println!("--- [u8; 64] (64 bytes) ---");
    for cap in [1024, 4096] {
        for batch in [1, 16, 64, 256] {
            bench(cap, batch, [0u8; 64]);
        }
        println!();
    }

    println!("--- [u8; 128] (128 bytes) ---");
    for cap in [1024, 4096] {
        for batch in [1, 16, 64, 256] {
            bench(cap, batch, [0u8; 128]);
        }
        println!();
    }
}