//! Ingestion cost: one event per call versus one batched call. //! //! The rest of the suite only measures batched construction, which is why a //! quadratic in the incremental path went unnoticed — `record_winner` and //! `event(..).commit()` each ingest a single event, so a caller looping over a //! match feed takes that path. use std::hint::black_box; use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main}; use smallvec::smallvec; use trueskill_tt::{Event, History, Member, Outcome, Team}; fn events(n: usize, time: i64) -> Vec> { (0..n) .map(|i| Event { time, teams: smallvec![ Team::with_members([Member::new(format!("p{}", 2 * i))]), Team::with_members([Member::new(format!("p{}", 2 * i + 1))]), ], outcome: Outcome::winner(0, 2), }) .collect() } fn bench_ingest(c: &mut Criterion) { let mut group = c.benchmark_group("ingest"); for n in [250usize, 500, 1000] { group.bench_with_input(BenchmarkId::new("one-at-a-time", n), &n, |b, &n| { b.iter_batched( || events(n, 0), |evs| { let mut h: History = History::builder_with_key().build(); for ev in evs { h.add_events(std::iter::once(ev)).unwrap(); } black_box(h.time_slices_len()) }, criterion::BatchSize::SmallInput, ); }); group.bench_with_input(BenchmarkId::new("single-batch", n), &n, |b, &n| { b.iter_batched( || events(n, 0), |evs| { let mut h: History = History::builder_with_key().build(); h.add_events(evs).unwrap(); black_box(h.time_slices_len()) }, criterion::BatchSize::SmallInput, ); }); } group.finish(); } criterion_group!(benches, bench_ingest); criterion_main!(benches);