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
use criterion::measurement::{Measurement, ValueFormatter}; use criterion::Throughput; pub struct CyclesPerByte; fn rdtsc() -> u64 { #[cfg(target_arch = "x86_64")] unsafe { core::arch::x86_64::_rdtsc() } #[cfg(target_arch = "x86")] unsafe { core::arch::x86::_rdtsc() } } impl Measurement for CyclesPerByte { type Intermediate = u64; type Value = u64; fn start(&self) -> Self::Intermediate { rdtsc() } fn end(&self, i: Self::Intermediate) -> Self::Value { rdtsc() - i } fn add(&self, v1: &Self::Value, v2: &Self::Value) -> Self::Value { v1 + v2 } fn zero(&self) -> Self::Value { 0 } fn to_f64(&self, value: &Self::Value) -> f64 { *value as f64 } fn formatter(&self) -> &dyn ValueFormatter { &CyclesPerByteFormatter } } struct CyclesPerByteFormatter; impl ValueFormatter for CyclesPerByteFormatter { fn format_value(&self, value: f64) -> String { format!("{:.4} cycles", value) } fn format_throughput(&self, throughput: &Throughput, value: f64) -> String { match throughput { Throughput::Bytes(b) => format!("{:.4} cpb", value / *b as f64), Throughput::Elements(b) => format!("{:.4} cycles/{}", value, b), } } fn scale_values(&self, _typical_value: f64, _values: &mut [f64]) -> &'static str { "cycles" } fn scale_throughputs( &self, _typical_value: f64, throughput: &Throughput, values: &mut [f64], ) -> &'static str { match throughput { Throughput::Bytes(n) => { for val in values { *val /= *n as f64; } "cpb" } Throughput::Elements(n) => { for val in values { *val /= *n as f64; } "c/e" } } } fn scale_for_machines(&self, _values: &mut [f64]) -> &'static str { "cycles" } }