oficina / docs Public

Clone
git clone https://amadan.net/oficina/docs

Plain git — no account needed to clone.

Download

Download this file

1#![feature(test)]
2
3extern crate test;
4
5use rand::prelude::*;
6use test::Bencher;
7
8/// Exposes wyhash's RNG through the rand traits
9struct WyRng(u64);
10
11impl rand::TryRng for WyRng {
12 type Error = std::convert::Infallible;
13
14 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
15 Ok(wyhash::wyrng(&mut self.0) as u32)
16 }
17
18 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
19 Ok(wyhash::wyrng(&mut self.0))
20 }
21
22 fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> {
23 for chunk in dst.chunks_mut(8) {
24 let bytes = wyhash::wyrng(&mut self.0).to_le_bytes();
25 chunk.copy_from_slice(&bytes[..chunk.len()]);
26 }
27 Ok(())
28 }
29}
30
31fn wyrng() -> WyRng {
32 WyRng(rand::random())
33}
34
35#[bench]
36fn shuffle_wyhash(b: &mut Bencher) {
37 let mut rng = wyrng();
38 let mut x = (0..100).collect::<Vec<usize>>();
39 b.iter(|| {
40 x.shuffle(&mut rng);
41 x[0]
42 })
43}
44
45#[bench]
46fn shuffle_fastrand(b: &mut Bencher) {
47 let mut rng = fastrand::Rng::new();
48 let mut x = (0..100).collect::<Vec<usize>>();
49 b.iter(|| {
50 rng.shuffle(&mut x);
51 x[0]
52 })
53}
54
55#[bench]
56fn u8_wyhash(b: &mut Bencher) {
57 let mut rng = wyrng();
58 b.iter(|| {
59 let mut sum = 0u8;
60 for _ in 0..10_000 {
61 sum = sum.wrapping_add(rng.random::<u8>());
62 }
63 sum
64 })
65}
66
67#[bench]
68fn u8_fastrand(b: &mut Bencher) {
69 let mut rng = fastrand::Rng::new();
70 b.iter(|| {
71 let mut sum = 0u8;
72 for _ in 0..10_000 {
73 sum = sum.wrapping_add(rng.u8(..));
74 }
75 sum
76 })
77}
78
79#[bench]
80fn u32_wyhash(b: &mut Bencher) {
81 let mut rng = wyrng();
82 b.iter(|| {
83 let mut sum = 0u32;
84 for _ in 0..10_000 {
85 sum = sum.wrapping_add(rng.random::<u32>());
86 }
87 sum
88 })
89}
90
91#[bench]
92fn u32_fastrand(b: &mut Bencher) {
93 let mut rng = fastrand::Rng::new();
94 b.iter(|| {
95 let mut sum = 0u32;
96 for _ in 0..10_000 {
97 sum = sum.wrapping_add(rng.u32(..));
98 }
99 sum
100 })
101}
102
103#[bench]
104fn f32_fastrand(b: &mut Bencher) {
105 let mut rng = fastrand::Rng::new();
106 b.iter(|| {
107 // f32 sum unrolled 2x to hide f32-add latency.
108 //
109 // Optimal amount of unrolling is somewhat sensitive to CPU and algorithm.
110 // Variously could be 2x, 3x, or 4x unrolling. On AArch64 and x86-64 on the
111 // current algorithm, 2x seems to be optimal on this benchmark.
112 let mut sum = 0.0;
113 for _ in 0..5_000 {
114 sum += rng.f32() + rng.f32();
115 }
116 sum
117 })
118}
119
120#[bench]
121fn fill(b: &mut Bencher) {
122 let mut rng = fastrand::Rng::new();
123 b.iter(|| {
124 // Pick a size that isn't divisible by 8.
125 let mut bytes = [0u8; 367];
126 rng.fill(&mut bytes);
127 bytes
128 })
129}
130
131#[bench]
132fn fill_naive(b: &mut Bencher) {
133 let mut rng = fastrand::Rng::new();
134 b.iter(|| {
135 let mut bytes = [0u8; 367];
136 for item in &mut bytes {
137 *item = rng.u8(..);
138 }
139 bytes
140 })
141}
142