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
//! Fresh owned outputs, prepared inputs, and optional batched reporting.
use std::hint::black_box;
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use histogram::{Histogram, Histogram32};
macro_rules! benchmark_width {
($function:ident, $label:literal, $dense:ident, $count:ty) => {
fn $function(c: &mut Criterion) {
let mut group = c.benchmark_group($label);
for (gp, max) in [(0, 1), (0, 7), (7, 30), (10, 30)] {
for windows in [2, 8, 64] {
for shape in ["clustered", "full"] {
let mut inputs = vec![$dense::new(gp, max).unwrap(); windows];
let len = inputs[0].as_slice().len();
for (window, input) in inputs.iter_mut().enumerate() {
for (i, count) in input.as_mut_slice().iter_mut().enumerate() {
if shape == "full" || (len / 2..len / 2 + 16).contains(&i) {
*count = ((i + window * 7) % 31 + 1) as $count;
}
}
}
let refs: Vec<_> = inputs.iter().collect();
let expected: Vec<u128> = (0..len)
.map(|i| inputs.iter().map(|h| u128::from(h.as_slice()[i])).sum())
.collect();
let run = |method, refs: &[&$dense]| match method {
"checked_sum" => $dense::checked_sum(refs).unwrap(),
"clone_first" => {
let mut result = refs[0].clone();
for input in &refs[1..] {
result.checked_add_assign(input).unwrap();
}
result
}
"scalar_owned" => {
let first = refs[0];
assert!(refs.iter().all(|h| h.config() == first.config()));
let mut result = first.clone();
for input in &refs[1..] {
for (dst, &src) in
result.as_mut_slice().iter_mut().zip(input.as_slice())
{
*dst = dst.checked_add(src).unwrap();
}
}
result
}
_ => unreachable!(),
};
for method in ["checked_sum", "clone_first", "scalar_owned"] {
assert_eq!(
run(method, &refs)
.as_slice()
.iter()
.copied()
.map(u128::from)
.collect::<Vec<_>>(),
expected
);
for reports in [false, true] {
let id = BenchmarkId::new(
method,
format!("gp{gp}-max{max}-{windows}w-{shape}-report{reports}"),
);
group.bench_function(id, |b| {
b.iter(|| {
let result = run(method, black_box(&refs));
if reports {
black_box(
result
.quantiles(black_box(&[
0.0, 0.5, 0.9, 0.99, 1.0,
]))
.unwrap(),
);
}
// The owned output is dropped in the timed iteration.
black_box(result);
});
});
}
}
}
}
}
group.finish();
}
};
}
benchmark_width!(wide, "dense_sum64", Histogram, u64);
benchmark_width!(narrow, "dense_sum32", Histogram32, u32);
criterion_group!(benches, wide, narrow);
criterion_main!(benches);