1// cargo run --example upstream_benchmark --release
2
3use rand::{Rng, SeedableRng};
4
5const SAMPLES: usize = 10000;
6const ITERATIONS: usize = 1000;
7
8struct MeanAndVariance {
9 n: i64,
10 mean: f64,
11 m2: f64,
12}
13
14impl MeanAndVariance {
15 fn new() -> Self {
16 MeanAndVariance {
17 n: 0,
18 mean: 0.0,
19 m2: 0.0,
20 }
21 }
22
23 fn update(&mut self, x: f64) {
24 self.n += 1;
25 let d = x - self.mean;
26 self.mean += d / self.n as f64;
27 let d2 = x - self.mean;
28 self.m2 += d * d2;
29 }
30
31 fn variance(&self) -> f64 {
32 self.m2 / (self.n - 1) as f64
33 }
34
35 fn stddev(&self) -> f64 {
36 self.variance().sqrt()
37 }
38}
39
40macro_rules! benchmark {
41 ($name:ident, $ty:ident) => {
42 fn $name() -> usize {
43 let mut rng = rand_xorshift::XorShiftRng::from_seed([123u8; 16]);
44 let mut mv = MeanAndVariance::new();
45 let mut throwaway = 0;
46 for _ in 0..SAMPLES {
47 let f = loop {
48 let f = $ty::from_bits(rng.gen());
49 if f.is_finite() {
50 break f;
51 }
52 };
53
54 let t1 = std::time::SystemTime::now();
55 for _ in 0..ITERATIONS {
56 throwaway += ryu::Buffer::new().format_finite(f).len();
57 }
58 let duration = t1.elapsed().unwrap();
59 let nanos = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64;
60 mv.update(nanos as f64 / ITERATIONS as f64);
61 }
62 println!(
63 "{:12} {:8.3} {:8.3}",
64 concat!(stringify!($name), ":"),
65 mv.mean,
66 mv.stddev(),
67 );
68 throwaway
69 }
70 };
71}
72
73benchmark!(pretty32, f32);
74benchmark!(pretty64, f64);
75
76fn main() {
77 println!("{:>20}{:>9}", "Average", "Stddev");
78 let mut throwaway = 0;
79 throwaway += pretty32();
80 throwaway += pretty64();
81 if std::env::var_os("ryu-benchmark").is_some() {
82 // Prevent the compiler from optimizing the code away.
83 println!("{}", throwaway);
84 }
85}
86