use criterion::{Criterion, criterion_group, criterion_main};
use std::hint::black_box;
use adaptite::{Memo, Reactor, memo_in, signal_in};
fn signal_write_read(c: &mut Criterion) {
let reactor = Reactor::new();
let signal = signal_in(&reactor, 0u64);
c.bench_function("signal_write_read", |b| {
let mut value = 0u64;
b.iter(|| {
value += 1;
signal.set(black_box(value));
black_box(signal.get())
});
});
}
fn signal_write_suppressed(c: &mut Criterion) {
let reactor = Reactor::new();
let signal = signal_in(&reactor, 7u64);
c.bench_function("signal_write_suppressed", |b| {
b.iter(|| signal.set(black_box(7u64)));
});
}
fn deep_chain(c: &mut Criterion) {
const DEPTH: usize = 100;
let reactor = Reactor::new();
let source = signal_in(&reactor, 0u64);
let mut tail: Memo<u64> = memo_in(&reactor, {
let source = source.clone();
move || source.get() + 1
});
for _ in 1..DEPTH {
let previous = tail.clone();
tail = memo_in(&reactor, move || previous.get() + 1);
}
c.bench_function("deep_chain_100_invalidate_and_pull", |b| {
let mut value = 0u64;
b.iter(|| {
value += 1;
source.set(black_box(value));
black_box(tail.get())
});
});
}
fn wide_fanout(c: &mut Criterion) {
const WIDTH: u64 = 100;
let reactor = Reactor::new();
let source = signal_in(&reactor, 0u64);
let layer: Vec<Memo<u64>> = (0..WIDTH)
.map(|offset| {
memo_in(&reactor, {
let source = source.clone();
move || source.get() + offset
})
})
.collect();
let collector = memo_in(&reactor, move || layer.iter().map(Memo::get).sum::<u64>());
c.bench_function("wide_fanout_100_invalidate_and_pull", |b| {
let mut value = 0u64;
b.iter(|| {
value += 1;
source.set(black_box(value));
black_box(collector.get())
});
});
}
fn layered_diamonds(c: &mut Criterion) {
const LAYERS: usize = 10;
let reactor = Reactor::new();
let source = signal_in(&reactor, 0u64);
let mut join: Memo<u64> = memo_in(&reactor, {
let source = source.clone();
move || source.get()
});
for _ in 0..LAYERS {
let left = memo_in(&reactor, {
let join = join.clone();
move || join.get() + 1
});
let right = memo_in(&reactor, {
let join = join.clone();
move || join.get() * 2
});
join = memo_in(&reactor, move || left.get() + right.get());
}
c.bench_function("layered_diamonds_10_invalidate_and_pull", |b| {
let mut value = 0u64;
b.iter(|| {
value += 1;
source.set(black_box(value));
black_box(join.get())
});
});
}
fn node_churn(c: &mut Criterion) {
let reactor = Reactor::new();
c.bench_function("node_create_and_dispose", |b| {
b.iter(|| {
let signal = signal_in(&reactor, black_box(0u64));
black_box(signal.get());
});
});
}
fn edge_churn(c: &mut Criterion) {
const WIDTH: u64 = 32;
let reactor = Reactor::new();
let inputs: Vec<_> = (0..WIDTH).map(|i| signal_in(&reactor, i)).collect();
let sum = memo_in(&reactor, {
let inputs = inputs.clone();
move || inputs.iter().map(adaptite::Signal::get).sum::<u64>()
});
c.bench_function("edge_churn_32_rerecord", |b| {
let mut value = 0u64;
b.iter(|| {
value += 1;
inputs[0].set(black_box(value));
black_box(sum.get())
});
});
}
fn graph_stats_snapshot(c: &mut Criterion) {
const WIDTH: u64 = 1_000;
let reactor = Reactor::new();
let source = signal_in(&reactor, 0u64);
let layer: Vec<Memo<u64>> = (0..WIDTH)
.map(|offset| {
let source = source.clone();
memo_in(&reactor, move || source.get() + offset)
})
.collect();
for memo in &layer {
black_box(memo.get());
}
c.bench_function("graph_stats_1000_nodes", |b| {
b.iter(|| black_box(reactor.graph_stats()));
});
}
criterion_group!(
benches,
signal_write_read,
signal_write_suppressed,
deep_chain,
wide_fanout,
layered_diamonds,
node_churn,
edge_churn,
graph_stats_snapshot
);
criterion_main!(benches);