mod common;
use std::cell::Cell;
use std::rc::Rc;
use std::time::Duration;
use common::time_on_runtime;
use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
use runite::channel::{mpsc, oneshot};
use runite::time::sleep;
fn bench_spawn_join(c: &mut Criterion) {
c.bench_function("spawn_join", |b| {
b.iter_custom(|iters| {
time_on_runtime(move || async move {
for _ in 0..iters {
let handle = runite::spawn(async { 1u64 });
let _ = handle.await;
}
})
});
});
}
fn bench_yield(c: &mut Criterion) {
c.bench_function("yield_now", |b| {
b.iter_custom(|iters| {
time_on_runtime(move || async move {
for _ in 0..iters {
runite::yield_now().await;
}
})
});
});
}
fn bench_oneshot(c: &mut Criterion) {
c.bench_function("oneshot_roundtrip", |b| {
b.iter_custom(|iters| {
time_on_runtime(move || async move {
for i in 0..iters {
let (tx, mut rx) = oneshot::channel::<u64>();
let _ = tx.send(i);
let _ = rx.recv().await;
}
})
});
});
}
fn bench_mpsc_pingpong(c: &mut Criterion) {
c.bench_function("mpsc_pingpong", |b| {
b.iter_custom(|iters| {
time_on_runtime(move || async move {
let (tx, mut rx) = mpsc::channel::<u64>(16);
let producer = runite::spawn(async move {
for i in 0..iters {
if tx.send(i).await.is_err() {
break;
}
}
});
for _ in 0..iters {
if rx.recv().await.is_none() {
break;
}
}
let _ = producer.await;
})
});
});
}
fn bench_timer_churn(c: &mut Criterion) {
let mut group = c.benchmark_group("timer");
group.measurement_time(Duration::from_secs(8));
group.bench_function("zero_sleep", |b| {
b.iter_custom(|iters| {
time_on_runtime(move || async move {
for _ in 0..iters {
sleep(Duration::ZERO).await;
}
})
});
});
group.finish();
}
fn bench_spawn_many(c: &mut Criterion) {
let mut group = c.benchmark_group("spawn_many");
for size in [100u64, 1_000, 10_000] {
group.throughput(Throughput::Elements(size));
group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &size| {
b.iter_custom(|iters| {
time_on_runtime(move || async move {
for _ in 0..iters {
let handles: Vec<_> =
(0..size).map(|i| runite::spawn(async move { i })).collect();
for handle in handles {
let _ = handle.await;
}
}
})
});
});
}
group.finish();
}
fn bench_mpsc_throughput(c: &mut Criterion) {
const SIZE: u64 = 10_000;
let mut group = c.benchmark_group("mpsc_throughput");
group.throughput(Throughput::Elements(SIZE));
group.bench_function("stream_10k", |b| {
b.iter_custom(|iters| {
time_on_runtime(move || async move {
for _ in 0..iters {
let (tx, mut rx) = mpsc::channel::<u64>(64);
let producer = runite::spawn(async move {
for i in 0..SIZE {
if tx.send(i).await.is_err() {
break;
}
}
});
let mut received = 0u64;
while rx.recv().await.is_some() {
received += 1;
if received == SIZE {
break;
}
}
let _ = producer.await;
}
})
});
});
group.finish();
}
fn bench_queueables(c: &mut Criterion) {
const BATCH: u64 = 1_000;
let mut group = c.benchmark_group("queueable");
group.throughput(Throughput::Elements(BATCH));
group.bench_function("microtask", |b| {
b.iter_custom(|iters| {
time_on_runtime(move || async move {
let counter = Rc::new(Cell::new(0u64));
for _ in 0..iters {
counter.set(0);
let (tx, mut rx) = oneshot::channel::<()>();
for _ in 0..BATCH {
let counter = Rc::clone(&counter);
runite::queue_microtask(move || counter.set(counter.get() + 1));
}
runite::queue_microtask(move || {
let _ = tx.send(());
});
let _ = rx.recv().await;
debug_assert_eq!(counter.get(), BATCH);
}
})
});
});
group.bench_function("macrotask", |b| {
b.iter_custom(|iters| {
time_on_runtime(move || async move {
let counter = Rc::new(Cell::new(0u64));
for _ in 0..iters {
counter.set(0);
let (tx, mut rx) = oneshot::channel::<()>();
for _ in 0..BATCH {
let counter = Rc::clone(&counter);
runite::queue_macrotask(move || counter.set(counter.get() + 1));
}
runite::queue_macrotask(move || {
let _ = tx.send(());
});
let _ = rx.recv().await;
debug_assert_eq!(counter.get(), BATCH);
}
})
});
});
group.finish();
}
criterion_group!(
benches,
bench_spawn_join,
bench_yield,
bench_oneshot,
bench_mpsc_pingpong,
bench_timer_churn,
bench_spawn_many,
bench_mpsc_throughput,
bench_queueables,
);
criterion_main!(benches);