use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use futures::stream::{self, StreamExt};
use tears::subscription::BenchSubscriptionManager;
use tears::{BoxStream, Subscription, SubscriptionSource};
use tokio::runtime::Builder;
use tokio::sync::mpsc;
struct BenchSource {
id: u64,
}
impl SubscriptionSource for BenchSource {
type Output = ();
type Key = u64;
fn stream(&self) -> BoxStream<'static, ()> {
stream::pending().boxed()
}
fn key(&self) -> Self::Key {
self.id
}
}
fn subscriptions(ids: impl IntoIterator<Item = u64>) -> Vec<Subscription<()>> {
ids.into_iter()
.map(|id| Subscription::new(BenchSource { id }))
.collect()
}
fn bench_reconcile_steady(c: &mut Criterion) {
let rt = Builder::new_multi_thread()
.worker_threads(1)
.build()
.expect("bench runtime should build");
let _guard = rt.enter();
let mut group = c.benchmark_group("subscription_reconcile_steady");
for count in [1u64, 8, 64, 256] {
group.bench_with_input(BenchmarkId::from_parameter(count), &count, |b, &count| {
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = BenchSubscriptionManager::new(tx);
manager.update(subscriptions(0..count));
b.iter(|| {
manager.update(subscriptions(0..count));
});
manager.shutdown();
});
}
group.finish();
}
fn bench_reconcile_churn(c: &mut Criterion) {
let rt = Builder::new_multi_thread()
.worker_threads(1)
.build()
.expect("bench runtime should build");
let _guard = rt.enter();
let mut group = c.benchmark_group("subscription_reconcile_churn");
for count in [1u64, 8, 64, 256] {
group.bench_with_input(BenchmarkId::from_parameter(count), &count, |b, &count| {
let (tx, _rx) = mpsc::unbounded_channel();
let mut manager = BenchSubscriptionManager::new(tx);
let mut toggle = false;
b.iter(|| {
let ids = if toggle { count..count * 2 } else { 0..count };
toggle = !toggle;
manager.update(subscriptions(ids));
});
manager.shutdown();
});
}
group.finish();
}
criterion_group!(benches, bench_reconcile_steady, bench_reconcile_churn);
criterion_main!(benches);