Some checks failed
CI / test (push) Failing after 1m42s
Adds four Criterion.rs benchmark suites to measure hot-path performance
and demonstrate the impact of Sprints 1–3 optimizations:
- benches/protocol.rs — Command & StatusMessage serialize/deserialize
- benches/bandwidth.rs — BandwidthState atomics, budget, interval math
- benches/tcp_rx_scan.rs — memchr SIMD scan vs naive O(n) loop (55× faster
on 256KB buffers with status at end)
- benches/ecsrp5.rs — WCurve::new() heavy math vs cached LazyLock
(~123,000× faster access)
Also adds BENCHMARKS.md with usage instructions and example results.
Visibility changes (bench-only):
- scan_status_message is now pub (was #[cfg(test)] only)
- WCurve and WCURVE are now pub in ecsrp5.rs
dev-dependencies: criterion + pprof (optional flamegraph support)
80 lines
2.6 KiB
Rust
80 lines
2.6 KiB
Rust
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
|
use btest_rs::bandwidth::{BandwidthState, calc_send_interval, advance_next_send};
|
|
use std::sync::atomic::Ordering;
|
|
use std::time::{Duration, Instant};
|
|
|
|
fn bench_atomic_fetch_add(c: &mut Criterion) {
|
|
let state = BandwidthState::new();
|
|
c.bench_function("bandwidth_rx_bytes_fetch_add", |b| {
|
|
b.iter(|| {
|
|
black_box(state.rx_bytes.fetch_add(1500, Ordering::Relaxed));
|
|
})
|
|
});
|
|
c.bench_function("bandwidth_tx_bytes_fetch_add", |b| {
|
|
b.iter(|| {
|
|
black_box(state.tx_bytes.fetch_add(32768, Ordering::Relaxed));
|
|
})
|
|
});
|
|
}
|
|
|
|
fn bench_spend_budget(c: &mut Criterion) {
|
|
// Unlimited budget (fast path)
|
|
let unlimited = BandwidthState::new();
|
|
c.bench_function("spend_budget_unlimited", |b| {
|
|
b.iter(|| black_box(unlimited.spend_budget(black_box(1500))))
|
|
});
|
|
|
|
// Limited budget
|
|
let limited = BandwidthState::new();
|
|
limited.byte_budget.store(1_000_000_000, Ordering::SeqCst);
|
|
c.bench_function("spend_budget_limited", |b| {
|
|
b.iter(|| black_box(limited.spend_budget(black_box(1500))))
|
|
});
|
|
}
|
|
|
|
fn bench_calc_send_interval(c: &mut Criterion) {
|
|
c.bench_function("calc_interval_100mbps_1500b", |b| {
|
|
b.iter(|| black_box(calc_send_interval(black_box(100_000_000), black_box(1500))))
|
|
});
|
|
c.bench_function("calc_interval_1gbps_32768b", |b| {
|
|
b.iter(|| black_box(calc_send_interval(black_box(1_000_000_000), black_box(32768))))
|
|
});
|
|
c.bench_function("calc_interval_unlimited", |b| {
|
|
b.iter(|| black_box(calc_send_interval(black_box(0), black_box(1500))))
|
|
});
|
|
}
|
|
|
|
fn bench_advance_next_send(c: &mut Criterion) {
|
|
let iv = Duration::from_micros(120);
|
|
let now = Instant::now();
|
|
let mut next = now;
|
|
c.bench_function("advance_next_send", |b| {
|
|
b.iter(|| {
|
|
let r = advance_next_send(&mut next, iv, now);
|
|
black_box(r);
|
|
});
|
|
next = now;
|
|
});
|
|
}
|
|
|
|
fn bench_summary(c: &mut Criterion) {
|
|
let state = BandwidthState::new();
|
|
// Pre-populate some values so loads are real
|
|
state.total_tx_bytes.store(1_000_000_000, Ordering::Relaxed);
|
|
state.total_rx_bytes.store(2_000_000_000, Ordering::Relaxed);
|
|
state.intervals.store(100, Ordering::Relaxed);
|
|
c.bench_function("bandwidth_summary", |b| {
|
|
b.iter(|| black_box(state.summary()))
|
|
});
|
|
}
|
|
|
|
criterion_group!(
|
|
bandwidth_benches,
|
|
bench_atomic_fetch_add,
|
|
bench_spend_budget,
|
|
bench_calc_send_interval,
|
|
bench_advance_next_send,
|
|
bench_summary
|
|
);
|
|
criterion_main!(bandwidth_benches);
|