You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
3.1 KiB
119 lines
3.1 KiB
7 months ago
|
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
|
||
|
}
|