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
|
use std::{
cmp,
hint::black_box,
time::{Duration, Instant},
};
use crate::BenchmarkResult;
/// Benchmark an operation for approx 5 seconds, returning the results.
///
/// `setup` is used to create the thing `op` acts on, and `undo` is called between each run to undo `op`.
/// If `undo` is invalid, this will return garbage results.
///
/// Warm-up for the setup is done beforehand.
pub fn benchmark_op<T>(
mut setup: impl FnMut() -> T,
mut op: impl FnMut(&mut T),
mut undo: impl FnMut(&mut T),
) -> BenchmarkResult {
// let loop_end = Instant::now() + Duration::from_secs(5);
let loop_end = Instant::now() + Duration::from_millis(100);
let mut times = 0;
let mut min = Duration::from_secs(u64::MAX);
let mut max = Duration::from_secs(0);
let mut sum = Duration::from_secs(0);
let mut target = setup();
while Instant::now() + max < loop_end {
#[allow(clippy::unit_arg)] // pretty sure this is necessary to prevent optimisations
let duration = time_singular(|| black_box(op(&mut target)));
undo(&mut target);
min = cmp::min(min, duration);
max = cmp::max(max, duration);
sum += duration;
times += 1;
}
BenchmarkResult {
times,
min,
max,
avg: sum / times as u32,
}
}
fn time_singular(f: impl FnOnce()) -> Duration {
let start = Instant::now();
f();
let end = Instant::now();
end - start
}
#[cfg(test)]
mod tests {
use super::benchmark_op;
use std::time::Duration;
#[test]
fn benchmark_op_resets_properly() {
benchmark_op(
|| false,
|b| {
assert!(!(*b));
*b = true;
},
|b| {
*b = false;
},
);
}
#[test]
fn benchmark_op_times_properly() {
let results = benchmark_op(
|| (),
|_| std::thread::sleep(Duration::from_millis(5)),
|_| {},
);
let avg_millis = results.avg.as_nanos() as f32 / (10.0_f32).powi(6);
dbg!(avg_millis);
assert!(
(avg_millis - 5.0).abs() < 0.1,
"sleeping for 5ms takes roughly 5ms"
)
}
}
|