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
|
// cargo run --example upstream_benchmark --release
use rand::{Rng, SeedableRng};
const SAMPLES: usize = 10000;
const ITERATIONS: usize = 1000;
struct MeanAndVariance {
n: i64,
mean: f64,
m2: f64,
}
impl MeanAndVariance {
fn new() -> Self {
MeanAndVariance {
n: 0,
mean: 0.0,
m2: 0.0,
}
}
fn update(&mut self, x: f64) {
self.n += 1;
let d = x - self.mean;
self.mean += d / self.n as f64;
let d2 = x - self.mean;
self.m2 += d * d2;
}
fn variance(&self) -> f64 {
self.m2 / (self.n - 1) as f64
}
fn stddev(&self) -> f64 {
self.variance().sqrt()
}
}
macro_rules! benchmark {
($name:ident, $ty:ident) => {
fn $name() -> usize {
let mut rng = rand_xorshift::XorShiftRng::from_seed([123u8; 16]);
let mut mv = MeanAndVariance::new();
let mut throwaway = 0;
for _ in 0..SAMPLES {
let f = loop {
let f = $ty::from_bits(rng.gen());
if f.is_finite() {
break f;
}
};
let t1 = std::time::SystemTime::now();
for _ in 0..ITERATIONS {
throwaway += ryu::Buffer::new().format_finite(f).len();
}
let duration = t1.elapsed().unwrap();
let nanos = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64;
mv.update(nanos as f64 / ITERATIONS as f64);
}
println!(
"{:12} {:8.3} {:8.3}",
concat!(stringify!($name), ":"),
mv.mean,
mv.stddev(),
);
throwaway
}
};
}
benchmark!(pretty32, f32);
benchmark!(pretty64, f64);
fn main() {
println!("{:>20}{:>9}", "Average", "Stddev");
let mut throwaway = 0;
throwaway += pretty32();
throwaway += pretty64();
if std::env::var_os("ryu-benchmark").is_some() {
// Prevent the compiler from optimizing the code away.
println!("{}", throwaway);
}
}
|