1 // cargo run --example upstream_benchmark --release
2 
3 use rand::{Rng, SeedableRng};
4 
5 const SAMPLES: usize = 10000;
6 const ITERATIONS: usize = 1000;
7 
8 struct MeanAndVariance {
9     n: i64,
10     mean: f64,
11     m2: f64,
12 }
13 
14 impl MeanAndVariance {
new() -> Self15     fn new() -> Self {
16         MeanAndVariance {
17             n: 0,
18             mean: 0.0,
19             m2: 0.0,
20         }
21     }
22 
update(&mut self, x: f64)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 
variance(&self) -> f6431     fn variance(&self) -> f64 {
32         self.m2 / (self.n - 1) as f64
33     }
34 
stddev(&self) -> f6435     fn stddev(&self) -> f64 {
36         self.variance().sqrt()
37     }
38 }
39 
40 macro_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 
73 benchmark!(pretty32, f32);
74 benchmark!(pretty64, f64);
75 
main()76 fn 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