chore: initial release v0.1.0
Runtime-agnostic oneshot broadcast channel for Rust.
This commit is contained in:
64 files changed
+23966
No files matched your search
@@ -0,0 +1,284 @@
|
||||
use announcement::Announcement;
|
||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
|
||||
use std::collections::HashMap;
|
||||
use std::hint::black_box;
|
||||
use std::sync::Arc;
|
||||
|
||||
// Small type: 4 bytes
|
||||
fn bench_small_type(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("small_type_i32");
|
||||
|
||||
for n in [1, 10, 100, 500].iter() {
|
||||
group.throughput(Throughput::Elements(*n as u64));
|
||||
|
||||
// Direct Clone
|
||||
group.bench_with_input(BenchmarkId::new("direct_clone", n), n, |b, &n| {
|
||||
b.iter(|| {
|
||||
let (tx, announcement) = Announcement::new();
|
||||
|
||||
let mut listeners = Vec::new();
|
||||
for _ in 0..n {
|
||||
listeners.push(announcement.listener());
|
||||
}
|
||||
|
||||
tx.announce(42i32).unwrap();
|
||||
|
||||
for listener in listeners {
|
||||
black_box(listener.try_listen());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Arc<i32> Clone
|
||||
group.bench_with_input(BenchmarkId::new("arc_clone", n), n, |b, &n| {
|
||||
b.iter(|| {
|
||||
let (tx, announcement) = Announcement::new();
|
||||
|
||||
let mut listeners = Vec::new();
|
||||
for _ in 0..n {
|
||||
listeners.push(announcement.listener());
|
||||
}
|
||||
|
||||
tx.announce(Arc::new(42i32)).unwrap();
|
||||
|
||||
for listener in listeners {
|
||||
black_box(listener.try_listen());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
group.finish();
|
||||
}
|
||||
|
||||
// Medium type: 1KB
|
||||
fn bench_medium_type(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("medium_type_1kb");
|
||||
|
||||
for n in [1, 10, 100, 500].iter() {
|
||||
group.throughput(Throughput::Elements(*n as u64));
|
||||
|
||||
// Direct Clone
|
||||
group.bench_with_input(BenchmarkId::new("direct_clone", n), n, |b, &n| {
|
||||
b.iter(|| {
|
||||
let (tx, announcement) = Announcement::new();
|
||||
|
||||
let mut listeners = Vec::new();
|
||||
for _ in 0..n {
|
||||
listeners.push(announcement.listener());
|
||||
}
|
||||
|
||||
tx.announce([0u8; 1024]).unwrap();
|
||||
|
||||
for listener in listeners {
|
||||
black_box(listener.try_listen());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Arc Clone
|
||||
group.bench_with_input(BenchmarkId::new("arc_clone", n), n, |b, &n| {
|
||||
b.iter(|| {
|
||||
let (tx, announcement) = Announcement::new();
|
||||
|
||||
let mut listeners = Vec::new();
|
||||
for _ in 0..n {
|
||||
listeners.push(announcement.listener());
|
||||
}
|
||||
|
||||
tx.announce(Arc::new([0u8; 1024])).unwrap();
|
||||
|
||||
for listener in listeners {
|
||||
black_box(listener.try_listen());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
group.finish();
|
||||
}
|
||||
|
||||
// Large type: 1MB
|
||||
fn bench_large_type(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("large_type_1mb");
|
||||
group.sample_size(10); // Reduce sample size for large data
|
||||
|
||||
for n in [1, 10, 100, 500].iter() {
|
||||
group.throughput(Throughput::Elements(*n as u64));
|
||||
|
||||
// Direct Clone
|
||||
group.bench_with_input(BenchmarkId::new("direct_clone", n), n, |b, &n| {
|
||||
b.iter(|| {
|
||||
let (tx, announcement) = Announcement::new();
|
||||
|
||||
let mut listeners = Vec::new();
|
||||
for _ in 0..n {
|
||||
listeners.push(announcement.listener());
|
||||
}
|
||||
|
||||
tx.announce(vec![0u8; 1024 * 1024]).unwrap();
|
||||
|
||||
for listener in listeners {
|
||||
black_box(listener.try_listen());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Arc Clone
|
||||
group.bench_with_input(BenchmarkId::new("arc_clone", n), n, |b, &n| {
|
||||
b.iter(|| {
|
||||
let (tx, announcement) = Announcement::new();
|
||||
|
||||
let mut listeners = Vec::new();
|
||||
for _ in 0..n {
|
||||
listeners.push(announcement.listener());
|
||||
}
|
||||
|
||||
tx.announce(Arc::new(vec![0u8; 1024 * 1024])).unwrap();
|
||||
|
||||
for listener in listeners {
|
||||
black_box(listener.try_listen());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
group.finish();
|
||||
}
|
||||
|
||||
// Complex type: Config with String, Vec, HashMap
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(dead_code)]
|
||||
struct Config {
|
||||
name: String,
|
||||
tags: Vec<String>,
|
||||
settings: HashMap<String, String>,
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
fn new() -> Self {
|
||||
let mut settings = HashMap::new();
|
||||
settings.insert("key1".to_string(), "value1".to_string());
|
||||
settings.insert("key2".to_string(), "value2".to_string());
|
||||
settings.insert("key3".to_string(), "value3".to_string());
|
||||
|
||||
Config {
|
||||
name: "MyConfig".to_string(),
|
||||
tags: vec!["tag1".to_string(), "tag2".to_string(), "tag3".to_string()],
|
||||
settings,
|
||||
data: vec![0u8; 1024],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn bench_complex_type(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("complex_type_config");
|
||||
|
||||
for n in [1, 10, 100, 500].iter() {
|
||||
group.throughput(Throughput::Elements(*n as u64));
|
||||
|
||||
// Direct Clone
|
||||
group.bench_with_input(BenchmarkId::new("direct_clone", n), n, |b, &n| {
|
||||
b.iter(|| {
|
||||
let (tx, announcement) = Announcement::new();
|
||||
|
||||
let mut listeners = Vec::new();
|
||||
for _ in 0..n {
|
||||
listeners.push(announcement.listener());
|
||||
}
|
||||
|
||||
tx.announce(Config::new()).unwrap();
|
||||
|
||||
for listener in listeners {
|
||||
black_box(listener.try_listen());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Arc Clone
|
||||
group.bench_with_input(BenchmarkId::new("arc_clone", n), n, |b, &n| {
|
||||
b.iter(|| {
|
||||
let (tx, announcement) = Announcement::new();
|
||||
|
||||
let mut listeners = Vec::new();
|
||||
for _ in 0..n {
|
||||
listeners.push(announcement.listener());
|
||||
}
|
||||
|
||||
tx.announce(Arc::new(Config::new())).unwrap();
|
||||
|
||||
for listener in listeners {
|
||||
black_box(listener.try_listen());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
group.finish();
|
||||
}
|
||||
|
||||
// Comparison benchmark showing the crossover point
|
||||
fn bench_crossover_analysis(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("crossover_analysis");
|
||||
|
||||
// Test various type sizes to find where Arc becomes beneficial
|
||||
let sizes = [4, 8, 16, 32, 64, 128, 256, 512];
|
||||
|
||||
for size in sizes.iter() {
|
||||
group.throughput(Throughput::Bytes(*size as u64));
|
||||
|
||||
// Direct clone with 10 listeners
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("direct_10_listeners", size),
|
||||
size,
|
||||
|b, &size| {
|
||||
b.iter(|| {
|
||||
let (tx, announcement) = Announcement::new();
|
||||
|
||||
let mut listeners = Vec::new();
|
||||
for _ in 0..10 {
|
||||
listeners.push(announcement.listener());
|
||||
}
|
||||
|
||||
let data = vec![0u8; size];
|
||||
tx.announce(data).unwrap();
|
||||
|
||||
for listener in listeners {
|
||||
black_box(listener.try_listen());
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
// Arc clone with 10 listeners
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("arc_10_listeners", size),
|
||||
size,
|
||||
|b, &size| {
|
||||
b.iter(|| {
|
||||
let (tx, announcement) = Announcement::new();
|
||||
|
||||
let mut listeners = Vec::new();
|
||||
for _ in 0..10 {
|
||||
listeners.push(announcement.listener());
|
||||
}
|
||||
|
||||
let data = Arc::new(vec![0u8; size]);
|
||||
tx.announce(data).unwrap();
|
||||
|
||||
for listener in listeners {
|
||||
black_box(listener.try_listen());
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
group.finish();
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_small_type,
|
||||
bench_medium_type,
|
||||
bench_large_type,
|
||||
bench_complex_type,
|
||||
bench_crossover_analysis,
|
||||
);
|
||||
criterion_main!(benches);
|
||||
Reference in new issue
Block a user