Skip to content

Commit 12d3f10

Browse files
committed
Auto merge of #96626 - thomcc:rand-bump, r=m-ou-se
Avoid using `rand::thread_rng` in the stdlib benchmarks. This is kind of an anti-pattern because it introduces extra nondeterminism for no real reason. In thread_rng's case this comes both from the random seed and also from the reseeding operations it does, which occasionally does syscalls (which adds additional nondeterminism). The impact of this would be pretty small in most cases, but it's a good practice to avoid (particularly because avoiding it was not hard). Anyway, several of our benchmarks already did the right thing here anyway, so the change was pretty easy and mostly just applying it more universally. That said, the stdlib benchmarks aren't particularly stable (nor is our benchmark framework particularly great), so arguably this doesn't matter that much in practice. ~~Anyway, this also bumps the `rand` dev-dependency to 0.8, since it had fallen somewhat out of date.~~ Nevermind, too much of a headache.
2 parents 7d3e036 + 0812759 commit 12d3f10

File tree

10 files changed

+43
-28
lines changed

10 files changed

+43
-28
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,7 @@ name = "core"
828828
version = "0.0.0"
829829
dependencies = [
830830
"rand 0.7.3",
831+
"rand_xorshift",
831832
]
832833

833834
[[package]]

library/alloc/benches/binary_heap.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use std::collections::BinaryHeap;
22

3-
use rand::{seq::SliceRandom, thread_rng};
3+
use rand::seq::SliceRandom;
44
use test::{black_box, Bencher};
55

