aboutsummaryrefslogtreecommitdiff
path: root/benches/benchmarks/custom_measurement.rs
diff options
context:
space:
mode:
Diffstat (limited to 'benches/benchmarks/custom_measurement.rs')
-rwxr-xr-xbenches/benchmarks/custom_measurement.rs118
1 files changed, 118 insertions, 0 deletions
diff --git a/benches/benchmarks/custom_measurement.rs b/benches/benchmarks/custom_measurement.rs
new file mode 100755
index 0000000..c685f38
--- /dev/null
+++ b/benches/benchmarks/custom_measurement.rs
@@ -0,0 +1,118 @@
+use criterion::{
+ black_box, criterion_group,
+ measurement::{Measurement, ValueFormatter},
+ Criterion, Throughput,
+};
+use std::time::{Duration, Instant};
+
+struct HalfSecFormatter;
+impl ValueFormatter for HalfSecFormatter {
+ fn format_value(&self, value: f64) -> String {
+ // The value will be in nanoseconds so we have to convert to half-seconds.
+ format!("{} s/2", value * 2f64 * 10f64.powi(-9))
+ }
+
+ fn format_throughput(&self, throughput: &Throughput, value: f64) -> String {
+ match *throughput {
+ Throughput::Bytes(bytes) => {
+ format!("{} b/s/2", (bytes as f64) / (value * 2f64 * 10f64.powi(-9)))
+ }
+ Throughput::Elements(elems) => format!(
+ "{} elem/s/2",
+ (elems as f64) / (value * 2f64 * 10f64.powi(-9))
+ ),
+ }
+ }
+
+ fn scale_values(&self, _typical: f64, values: &mut [f64]) -> &'static str {
+ for val in values {
+ *val *= 2f64 * 10f64.powi(-9);
+ }
+
+ "s/2"
+ }
+
+ fn scale_throughputs(
+ &self,
+ _typical: f64,
+ throughput: &Throughput,
+ values: &mut [f64],
+ ) -> &'static str {
+ match *throughput {
+ Throughput::Bytes(bytes) => {
+ for val in values {
+ *val = (bytes as f64) / (*val * 2f64 * 10f64.powi(-9))
+ }
+
+ "b/s/2"
+ }
+ Throughput::Elements(elems) => {
+ for val in values {
+ *val = (elems as f64) / (*val * 2f64 * 10f64.powi(-9))
+ }
+
+ "elem/s/2"
+ }
+ }
+ }
+
+ fn scale_for_machines(&self, values: &mut [f64]) -> &'static str {
+ for val in values {
+ *val *= 2f64 * 10f64.powi(-9);
+ }
+
+ "s/2"
+ }
+}
+
+const NANOS_PER_SEC: u64 = 1_000_000_000;
+
+/// Silly "measurement" that is really just wall-clock time reported in half-seconds.
+struct HalfSeconds;
+impl Measurement for HalfSeconds {
+ type Intermediate = Instant;
+ type Value = Duration;
+
+ fn start(&self) -> Self::Intermediate {
+ Instant::now()
+ }
+ fn end(&self, i: Self::Intermediate) -> Self::Value {
+ i.elapsed()
+ }
+ fn add(&self, v1: &Self::Value, v2: &Self::Value) -> Self::Value {
+ *v1 + *v2
+ }
+ fn zero(&self) -> Self::Value {
+ Duration::from_secs(0)
+ }
+ fn to_f64(&self, val: &Self::Value) -> f64 {
+ let nanos = val.as_secs() * NANOS_PER_SEC + u64::from(val.subsec_nanos());
+ nanos as f64
+ }
+ fn formatter(&self) -> &dyn ValueFormatter {
+ &HalfSecFormatter
+ }
+}
+
+fn fibonacci_slow(n: u64) -> u64 {
+ match n {
+ 0 | 1 => 1,
+ n => fibonacci_slow(n - 1) + fibonacci_slow(n - 2),
+ }
+}
+
+fn fibonacci_cycles(criterion: &mut Criterion<HalfSeconds>) {
+ criterion.bench_function("fibonacci_custom_measurement", |bencher| {
+ bencher.iter(|| fibonacci_slow(black_box(10)))
+ });
+}
+
+fn alternate_measurement() -> Criterion<HalfSeconds> {
+ Criterion::default().with_measurement(HalfSeconds)
+}
+
+criterion_group! {
+ name = benches;
+ config = alternate_measurement();
+ targets = fibonacci_cycles
+}