`TimeSlice`, `EventKind`, `KeyTable`, `CompetitorStore`, `Competitor` and the `storage` module were all public and none was obtainable from a `History` — `time_slices`, `agents` and `keys` are all private or `pub(crate)`. `TimeSlice` was the worst: `new`, `add_events`, `iteration`, `get_composition` and `get_results` were `pub` on a type you could only build standalone and never feed back into anything. Their sole consumer outside `src/` was `benches/batch.rs`, so a benchmark was dictating six public types. It is rewritten against the public API: a single-slice history's `converge` calls exactly the same per-slice sweep, so capping at one iteration measures the same code path. `N01` had zero references in the entire repository, including inside the crate; removed. `N00` and `N_INF` are EP identities (`Add` and `Mul`) and are now `pub(crate)` — a user reaching for `N_INF` as "an unknown competitor's prior" would get an improper distribution whose `mu()` silently reports 0.0. Adds the accessors their absence forced people around, from #70: `competitors()`, `competitor_count()` and `event_count()` (`size` had no accessor at all). Answering "who is best" previously meant materialising every competitor's full smoothed curve to read the last point of each. `KeyTable::keys` now iterates the dense reverse table rather than the forward `HashMap`, so `competitors()` yields insertion order rather than per-process hash order — the same hazard as #62, caught before it could reach a caller building a standings table. Two `CompetitorStore` methods (`is_empty`, `iter_mut`) had no callers anywhere and are gone; four more are now `#[cfg(test)]`, which is what they always were in practice. Worth recording a mistake: I first deleted `get_composition`/`get_results` on the strength of a "never used" warning, and the build broke — the warning came from the plain-lib target, where `#[cfg(test)]` callers in history.rs are not compiled. A dead-code warning from one target is not evidence about the others. BREAKING CHANGE: `TimeSlice`, `EventKind`, `KeyTable`, `CompetitorStore`, `Competitor`, the `storage` module, `N01`, `N00` and `N_INF` are no longer public. Refs #73, #70 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011hcFjNDmHXZF8URGLku5zZ
60 lines
2.0 KiB
Rust
60 lines
2.0 KiB
Rust
//! One slice's event sweep.
|
|
//!
|
|
//! Written against the public API rather than against `TimeSlice` directly.
|
|
//! It used to reach for `TimeSlice`, `KeyTable`, `CompetitorStore`,
|
|
//! `Competitor` and `EventKind`, and was the *only* thing outside `src/`
|
|
//! that did — so a benchmark was dictating five public types that no test,
|
|
//! example or consumer could otherwise obtain.
|
|
//!
|
|
//! A single-slice history's `converge` calls exactly the same per-slice sweep,
|
|
//! so capping at one iteration measures the same code path.
|
|
|
|
use criterion::{Criterion, criterion_group, criterion_main};
|
|
use smallvec::smallvec;
|
|
use trueskill_tt::{
|
|
ConstantDrift, ConvergenceOptions, Event, History, Member, Outcome, Team,
|
|
};
|
|
|
|
fn criterion_benchmark(criterion: &mut Criterion) {
|
|
let build = || {
|
|
let mut h = History::builder()
|
|
.convergence(ConvergenceOptions {
|
|
max_iter: 1,
|
|
epsilon: 0.0,
|
|
alpha: 1.0,
|
|
})
|
|
.drift(ConstantDrift::new(0.0))
|
|
.build();
|
|
|
|
// 100 events, all at one time, so the history has a single slice.
|
|
let events: Vec<Event<i64, &'static str>> = (0..100)
|
|
.map(|_| Event {
|
|
time: 1,
|
|
teams: smallvec![
|
|
Team::with_members([Member::new("a")]),
|
|
Team::with_members([Member::new("b")]),
|
|
],
|
|
outcome: Outcome::winner(0, 2),
|
|
})
|
|
.collect();
|
|
h.add_events(events).expect("fixture ingests");
|
|
h
|
|
};
|
|
|
|
criterion.bench_function("slice_sweep_100_events", |b| {
|
|
b.iter_batched(
|
|
build,
|
|
|mut h| {
|
|
// `converge_partial`, not `converge`: one iteration is
|
|
// deliberately short of convergence and `converge` reports that
|
|
// as an error.
|
|
let _ = h.converge_partial();
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
);
|
|
});
|
|
}
|
|
|
|
criterion_group!(benches, criterion_benchmark);
|
|
criterion_main!(benches);
|