From 0812759840eb9c52e646729603a207c2a0ed1a65 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Sun, 1 May 2022 23:10:56 -0700 Subject: [PATCH] Avoid use of `rand::thread_rng` in stdlib benchmarks --- Cargo.lock | 1 + library/alloc/benches/binary_heap.rs | 8 ++++---- library/alloc/benches/btree/map.rs | 12 ++++++------ library/alloc/benches/btree/set.rs | 4 ++-- library/alloc/benches/lib.rs | 8 ++++++++ library/alloc/benches/slice.rs | 21 +++++++++------------ library/alloc/benches/vec.rs | 4 ++-- library/core/Cargo.toml | 1 + library/core/benches/lib.rs | 8 ++++++++ library/core/benches/num/int_log/mod.rs | 4 ++-- 10 files changed, 43 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ef4800a226136..f4d2caea44300 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -827,6 +827,7 @@ name = "core" version = "0.0.0" dependencies = [ "rand 0.7.3", + "rand_xorshift", ] [[package]] diff --git a/library/alloc/benches/binary_heap.rs b/library/alloc/benches/binary_heap.rs index 491243e22c73b..917e71f250ee8 100644 --- a/library/alloc/benches/binary_heap.rs +++ b/library/alloc/benches/binary_heap.rs @@ -1,11 +1,11 @@ use std::collections::BinaryHeap; -use rand::{seq::SliceRandom, thread_rng}; +use rand::seq::SliceRandom; use test::{black_box, Bencher}; #[bench] fn bench_find_smallest_1000(b: &mut Bencher) { - let mut rng = thread_rng(); + let mut rng = crate::bench_rng(); let mut vec: Vec = (0..100_000).collect(); vec.shuffle(&mut rng); @@ -47,7 +47,7 @@ fn bench_peek_mut_deref_mut(b: &mut Bencher) { #[bench] fn bench_from_vec(b: &mut Bencher) { - let mut rng = thread_rng(); + let mut rng = crate::bench_rng(); let mut vec: Vec = (0..100_000).collect(); vec.shuffle(&mut rng); @@ -64,7 +64,7 @@ fn bench_into_sorted_vec(b: &mut Bencher) { #[bench] fn bench_push(b: &mut Bencher) { let mut bheap = BinaryHeap::with_capacity(50_000); - let mut rng = thread_rng(); + let mut rng = crate::bench_rng(); let mut vec: Vec = (0..50_000).collect(); vec.shuffle(&mut rng); diff --git a/library/alloc/benches/btree/map.rs b/library/alloc/benches/btree/map.rs index 89c21929dbcda..1f6b87fb0e40f 100644 --- a/library/alloc/benches/btree/map.rs +++ b/library/alloc/benches/btree/map.rs @@ -3,7 +3,7 @@ use std::iter::Iterator; use std::ops::RangeBounds; use std::vec::Vec; -use rand::{seq::SliceRandom, thread_rng, Rng}; +use rand::{seq::SliceRandom, Rng}; use test::{black_box, Bencher}; macro_rules! map_insert_rand_bench { @@ -13,7 +13,7 @@ macro_rules! map_insert_rand_bench { let n: usize = $n; let mut map = $map::new(); // setup - let mut rng = thread_rng(); + let mut rng = crate::bench_rng(); for _ in 0..n { let i = rng.gen::() % n; @@ -60,7 +60,7 @@ macro_rules! map_from_iter_rand_bench { pub fn $name(b: &mut Bencher) { let n: usize = $n; // setup - let mut rng = thread_rng(); + let mut rng = crate::bench_rng(); let mut vec = Vec::with_capacity(n); for _ in 0..n { @@ -106,7 +106,7 @@ macro_rules! map_find_rand_bench { let n: usize = $n; // setup - let mut rng = thread_rng(); + let mut rng = crate::bench_rng(); let mut keys: Vec<_> = (0..n).map(|_| rng.gen::() % n).collect(); for &k in &keys { @@ -169,7 +169,7 @@ map_find_seq_bench! {find_seq_10_000, 10_000, BTreeMap} fn bench_iteration(b: &mut Bencher, size: i32) { let mut map = BTreeMap::::new(); - let mut rng = thread_rng(); + let mut rng = crate::bench_rng(); for _ in 0..size { map.insert(rng.gen(), rng.gen()); @@ -199,7 +199,7 @@ pub fn iteration_100000(b: &mut Bencher) { fn bench_iteration_mut(b: &mut Bencher, size: i32) { let mut map = BTreeMap::::new(); - let mut rng = thread_rng(); + let mut rng = crate::bench_rng(); for _ in 0..size { map.insert(rng.gen(), rng.gen()); diff --git a/library/alloc/benches/btree/set.rs b/library/alloc/benches/btree/set.rs index 07bf5093727c0..3f4b0e0f14af7 100644 --- a/library/alloc/benches/btree/set.rs +++ b/library/alloc/benches/btree/set.rs @@ -1,10 +1,10 @@ use std::collections::BTreeSet; -use rand::{thread_rng, Rng}; +use rand::Rng; use test::Bencher; fn random(n: usize) -> BTreeSet { - let mut rng = thread_rng(); + let mut rng = crate::bench_rng(); let mut set = BTreeSet::new(); while set.len() < n { set.insert(rng.gen()); diff --git a/library/alloc/benches/lib.rs b/library/alloc/benches/lib.rs index 38a8f65f1695a..7dc0f7cebd535 100644 --- a/library/alloc/benches/lib.rs +++ b/library/alloc/benches/lib.rs @@ -17,3 +17,11 @@ mod str; mod string; mod vec; mod vec_deque; + +/// Returns a `rand::Rng` seeded with a consistent seed. +/// +/// This is done to avoid introducing nondeterminism in benchmark results. +fn bench_rng() -> rand_xorshift::XorShiftRng { + const SEED: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + rand::SeedableRng::from_seed(SEED) +} diff --git a/library/alloc/benches/slice.rs b/library/alloc/benches/slice.rs index e20c043286e6f..bd6f38f2f1003 100644 --- a/library/alloc/benches/slice.rs +++ b/library/alloc/benches/slice.rs @@ -1,8 +1,7 @@ use std::{mem, ptr}; use rand::distributions::{Alphanumeric, Standard}; -use rand::{thread_rng, Rng, SeedableRng}; -use rand_xorshift::XorShiftRng; +use rand::Rng; use test::{black_box, Bencher}; #[bench] @@ -152,7 +151,7 @@ fn zero_1kb_mut_iter(b: &mut Bencher) { #[bench] fn random_inserts(b: &mut Bencher) { - let mut rng = thread_rng(); + let mut rng = crate::bench_rng(); b.iter(|| { let mut v = vec![(0, 0); 30]; for _ in 0..100 { @@ -164,7 +163,7 @@ fn random_inserts(b: &mut Bencher) { #[bench] fn random_removes(b: &mut Bencher) { - let mut rng = thread_rng(); + let mut rng = crate::bench_rng(); b.iter(|| { let mut v = vec![(0, 0); 130]; for _ in 0..100 { @@ -182,20 +181,18 @@ fn gen_descending(len: usize) -> Vec { (0..len as u64).rev().collect() } -const SEED: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; - fn gen_random(len: usize) -> Vec { - let mut rng = XorShiftRng::from_seed(SEED); + let mut rng = crate::bench_rng(); (&mut rng).sample_iter(&Standard).take(len).collect() } fn gen_random_bytes(len: usize) -> Vec { - let mut rng = XorShiftRng::from_seed(SEED); + let mut rng = crate::bench_rng(); (&mut rng).sample_iter(&Standard).take(len).collect() } fn gen_mostly_ascending(len: usize) -> Vec { - let mut rng = XorShiftRng::from_seed(SEED); + let mut rng = crate::bench_rng(); let mut v = gen_ascending(len); for _ in (0usize..).take_while(|x| x * x <= len) { let x = rng.gen::() % len; @@ -206,7 +203,7 @@ fn gen_mostly_ascending(len: usize) -> Vec { } fn gen_mostly_descending(len: usize) -> Vec { - let mut rng = XorShiftRng::from_seed(SEED); + let mut rng = crate::bench_rng(); let mut v = gen_descending(len); for _ in (0usize..).take_while(|x| x * x <= len) { let x = rng.gen::() % len; @@ -217,7 +214,7 @@ fn gen_mostly_descending(len: usize) -> Vec { } fn gen_strings(len: usize) -> Vec { - let mut rng = XorShiftRng::from_seed(SEED); + let mut rng = crate::bench_rng(); let mut v = vec![]; for _ in 0..len { let n = rng.gen::() % 20 + 1; @@ -227,7 +224,7 @@ fn gen_strings(len: usize) -> Vec { } fn gen_big_random(len: usize) -> Vec<[u64; 16]> { - let mut rng = XorShiftRng::from_seed(SEED); + let mut rng = crate::bench_rng(); (&mut rng).sample_iter(&Standard).map(|x| [x; 16]).take(len).collect() } diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs index 333b3c20d1d39..efc47327e8a86 100644 --- a/library/alloc/benches/vec.rs +++ b/library/alloc/benches/vec.rs @@ -476,7 +476,7 @@ fn bench_in_place_recycle(b: &mut Bencher) { #[bench] fn bench_in_place_zip_recycle(b: &mut Bencher) { let mut data = vec![0u8; 1000]; - let mut rng = rand::thread_rng(); + let mut rng = crate::bench_rng(); let mut subst = vec![0u8; 1000]; rng.fill_bytes(&mut subst[..]); @@ -495,7 +495,7 @@ fn bench_in_place_zip_recycle(b: &mut Bencher) { #[bench] fn bench_in_place_zip_iter_mut(b: &mut Bencher) { let mut data = vec![0u8; 256]; - let mut rng = rand::thread_rng(); + let mut rng = crate::bench_rng(); let mut subst = vec![0u8; 1000]; rng.fill_bytes(&mut subst[..]); diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index 6a0c6cd961d26..2a7df9556cfe1 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -25,6 +25,7 @@ test = true [dev-dependencies] rand = "0.7" +rand_xorshift = "0.2" [features] # Make panics and failed asserts immediately abort without formatting any message diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs index d5e1ec083f95d..5e19b6db85489 100644 --- a/library/core/benches/lib.rs +++ b/library/core/benches/lib.rs @@ -17,3 +17,11 @@ mod ops; mod pattern; mod slice; mod str; + +/// Returns a `rand::Rng` seeded with a consistent seed. +/// +/// This is done to avoid introducing nondeterminism in benchmark results. +fn bench_rng() -> rand_xorshift::XorShiftRng { + const SEED: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + rand::SeedableRng::from_seed(SEED) +} diff --git a/library/core/benches/num/int_log/mod.rs b/library/core/benches/num/int_log/mod.rs index 6a219bcdd55aa..19864d2d4676a 100644 --- a/library/core/benches/num/int_log/mod.rs +++ b/library/core/benches/num/int_log/mod.rs @@ -17,7 +17,7 @@ macro_rules! int_log_bench { #[bench] fn $random(bench: &mut Bencher) { - let mut rng = rand::thread_rng(); + let mut rng = crate::bench_rng(); /* Exponentially distributed random numbers from the whole range of the type. */ let numbers: Vec<$t> = (0..256) .map(|_| { @@ -34,7 +34,7 @@ macro_rules! int_log_bench { #[bench] fn $random_small(bench: &mut Bencher) { - let mut rng = rand::thread_rng(); + let mut rng = crate::bench_rng(); /* Exponentially distributed random numbers from the range 0..256. */ let numbers: Vec<$t> = (0..256) .map(|_| {