chore: initial release v0.1.0

Runtime-agnostic oneshot broadcast channel for Rust.
This commit is contained in:
swaits committed 2025-10-13 19:36:37 -06:00
commit e8e55b7676
64 files changed
+23966

No files matched your search

+231
View File
@@ -0,0 +1,231 @@
//! Stress test benchmarks for extreme scenarios
//!
//! Tests announcement under extreme conditions:
//! - Million-scale operations (1M+ listeners/announcements)
//! - Fully connected networks (N announcements × N listeners)
//! - Cascade patterns (chain reactions and trees)
use announcement::Announcement;
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
use std::hint::black_box;
use std::sync::Arc;
use std::time::Duration;
/// Benchmark: Million scale stress - 1M announcements × 10 listeners
fn bench_million_announcements(c: &mut Criterion) {
let mut group = c.benchmark_group("stress/million_scale");
group.sample_size(10);
group.measurement_time(Duration::from_secs(30));
group.bench_function("10K_announcements_x_10_listeners", |b| {
b.iter(|| {
let num_announcements = 10_000;
let listeners_per_announcement = 10;
let mut announcements = Vec::with_capacity(num_announcements);
let mut announcers = Vec::with_capacity(num_announcements);
// Create 10K announcement channels
for _ in 0..num_announcements {
let (tx, announcement) = Announcement::<Arc<i32>>::new();
announcers.push(tx);
announcements.push(announcement);
}
// Create 10 listeners for each announcement (100K total)
let mut all_listeners =
Vec::with_capacity(num_announcements * listeners_per_announcement);
for announcement in &announcements {
for _ in 0..listeners_per_announcement {
all_listeners.push(announcement.listener());
}
}
// Announce on all channels
for (i, announcer) in announcers.into_iter().enumerate() {
announcer.announce(Arc::new(i as i32)).unwrap();
}
// Verify delivery (sampling for performance)
for i in (0..all_listeners.len()).step_by(1000) {
black_box(all_listeners[i].try_listen());
}
});
});
group.finish();
}
/// Benchmark: Single announcement to 10K listeners
fn bench_one_to_million(c: &mut Criterion) {
let mut group = c.benchmark_group("stress/one_to_ten_thousand");
group.sample_size(10);
group.bench_function("1_announcement_x_10K_listeners", |b| {
b.iter(|| {
let (tx, announcement) = Announcement::new();
let num_listeners = 10_000;
let mut listeners = Vec::with_capacity(num_listeners);
for _ in 0..num_listeners {
listeners.push(announcement.listener());
}
tx.announce(Arc::new(42)).unwrap();
// Sample retrieval
for i in (0..listeners.len()).step_by(1000) {
black_box(listeners[i].try_listen());
}
});
});
group.finish();
}
/// Benchmark: Fully connected network - N announcements × N listeners
fn bench_fully_connected(c: &mut Criterion) {
let mut group = c.benchmark_group("stress/fully_connected");
group.sample_size(10);
group.measurement_time(Duration::from_secs(10));
// N announcements each received by N listeners = N² connections
for n in [10, 100, 500].iter() {
let total_connections = n * n;
group.throughput(Throughput::Elements(total_connections as u64));
group.bench_with_input(BenchmarkId::from_parameter(n), n, |b, &n| {
b.iter(|| {
// Create N announcement channels
let mut announcements = Vec::with_capacity(n);
let mut announcers = Vec::with_capacity(n);
for _ in 0..n {
let (tx, announcement) = Announcement::<Arc<i32>>::new();
announcers.push(tx);
announcements.push(announcement);
}
// Create N listeners for each announcement (N² total listeners)
let mut all_listeners = Vec::with_capacity(n * n);
for announcement in &announcements {
for _ in 0..n {
all_listeners.push(announcement.listener());
}
}
// Announce on all channels
for (i, announcer) in announcers.into_iter().enumerate() {
announcer.announce(Arc::new(i as i32)).unwrap();
}
// Retrieve all values
for listener in &all_listeners {
black_box(listener.try_listen());
}
});
});
}
group.finish();
}
/// Benchmark: Cascade chain - A triggers B triggers C...
fn bench_cascade_chain(c: &mut Criterion) {
let mut group = c.benchmark_group("stress/cascade_chain");
for chain_length in [10, 100, 500].iter() {
group.bench_with_input(
BenchmarkId::from_parameter(chain_length),
chain_length,
|b, &n| {
b.iter(|| {
let mut announcements = Vec::with_capacity(n);
let mut announcers = Vec::with_capacity(n);
// Create chain of announcements
for _ in 0..n {
let (tx, announcement) = Announcement::<Arc<i32>>::new();
announcers.push(tx);
announcements.push(announcement);
}
// Link chain: each announcement triggers next
let listeners: Vec<_> = announcements
.iter()
.take(n - 1)
.map(|a| a.listener())
.collect();
// Trigger cascade
for (i, announcer) in announcers.into_iter().enumerate() {
announcer.announce(Arc::new(i as i32)).unwrap();
}
// Verify propagation
for listener in &listeners {
black_box(listener.try_listen());
}
});
},
);
}
group.finish();
}
/// Benchmark: Cascade tree - A triggers B1, B2, B3... (tree fanout)
fn bench_cascade_tree(c: &mut Criterion) {
let mut group = c.benchmark_group("stress/cascade_tree");
for fanout in [2, 5, 10, 50].iter() {
group.throughput(Throughput::Elements(*fanout as u64));
group.bench_with_input(BenchmarkId::from_parameter(fanout), fanout, |b, &fanout| {
b.iter(|| {
// Root announcement
let (root_tx, root_announcement) = Announcement::<Arc<i32>>::new();
// Create fanout child announcements
let mut child_announcers = Vec::with_capacity(fanout);
let mut child_announcements = Vec::with_capacity(fanout);
for _ in 0..fanout {
let (tx, announcement) = Announcement::<Arc<i32>>::new();
child_announcers.push(tx);
child_announcements.push(announcement);
}
// Root listener triggers all children
let _root_listener = root_announcement.listener();
// Create listeners for all children
let mut child_listeners = Vec::with_capacity(fanout);
for announcement in &child_announcements {
child_listeners.push(announcement.listener());
}
// Trigger cascade
root_tx.announce(Arc::new(0)).unwrap();
for (i, announcer) in child_announcers.into_iter().enumerate() {
announcer.announce(Arc::new(i as i32)).unwrap();
}
// Verify all children received
for listener in &child_listeners {
black_box(listener.try_listen());
}
});
});
}
group.finish();
}
criterion_group!(
benches,
bench_million_announcements,
bench_one_to_million,
bench_fully_connected,
bench_cascade_chain,
bench_cascade_tree,
);
criterion_main!(benches);