1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//! Boilerplate-killer for perf examples. Most recipe benches follow
//! one of two shapes:
//!
//! 1. **Keyed**: generate N keys with [`SubMsLcg`], time each `op(&key)`.
//! Common for hash maps, bloom filters, caches, dedup gates.
//! 2. **Indexed**: call `op(i)` for `i in 0..N`, time each. Common for
//! sequential workloads (arena allocations, ring-buffer enqueues,
//! fixed-size record reads).
//!
//! Both shapes used to repeat ~6 lines per stage in every
//! `examples/perf_main.rs`. These helpers collapse that to one call.
//!
//! ```no_run
//! use subms::{SubMsLcg, SubMsPerfHarness, bench_keyed_op, bench_indexed_op};
//!
//! let mut h = SubMsPerfHarness::new("my-recipe", "rust");
//! let mut data_structure = std::collections::HashMap::new();
//!
//! // 50k keyed adds:
//! bench_keyed_op(&mut h, "add", 50_000, 0, |key| {
//! data_structure.insert(key.to_string(), 1u32);
//! });
//!
//! // 50k indexed ops:
//! bench_indexed_op(&mut h, "scan", 50_000, |i| {
//! let _ = data_structure.get(&format!("k{i}"));
//! });
//! ```
use crate::;
/// Run `count` timed invocations of `op` against keys generated by a
/// deterministic LCG seeded with `seed`. Each key is formatted as
/// `"k{u32}"`. The `op` closure receives the key string by reference.
///
/// Registers a stage named `stage_name` on the harness and records
/// one sample per invocation. Use the same seed across reads/writes
/// (e.g. `add` then `lookup`) so the key universes match.
/// Run `count` timed invocations of `op(i)` for `i in 0..count`. Use
/// for indexed sequential workloads (sequential ID generation, fixed
/// record reads, arena allocations).
/// Run `count` timed invocations of `op` against keys formatted from a
/// caller-provided template. Useful when you specifically want
/// negative-lookup keys ("miss-{i}", "absent-{i}") that don't overlap
/// the positive-lookup universe.