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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
//! # Binggan (餅乾, bǐng gān) - A Benchmarking Library for Stable Rust
//!
//! Binggan is a benchmarking library designed for flexibility, providing fast and stable results.
//! It reports peak memory consumption and can integrate with `perf` for hardware performance counters.
//!
//! ## Main Components
//! Binggan has two primary entry points for running benchmarks:
//!
//! - **[BenchRunner]**: A main runner for. Useful for single benchmarks or to create groups.
//! - **[InputGroup]**: Use this when running a group of benchmarks with the same inputs, where ownership of inputs can be transferred.
//!
//! Otherwise if you need more flexibility you can use [BenchGroup] via [BenchRunner::new_group](crate::BenchRunner::new).
//!
//! See <https://github.com/PSeitz/binggan/tree/main/benches> for examples. `benches/bench_group.rs` and
//! `benches/bench_input_group.rs` are different ways to produce the same output.
//!
//! ## OutputValue
//! The typical benchmarking flow involves providing some input, processing it through a function, and obtaining an output.
//! Benchmarks return [OutputValue], which represents the result of the benchmark. This output can be particularly
//! useful in scenarios like compression benchmarks, where it reports the output size or other relevant metrics.
//!
//! ## Plugins
//! See the [plugins] module for more information on how to register custom plugins.
//!
//! ## Reporting
//! See the [report] module for more information on how to customize the benchmark result reporting.
//!
//! # Perf Integration
//! Binggan can integrate with perf to report hardware performance counters.
//! See [PerfCounterPlugin](crate::plugins::PerfCounterPlugin) for more information.
//!
//! # Example for InputGroup
//! ```rust
//! use binggan::{black_box, InputGroup, PeakMemAlloc, INSTRUMENTED_SYSTEM, plugins::*};
//!
//! #[global_allocator]
//! pub static GLOBAL: &PeakMemAlloc<std::alloc::System> = &INSTRUMENTED_SYSTEM;
//!
//! fn main() {
//! // Tuples of name and data for the inputs
//! let data = vec![
//! (
//! "max id 100; 100 el all the same",
//! std::iter::repeat(100).take(100).collect(),
//! ),
//! (
//! "max id 100; 100 el all different",
//! (0..100).collect()
//! ),
//! ];
//! bench_group(InputGroup::new_with_inputs(data));
//! }
//!
//! // Run the benchmark for the group with input `Vec<usize>`
//! fn bench_group(mut runner: InputGroup<Vec<usize>, u64>) {
//! runner
//! // Set the peak mem allocator. This will enable peak memory reporting.
//! .add_plugin(PeakMemAllocPlugin::new(GLOBAL))
//! .add_plugin(PerfCounterPlugin::default());
//! runner.register("vec", move |data| {
//! let vec = test_vec(data);
//! vec.len() as u64
//! });
//! runner.register("hashmap", move |data| {
//! let map = test_hashmap(data);
//! map.len() as u64
//! });
//! runner.run();
//! }
//!
//! fn test_vec(data: &Vec<usize>) -> Vec<usize> {
//! let mut vec = Vec::new();
//! for idx in data {
//! if vec.len() <= *idx {
//! vec.resize(idx + 1, 0);
//! }
//! vec[*idx] += 1;
//! }
//! black_box(vec)
//! }
//! fn test_hashmap(data: &Vec<usize>) -> std::collections::HashMap<usize, i32> {
//! let mut map = std::collections::HashMap::new();
//! for idx in data {
//! *map.entry(*idx).or_insert(0) += 1;
//! }
//! black_box(map)
//! }
//!
//! ```
//!
//! # Example for BenchGroup
//!
//! ```
//! use std::collections::HashMap;
//!
//! use binggan::{black_box, plugins::*, BenchRunner, PeakMemAlloc, INSTRUMENTED_SYSTEM};
//!
//! #[global_allocator]
//! pub static GLOBAL: &PeakMemAlloc<std::alloc::System> = &INSTRUMENTED_SYSTEM;
//!
//! fn test_vec(data: &Vec<usize>) -> Vec<i32> {
//! let mut vec = Vec::new();
//! for idx in data {
//! if vec.len() <= *idx {
//! vec.resize(idx + 1, 0);
//! }
//! vec[*idx] += 1;
//! }
//! vec
//! }
//! fn test_hashmap(data: &Vec<usize>) -> HashMap<&usize, i32> {
//! let mut map = std::collections::HashMap::new();
//! for idx in data {
//! *map.entry(idx).or_insert(0) += 1;
//! }
//! map
//! }
//!
//! fn run_bench() {
//! let inputs: Vec<(&str, Vec<usize>)> = vec![
//! (
//! "max id 100; 100 el all the same",
//! std::iter::repeat(100).take(100).collect(),
//! ),
//! ("max id 100; 100 el all different", (0..100).collect()),
//! ];
//! let mut runner: BenchRunner = BenchRunner::new();
//!
//! runner
//! // Set the peak mem allocator. This will enable peak memory reporting.
//! .add_plugin(PeakMemAllocPlugin::new(GLOBAL))
//! .add_plugin(CacheTrasher::default());
//!
//! let mut group = runner.new_group();
//! for (input_name, data) in inputs.iter() {
//! group.set_input_size(data.len() * std::mem::size_of::<usize>());
//! group.register_with_input("vec", data, move |data| {
//! black_box(test_vec(data));
//! });
//! group.register_with_input("hashmap", data, move |data| {
//! black_box(test_hashmap(data));
//! });
//! }
//! group.run();
//! }
//!
//! fn main() {
//! run_bench();
//! }
//! ```
extern crate test;
/// The module to define custom plugins
/// The module to report benchmark results
pub
pub
pub
pub
pub
pub
pub
pub use BenchResult;
pub use BenchGroup;
pub use BenchId;
pub use InputGroup;
pub use BenchRunner;
pub use Config;
pub use OutputValue;
pub use *;
pub use parse_args;
/// A function that is opaque to the optimizer, used to prevent the compiler from
/// optimizing away computations in a benchmark.
pub use black_box;