nimbusqueue 0.2.7

fifo collection
Documentation
use criterion::{
    black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, BenchmarkId,
    Criterion, Throughput,
};

#[cfg(feature = "std")]
use nimbusqueue::synchronous_queue::Queue;

#[cfg(feature = "no_std")]
use nimbusqueue::crossbeam_queue::Queue;

use std::time::Duration;

fn bench_queues(c: &mut Criterion) {
    let mut group = c.benchmark_group("queue_operations");

    for size in [100, 1000, 10000].iter() {
        group.throughput(Throughput::Elements(*size as u64));
        bench_enqueue(&mut group, *size);
        bench_dequeue(&mut group, *size);
        bench_mixed(&mut group, *size);
        bench_iterator(&mut group, *size); // Call iterator benchmark
        bench_concurrent(&mut group, *size); // Call concurrent benchmark
    }

    group.finish();
}

fn bench_enqueue(group: &mut BenchmarkGroup<WallTime>, size: usize) {
    // SegQueue enqueue
    #[cfg(feature = "no_std")]
    group.bench_function(BenchmarkId::new("SegQueue/enqueue", size), |b| {
        let queue = Queue::new_segmented();
        let mut i = 0;
        b.iter(|| {
            queue.enqueue(black_box(i)).unwrap();
            i = (i + 1) % size;
        });
    });

    // ArrayQueue enqueue
    #[cfg(feature = "no_std")]
    group.bench_function(BenchmarkId::new("ArrayQueue/enqueue", size), |b| {
        let queue = Queue::new_array(size);
        let mut i = 0;
        b.iter(|| {
            let _ = queue.enqueue(black_box(i));
            i = (i + 1) % size;
        });
    });

    #[cfg(feature = "std")]
    // SyncQueue enqueue
    group.bench_function(BenchmarkId::new("SyncQueue/enqueue", size), |b| {
        let queue = Queue::new();
        let mut i = 0;
        b.iter(|| {
            queue.enqueue(black_box(i));
            i = (i + 1) % size;
        });
    });
}

fn bench_dequeue(group: &mut BenchmarkGroup<WallTime>, size: usize) {
    // SegQueue dequeue
    #[cfg(feature = "no_std")]
    group.bench_function(BenchmarkId::new("SegQueue/dequeue", size), |b| {
        b.iter_batched(
            || {
                let queue = Queue::new_segmented();
                for i in 0..size {
                    queue.enqueue(i).unwrap();
                }
                queue
            },
            |queue| {
                for _ in 0..size {
                    black_box(queue.dequeue());
                }
            },
            criterion::BatchSize::LargeInput,
        );
    });

    // ArrayQueue dequeue
    #[cfg(feature = "no_std")]
    group.bench_function(BenchmarkId::new("ArrayQueue/dequeue", size), |b| {
        b.iter_batched(
            || {
                let queue = Queue::new_array(size);
                for i in 0..size {
                    queue.enqueue(i).unwrap();
                }
                queue
            },
            |queue| {
                for _ in 0..size {
                    black_box(queue.dequeue());
                }
            },
            criterion::BatchSize::LargeInput,
        );
    });

    #[cfg(feature = "std")]
    // SyncQueue dequeue
    group.bench_function(BenchmarkId::new("SyncQueue/dequeue", size), |b| {
        b.iter_batched(
            || {
                let queue = Queue::new();
                for i in 0..size {
                    queue.enqueue(i);
                }
                queue
            },
            |queue| {
                for _ in 0..size {
                    black_box(queue.dequeue());
                }
            },
            criterion::BatchSize::LargeInput,
        );
    });
}

fn bench_mixed(group: &mut BenchmarkGroup<WallTime>, size: usize) {
    // SegQueue mixed operations
    #[cfg(feature = "no_std")]
    group.bench_function(BenchmarkId::new("SegQueue/mixed", size), |b| {
        let queue = Queue::new_segmented();
        b.iter(|| {
            for i in 0..(size / 2) {
                queue.enqueue(black_box(i)).unwrap();
            }
            for _ in 0..(size / 2) {
                black_box(queue.dequeue());
            }
        });
    });

    // ArrayQueue mixed operations
    #[cfg(feature = "no_std")]
    group.bench_function(BenchmarkId::new("ArrayQueue/mixed", size), |b| {
        let queue = Queue::new_array(size);
        b.iter(|| {
            for i in 0..(size / 2) {
                queue.enqueue(black_box(i)).unwrap();
            }
            for _ in 0..(size / 2) {
                black_box(queue.dequeue());
            }
        });
    });

    #[cfg(feature = "std")]
    // SyncQueue mixed operations
    group.bench_function(BenchmarkId::new("SyncQueue/mixed", size), |b| {
        let queue = Queue::new();
        b.iter(|| {
            for i in 0..(size / 2) {
                queue.enqueue(black_box(i));
            }
            for _ in 0..(size / 2) {
                black_box(queue.dequeue());
            }
        });
    });
}

