Skip to content

Commit 33bca87

Browse files
authored
Merge pull request #1476 from nnethercote/runtime-tweaks
Runtime benchmarking tweaks
2 parents 7f1a5f9 + 7e197a5 commit 33bca87

File tree

4 files changed

+31
-50
lines changed

4 files changed

+31
-50
lines changed

collector/benchlib/src/benchmark.rs

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,25 @@ use crate::measure::benchmark_function;
55
use crate::process::raise_process_priority;
66
use std::collections::HashMap;
77

8-
/// Create a new benchmark group. Use the closure argument to define individual benchmarks.
9-
pub fn run_benchmark_group<F: FnOnce(&mut BenchmarkGroup)>(define_func: F) {
8+
/// Create and run a new benchmark group. Use the closure argument to register
9+
/// the individual benchmarks.
10+
pub fn run_benchmark_group<F>(register: F)
11+
where
12+
F: FnOnce(&mut BenchmarkGroup),
13+
{
1014
env_logger::init();
1115

1216
let mut group = BenchmarkGroup::new();
13-
define_func(&mut group);
17+
register(&mut group);
1418
group.run().expect("Benchmark group execution has failed");
1519
}
1620

1721
/// Type-erased function that executes a single benchmark.
18-
struct BenchmarkWrapper {
19-
func: Box<dyn Fn() -> anyhow::Result<BenchmarkStats>>,
20-
}
22+
type BenchmarkFn = Box<dyn Fn() -> anyhow::Result<BenchmarkStats>>;
2123

2224
#[derive(Default)]
2325
pub struct BenchmarkGroup {
24-
benchmarks: HashMap<&'static str, BenchmarkWrapper>,
26+
benchmarks: HashMap<&'static str, BenchmarkFn>,
2527
}
2628

2729
impl BenchmarkGroup {
@@ -30,19 +32,21 @@ impl BenchmarkGroup {
3032
}
3133

3234
/// Registers a single benchmark.
33-
/// `constructor` should return a closure that will be benchmarked.
34-
pub fn register<F: Fn() -> Bench + Clone + 'static, R, Bench: FnOnce() -> R + 'static>(
35-
&mut self,
36-
name: &'static str,
37-
constructor: F,
38-
) {
35+
///
36+
/// `constructor` returns a closure that will be benchmarked. This means
37+
/// `constructor` can do initialization steps outside of the code that is
38+
/// measured. `constructor` may be called multiple times (e.g. once for a
39+
/// run with performance counters and once for a run without), but the
40+
/// closure it produces each time will only be called once.
41+
pub fn register_benchmark<Ctor, Bench, R>(&mut self, name: &'static str, constructor: Ctor)
42+
where
43+
Ctor: Fn() -> Bench + Clone + 'static,
44+
Bench: FnOnce() -> R + 'static,
45+
{
3946
// We want to type-erase the target `func` by wrapping it in a Box.
40-
let benchmark_func = Box::new(move || benchmark_function(constructor.clone()));
41-
let benchmark_def = BenchmarkWrapper {
42-
func: benchmark_func,
43-
};
44-
if self.benchmarks.insert(name, benchmark_def).is_some() {
45-
panic!("Benchmark {} was registered twice", name);
47+
let benchmark_fn = Box::new(move || benchmark_function(constructor.clone()));
48+
if self.benchmarks.insert(name, benchmark_fn).is_some() {
49+
panic!("Benchmark '{}' was registered twice", name);
4650
}
4751
}
4852

@@ -63,7 +67,7 @@ impl BenchmarkGroup {
6367
}
6468

6569
fn run_benchmarks(self, args: BenchmarkArgs) -> anyhow::Result<()> {
66-
let mut items: Vec<(&'static str, BenchmarkWrapper)> = self
70+
let mut items: Vec<(&'static str, BenchmarkFn)> = self
6771
.benchmarks
6872
.into_iter()
6973
.filter(|(name, _)| {
@@ -74,10 +78,10 @@ impl BenchmarkGroup {
7478

7579
let mut stdout = std::io::stdout().lock();
7680

77-
for (name, def) in items {
81+
for (name, benchmark_fn) in items {
7882
let mut stats: Vec<BenchmarkStats> = Vec::with_capacity(args.iterations as usize);
7983
for i in 0..args.iterations {
80-
let benchmark_stats = (def.func)()?;
84+
let benchmark_stats = benchmark_fn()?;
8185
log::info!("Benchmark (run {i}) `{name}` completed: {benchmark_stats:?}");
8286
stats.push(benchmark_stats);
8387
}
@@ -101,24 +105,6 @@ impl BenchmarkGroup {
101105
}
102106
}
103107

104-
/// Adds a single benchmark to the benchmark group.
105-
/// ```ignore
106-
/// use benchlib::define_benchmark;
107-
///
108-
/// define_benchmark!(group, my_bench, {
109-
/// || do_something()
110-
/// });
111-
/// ```
112-
#[macro_export]
113-
macro_rules! define_benchmark {
114-
($group:expr, $name:ident, $fun:expr) => {
115-
let func = move || $fun;
116-
$group.register(stringify!($name), func);
117-
};
118-
}
119-
120-
pub use define_benchmark;
121-
122108
/// Tests if the name of the benchmark passes through the include and exclude filters.
123109
/// Both filters can contain multiple comma-separated prefixes.
124110
pub fn passes_filter(name: &str, exclude: Option<&str>, include: Option<&str>) -> bool {

collector/runtime-benchmarks/bufreader/src/main.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
use std::io::{BufRead, BufReader, Write};
2-
3-
use snap::{read::FrameDecoder, write::FrameEncoder};
4-
51
use benchlib::benchmark::{black_box, run_benchmark_group};
6-
use benchlib::define_benchmark;
2+
use snap::{read::FrameDecoder, write::FrameEncoder};
3+
use std::io::{BufRead, BufReader, Write};
74

85
const BYTES: usize = 64 * 1024 * 1024;
96

@@ -12,7 +9,7 @@ fn main() {
129
// The pattern we want is a BufReader which wraps a Read impl where one Read::read call will
1310
// never fill the whole BufReader buffer.
1411
run_benchmark_group(|group| {
15-
define_benchmark!(group, bufreader_snappy, {
12+
group.register_benchmark("bufreader_snappy", || {
1613
let data = vec![0u8; BYTES];
1714
move || {
1815
let mut compressed = Vec::new();

collector/runtime-benchmarks/hashmap/src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use benchlib;
22
use benchlib::benchmark::run_benchmark_group;
3-
use benchlib::define_benchmark;
43

54
fn main() {
65
run_benchmark_group(|group| {
76
// Measures how long does it take to insert 10 thousand numbers into a `hashbrown` hashmap.
8-
define_benchmark!(group, hashmap_insert_10k, {
7+
group.register_benchmark("hashmap_insert_10k", || {
98
let mut map = hashbrown::HashMap::with_capacity_and_hasher(
109
10000,
1110
fxhash::FxBuildHasher::default(),

collector/runtime-benchmarks/nbody/src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22
//! Code taken from https://github.com/prestontw/rust-nbody
33
44
use benchlib::benchmark::run_benchmark_group;
5-
use benchlib::define_benchmark;
65

76
mod nbody;
87

98
fn main() {
109
run_benchmark_group(|group| {
11-
define_benchmark!(group, nbody_10k, {
10+
group.register_benchmark("nbody_10k", || {
1211
let mut nbody_10k = nbody::init(10000);
1312
|| {
1413
for _ in 0..10 {

0 commit comments

Comments
 (0)