166 lines
5.2 KiB
Rust
166 lines
5.2 KiB
Rust
//! Runtime comparison benchmarks
|
|
//!
|
|
//! Compares announcement performance across different async runtimes.
|
|
//! This verifies the runtime-agnostic design works consistently.
|
|
//!
|
|
//! Runtimes tested:
|
|
//! - tokio (most popular)
|
|
//! - smol (lightweight alternative)
|
|
//!
|
|
//! Expected result: Similar performance across runtimes since announcement
|
|
//! uses event-listener which abstracts runtime details.
|
|
|
|
#![allow(unused_must_use)]
|
|
|
|
use announcement::Announcement;
|
|
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
|
|
use std::hint::black_box;
|
|
use std::sync::Arc;
|
|
|
|
/// Benchmark: Basic announce and listen - tokio vs smol
|
|
fn bench_basic(c: &mut Criterion) {
|
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
|
let mut group = c.benchmark_group("runtimes/basic");
|
|
|
|
// Tokio version
|
|
group.bench_function("tokio", |b| {
|
|
b.to_async(&rt).iter(|| async {
|
|
let (announcer, announcement) = Announcement::new();
|
|
let listener = announcement.listener();
|
|
|
|
let handle = tokio::spawn(async move { listener.listen().await });
|
|
announcer.announce(Arc::new(42)).unwrap();
|
|
|
|
black_box(handle.await.unwrap());
|
|
});
|
|
});
|
|
|
|
// Smol version
|
|
group.bench_function("smol", |b| {
|
|
b.iter(|| {
|
|
smol::block_on(async {
|
|
let (announcer, announcement) = Announcement::new();
|
|
let listener = announcement.listener();
|
|
|
|
let handle = smol::spawn(async move { listener.listen().await });
|
|
announcer.announce(Arc::new(42)).unwrap();
|
|
|
|
black_box(handle.await);
|
|
});
|
|
});
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
/// Benchmark: Fanout to multiple listeners - tokio vs smol
|
|
fn bench_fanout(c: &mut Criterion) {
|
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
|
let mut group = c.benchmark_group("runtimes/fanout");
|
|
|
|
for n in [10, 100, 500].iter() {
|
|
group.throughput(Throughput::Elements(*n as u64));
|
|
|
|
// Tokio version
|
|
group.bench_with_input(BenchmarkId::new("tokio", n), n, |b, &n| {
|
|
b.to_async(&rt).iter(|| async move {
|
|
let (announcer, announcement) = Announcement::new();
|
|
|
|
let mut handles = Vec::with_capacity(n);
|
|
for _ in 0..n {
|
|
let listener = announcement.listener();
|
|
handles.push(tokio::spawn(async move { listener.listen().await }));
|
|
}
|
|
|
|
announcer.announce(Arc::new(42)).unwrap();
|
|
|
|
for h in handles {
|
|
black_box(h.await.unwrap());
|
|
}
|
|
});
|
|
});
|
|
|
|
// Smol version
|
|
group.bench_with_input(BenchmarkId::new("smol", n), n, |b, &n| {
|
|
b.iter(|| {
|
|
smol::block_on(async {
|
|
let (announcer, announcement) = Announcement::new();
|
|
|
|
let mut handles = Vec::with_capacity(n);
|
|
for _ in 0..n {
|
|
let listener = announcement.listener();
|
|
handles.push(smol::spawn(async move { listener.listen().await }));
|
|
}
|
|
|
|
announcer.announce(Arc::new(42)).unwrap();
|
|
|
|
for h in handles {
|
|
black_box(h.await);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
group.finish();
|
|
}
|
|
|
|
/// Benchmark: Concurrent announcements - tokio vs smol
|
|
fn bench_concurrent(c: &mut Criterion) {
|
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
|
let mut group = c.benchmark_group("runtimes/concurrent");
|
|
|
|
// Tokio version
|
|
group.bench_function("tokio", |b| {
|
|
b.to_async(&rt).iter(|| async {
|
|
let mut handles = Vec::with_capacity(100);
|
|
|
|
for i in 0..100 {
|
|
handles.push(tokio::spawn(async move {
|
|
let (announcer, announcement) = Announcement::new();
|
|
let listener = announcement.listener();
|
|
|
|
let recv_handle = tokio::spawn(async move { listener.listen().await });
|
|
announcer.announce(Arc::new(i)).unwrap();
|
|
|
|
recv_handle.await.unwrap()
|
|
}));
|
|
}
|
|
|
|
for h in handles {
|
|
black_box(h.await.unwrap());
|
|
}
|
|
});
|
|
});
|
|
|
|
// Smol version
|
|
group.bench_function("smol", |b| {
|
|
b.iter(|| {
|
|
smol::block_on(async {
|
|
let mut handles = Vec::with_capacity(100);
|
|
|
|
for i in 0..100 {
|
|
handles.push(smol::spawn(async move {
|
|
let (announcer, announcement) = Announcement::new();
|
|
let listener = announcement.listener();
|
|
|
|
let recv_handle = smol::spawn(async move { listener.listen().await });
|
|
announcer.announce(Arc::new(i)).unwrap();
|
|
|
|
recv_handle.await
|
|
}));
|
|
}
|
|
|
|
for h in handles {
|
|
black_box(h.await);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
criterion_group!(benches, bench_basic, bench_fanout, bench_concurrent,);
|
|
criterion_main!(benches);
|