fn bench_iterator(group: &mut BenchmarkGroup<WallTime>, size: usize) {
    // SegQueue iterator
    #[cfg(feature = "no_std")]
    group.bench_function(BenchmarkId::new("SegQueue/iter", size), |b| {
        let queue = Queue::new_segmented();
        for i in 0..size {
            queue.enqueue(i).unwrap();
        }
        b.iter(|| {
            for item in queue.iter() {
                black_box(item);
            }
        });
    });

    // ArrayQueue iterator
    #[cfg(feature = "no_std")]
    group.bench_function(BenchmarkId::new("ArrayQueue/iter", size), |b| {
        let queue = Queue::new_array(size);
        for i in 0..size {
            queue.enqueue(i).unwrap();
        }
        b.iter(|| {
            for item in queue.iter() {
                black_box(item);
            }
        });
    });

    #[cfg(feature = "std")]
    // SyncQueue iterator
    group.bench_function(BenchmarkId::new("SyncQueue/iter", size), |b| {
        let queue = Queue::new();
        for i in 0..size {
            queue.enqueue(i);
        }
        b.iter(|| {
            for item in queue.iter() {
                black_box(item);
            }
        });
    });
}

fn bench_concurrent(group: &mut BenchmarkGroup<WallTime>, size: usize) {
    use std::sync::Arc;
    use std::thread;

    // SegQueue concurrent operations
    #[cfg(feature = "no_std")]
    group.bench_function(BenchmarkId::new("SegQueue/concurrent", size), |b| {
        b.iter(|| {
            let queue = Arc::new(Queue::new_segmented());
            let mut handles = vec![];

            // Spawn producer threads
            for i in 0..4 {
                let queue = Arc::clone(&queue);
                let handle = thread::spawn(move || {
                    for j in 0..(size / 4) {
                        queue.enqueue(i * (size / 4) + j).unwrap();
                    }
                });
                handles.push(handle);
            }

            // Spawn consumer threads
            for _ in 0..4 {
                let queue = Arc::clone(&queue);
                let handle = thread::spawn(move || {
                    for _ in 0..(size / 4) {
                        while queue.dequeue().is_none() {
                            thread::yield_now();
                        }
                    }
                });
                handles.push(handle);
            }

            // Wait for all threads to complete
            for handle in handles {
                handle.join().unwrap();
            }
        });
    });

    // ArrayQueue concurrent operations
    #[cfg(feature = "no_std")]
    group.bench_function(BenchmarkId::new("ArrayQueue/concurrent", size), |b| {
        b.iter(|| {
            let queue = Arc::new(Queue::new_array(size));
            let mut handles = vec![];

            // Spawn producer threads
            for i in 0..4 {
                let queue = Arc::clone(&queue);
                let handle = thread::spawn(move || {
                    for j in 0..(size / 4) {
                        while queue.enqueue(i * (size / 4) + j).is_err() {
                            thread::yield_now();
                        }
                    }
                });
                handles.push(handle);
            }

            // Spawn consumer threads
            for _ in 0..4 {
                let queue = Arc::clone(&queue);
                let handle = thread::spawn(move || {
                    for _ in 0..(size / 4) {
                        while queue.dequeue().is_none() {
                            thread::yield_now();
                        }
                    }
                });
                handles.push(handle);
            }

            // Wait for all threads to complete
            for handle in handles {
                handle.join().unwrap();
            }
        });
    });

    #[cfg(feature = "std")]
    // SyncQueue concurrent operations
    group.bench_function(BenchmarkId::new("SyncQueue/concurrent", size), |b| {
        b.iter(|| {
            let queue = Arc::new(Queue::new());
            let mut handles = vec![];

            // Spawn producer threads
            for i in 0..4 {
                let queue = Arc::clone(&queue);
                let handle = thread::spawn(move || {
                    for j in 0..(size / 4) {
                        queue.enqueue(i * (size / 4) + j);
                    }
                });
                handles.push(handle);
            }

            // Spawn consumer threads
            for _ in 0..4 {
                let queue = Arc::clone(&queue);
                let handle = thread::spawn(move || {
                    for _ in 0..(size / 4) {
                        queue.dequeue();
                    }
                });
                handles.push(handle);
            }

            // Wait for all threads to complete
            for handle in handles {
                handle.join().unwrap();
            }
        });
    });
}

criterion_group!(
    name = benches;
    config = Criterion::default()
        .with_plots()
        .sample_size(100)
        .measurement_time(Duration::from_secs(10))
        .warm_up_time(Duration::from_secs(1))
        .confidence_level(0.95)
        .noise_threshold(0.02);
    targets = bench_queues
);
criterion_main!(benches);