66
#[bench]
77
fn bench_find_smallest_1000(b: &mut Bencher) {
8-
let mut rng = thread_rng();
8+
let mut rng = crate::bench_rng();
99
let mut vec: Vec<u32> = (0..100_000).collect();
1010
vec.shuffle(&mut rng);
1111

@@ -47,7 +47,7 @@ fn bench_peek_mut_deref_mut(b: &mut Bencher) {
4747

4848
#[bench]
4949
fn bench_from_vec(b: &mut Bencher) {
50-
let mut rng = thread_rng();
50+
let mut rng = crate::bench_rng();
5151
let mut vec: Vec<u32> = (0..100_000).collect();
5252
vec.shuffle(&mut rng);
5353

@@ -64,7 +64,7 @@ fn bench_into_sorted_vec(b: &mut Bencher) {
6464
#[bench]
6565
fn bench_push(b: &mut Bencher) {
6666
let mut bheap = BinaryHeap::with_capacity(50_000);
67-
let mut rng = thread_rng();
67+
let mut rng = crate::bench_rng();
6868
let mut vec: Vec<u32> = (0..50_000).collect();
6969
vec.shuffle(&mut rng);
7070

library/alloc/benches/btree/map.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::iter::Iterator;
33
use std::ops::RangeBounds;
44
use std::vec::Vec;
55

6-
use rand::{seq::SliceRandom, thread_rng, Rng};
6+
use rand::{seq::SliceRandom, Rng};
77
use test::{black_box, Bencher};
88

99
macro_rules! map_insert_rand_bench {
@@ -13,7 +13,7 @@ macro_rules! map_insert_rand_bench {
1313
let n: usize = $n;
1414
let mut map = $map::new();
1515
// setup
16-
let mut rng = thread_rng();
16+
let mut rng = crate::bench_rng();
1717

1818
for _ in 0..n {
1919
let i = rng.gen::<usize>() % n;
@@ -60,7 +60,7 @@ macro_rules! map_from_iter_rand_bench {
6060
pub fn $name(b: &mut Bencher) {
6161
let n: usize = $n;
6262
// setup
63-
let mut rng = thread_rng();
63+
let mut rng = crate::bench_rng();
6464
let mut vec = Vec::with_capacity(n);
6565

6666
for _ in 0..n {
@@ -106,7 +106,7 @@ macro_rules! map_find_rand_bench {
106106
let n: usize = $n;
107107

108108
// setup
109-
let mut rng = thread_rng();
109+
let mut rng = crate::bench_rng();
110110
let mut keys: Vec<_> = (0..n).map(|_| rng.gen::<usize>() % n).collect();
111111

112112
for &k in &keys {
@@ -169,7 +169,7 @@ map_find_seq_bench! {find_seq_10_000, 10_000, BTreeMap}
169169

170170
fn bench_iteration(b: &mut Bencher, size: i32) {
171171
let mut map = BTreeMap::<i32, i32>::new();
172-
let mut rng = thread_rng();
172+
let mut rng = crate::bench_rng();
173173

174174
for _ in 0..size {
175175
map.insert(rng.gen(), rng.gen());
@@ -199,7 +199,7 @@ pub fn iteration_100000(b: &mut Bencher) {
199199

200200
fn bench_iteration_mut(b: &mut Bencher, size: i32) {
201201
let mut map = BTreeMap::<i32, i32>::new();
202-
let mut rng = thread_rng();
202+
let mut rng = crate::bench_rng();
203203

204204
for _ in 0..size {
205205
map.insert(rng.gen(), rng.gen());

library/alloc/benches/btree/set.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use std::collections::BTreeSet;
22

3-
use rand::{thread_rng, Rng};
3+
use rand::Rng;
44
use test::Bencher;
55

66
fn random(n: usize) -> BTreeSet<usize> {
7-
let mut rng = thread_rng();
7+
let mut rng = crate::bench_rng();
88
let mut set = BTreeSet::new();
99
while set.len() < n {
1010
set.insert(rng.gen());

library/alloc/benches/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,11 @@ mod str;
1717
mod string;
1818
mod vec;
1919
mod vec_deque;
20+
21+
/// Returns a `rand::Rng` seeded with a consistent seed.
22+
///
23+
/// This is done to avoid introducing nondeterminism in benchmark results.
24+
fn bench_rng() -> rand_xorshift::XorShiftRng {
25+
const SEED: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
26+
rand::SeedableRng::from_seed(SEED)
27+
}

library/alloc/benches/slice.rs

+9-12
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use std::{mem, ptr};
22

33
use rand::distributions::{Alphanumeric, Standard};
4-
use rand::{thread_rng, Rng, SeedableRng};
5-
use rand_xorshift::XorShiftRng;
4+
use rand::Rng;
65
use test::{black_box, Bencher};
76

87
#[bench]
@@ -152,7 +151,7 @@ fn zero_1kb_mut_iter(b: &mut Bencher) {
152151

153152
#[bench]
154153
fn random_inserts(b: &mut Bencher) {
155-
let mut rng = thread_rng();
154+
let mut rng = crate::bench_rng();
156155
b.iter(|| {
157156
let mut v = vec![(0, 0); 30];
158157
for _ in 0..100 {
@@ -164,7 +163,7 @@ fn random_inserts(b: &mut Bencher) {
164163

165164
#[bench]
166165
fn random_removes(b: &mut Bencher) {
167-
let mut rng = thread_rng();
166+
let mut rng = crate::bench_rng();
168167
b.iter(|| {
169168
let mut v = vec![(0, 0); 130];
170169
for _ in 0..100 {
@@ -182,20 +181,18 @@ fn gen_descending(len: usize) -> Vec<u64> {
182181
(0..len as u64).rev().collect()
183182
}
184183

185-
const SEED: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
186-
187184
fn gen_random(len: usize) -> Vec<u64> {
188-
let mut rng = XorShiftRng::from_seed(SEED);
185+
let mut rng = crate::bench_rng();
189186
(&mut rng).sample_iter(&Standard).take(len).collect()
190187
}
191188

192189
fn gen_random_bytes(len: usize) -> Vec<u8> {
193-
let mut rng = XorShiftRng::from_seed(SEED);
190+
let mut rng = crate::bench_rng();
194191
(&mut rng).sample_iter(&Standard).take(len).collect()
195192
}
196193

197194
fn gen_mostly_ascending(len: usize) -> Vec<u64> {
198-
let mut rng = XorShiftRng::from_seed(SEED);
195+
let mut rng = crate::bench_rng();
199196
let mut v = gen_ascending(len);
200197
for _ in (0usize..).take_while(|x| x * x <= len) {
201198
let x = rng.gen::<usize>() % len;
@@ -206,7 +203,7 @@ fn gen_mostly_ascending(len: usize) -> Vec<u64> {
206203
}
207204

208205
fn gen_mostly_descending(len: usize) -> Vec<u64> {
209-
let mut rng = XorShiftRng::from_seed(SEED);
206+
let mut rng = crate::bench_rng();
210207
let mut v = gen_descending(len);
211208
for _ in (0usize..).take_while(|x| x * x <= len) {
212209
let x = rng.gen::<usize>() % len;
@@ -217,7 +214,7 @@ fn gen_mostly_descending(len: usize) -> Vec<u64> {
217214
}
218215

219216
fn gen_strings(len: usize) -> Vec<String> {
220-
let mut rng = XorShiftRng::from_seed(SEED);
217+
let mut rng = crate::bench_rng();
221218
let mut v = vec![];
222219
for _ in 0..len {
223220
let n = rng.gen::<usize>() % 20 + 1;
@@ -227,7 +224,7 @@ fn gen_strings(len: usize) -> Vec<String> {
227224
}
228225

229226
fn gen_big_random(len: usize) -> Vec<[u64; 16]> {
230-
let mut rng = XorShiftRng::from_seed(SEED);
227+
let mut rng = crate::bench_rng();
231228
(&mut rng).sample_iter(&Standard).map(|x| [x; 16]).take(len).collect()
232229
}
233230

library/alloc/benches/vec.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ fn bench_in_place_recycle(b: &mut Bencher) {
476476
#[bench]
477477
fn bench_in_place_zip_recycle(b: &mut Bencher) {
478478
let mut data = vec![0u8; 1000];
479-
let mut rng = rand::thread_rng();
479+
let mut rng = crate::bench_rng();
480480
let mut subst = vec![0u8; 1000];
481481
rng.fill_bytes(&mut subst[..]);
482482

@@ -495,7 +495,7 @@ fn bench_in_place_zip_recycle(b: &mut Bencher) {
495495
#[bench]
496496
fn bench_in_place_zip_iter_mut(b: &mut Bencher) {
497497
let mut data = vec![0u8; 256];
498-
let mut rng = rand::thread_rng();
498+
let mut rng = crate::bench_rng();
499499
let mut subst = vec![0u8; 1000];
500500
rng.fill_bytes(&mut subst[..]);
501501

library/core/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ test = true
2525

2626
[dev-dependencies]
2727
rand = "0.7"
28+
rand_xorshift = "0.2"
2829

2930
[features]
3031
# Make panics and failed asserts immediately abort without formatting any message

library/core/benches/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,11 @@ mod ops;
1818
mod pattern;
1919
mod slice;
2020
mod str;
21+
22+
/// Returns a `rand::Rng` seeded with a consistent seed.
23+
///
24+
/// This is done to avoid introducing nondeterminism in benchmark results.
25+
fn bench_rng() -> rand_xorshift::XorShiftRng {
26+
const SEED: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
27+
rand::SeedableRng::from_seed(SEED)
28+
}

library/core/benches/num/int_log/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ macro_rules! int_log_bench {
1717

1818
#[bench]
1919
fn $random(bench: &mut Bencher) {
20-
let mut rng = rand::thread_rng();
20+
let mut rng = crate::bench_rng();
2121
/* Exponentially distributed random numbers from the whole range of the type. */
2222
let numbers: Vec<$t> = (0..256)
2323
.map(|_| {
@@ -34,7 +34,7 @@ macro_rules! int_log_bench {
3434

3535
#[bench]
3636
fn $random_small(bench: &mut Bencher) {
37-
let mut rng = rand::thread_rng();
37+
let mut rng = crate::bench_rng();
3838
/* Exponentially distributed random numbers from the range 0..256. */
3939
let numbers: Vec<$t> = (0..256)
4040
.map(|_| {

0 commit comments

Comments
 (0)