Avoid use of `rand::thread_rng` in stdlib benchmarks

This commit is contained in:
Thom Chiovoloni 2022-05-01 23:10:56 -07:00
parent 4c5efea6fe
commit 0812759840
No known key found for this signature in database
GPG Key ID: E2EFD4309E11C8A8
10 changed files with 43 additions and 28 deletions

View File

@ -827,6 +827,7 @@ name = "core"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"rand 0.7.3", "rand 0.7.3",
"rand_xorshift",
] ]
[[package]] [[package]]

View File

@ -1,11 +1,11 @@
use std::collections::BinaryHeap; use std::collections::BinaryHeap;
use rand::{seq::SliceRandom, thread_rng}; use rand::seq::SliceRandom;
use test::{black_box, Bencher}; use test::{black_box, Bencher};
#[bench] #[bench]
fn bench_find_smallest_1000(b: &mut Bencher) { fn bench_find_smallest_1000(b: &mut Bencher) {
let mut rng = thread_rng(); let mut rng = crate::bench_rng();
let mut vec: Vec<u32> = (0..100_000).collect(); let mut vec: Vec<u32> = (0..100_000).collect();
vec.shuffle(&mut rng); vec.shuffle(&mut rng);
@ -47,7 +47,7 @@ fn bench_peek_mut_deref_mut(b: &mut Bencher) {
#[bench] #[bench]
fn bench_from_vec(b: &mut Bencher) { fn bench_from_vec(b: &mut Bencher) {
let mut rng = thread_rng(); let mut rng = crate::bench_rng();
let mut vec: Vec<u32> = (0..100_000).collect(); let mut vec: Vec<u32> = (0..100_000).collect();
vec.shuffle(&mut rng); vec.shuffle(&mut rng);
@ -64,7 +64,7 @@ fn bench_into_sorted_vec(b: &mut Bencher) {
#[bench] #[bench]
fn bench_push(b: &mut Bencher) { fn bench_push(b: &mut Bencher) {
let mut bheap = BinaryHeap::with_capacity(50_000); let mut bheap = BinaryHeap::with_capacity(50_000);
let mut rng = thread_rng(); let mut rng = crate::bench_rng();
let mut vec: Vec<u32> = (0..50_000).collect(); let mut vec: Vec<u32> = (0..50_000).collect();
vec.shuffle(&mut rng); vec.shuffle(&mut rng);

View File

@ -3,7 +3,7 @@ use std::iter::Iterator;
use std::ops::RangeBounds; use std::ops::RangeBounds;
use std::vec::Vec; use std::vec::Vec;
use rand::{seq::SliceRandom, thread_rng, Rng}; use rand::{seq::SliceRandom, Rng};
use test::{black_box, Bencher}; use test::{black_box, Bencher};
macro_rules! map_insert_rand_bench { macro_rules! map_insert_rand_bench {
@ -13,7 +13,7 @@ macro_rules! map_insert_rand_bench {
let n: usize = $n; let n: usize = $n;
let mut map = $map::new(); let mut map = $map::new();
// setup // setup
let mut rng = thread_rng(); let mut rng = crate::bench_rng();
for _ in 0..n { for _ in 0..n {
let i = rng.gen::<usize>() % n; let i = rng.gen::<usize>() % n;
@ -60,7 +60,7 @@ macro_rules! map_from_iter_rand_bench {
pub fn $name(b: &mut Bencher) { pub fn $name(b: &mut Bencher) {
let n: usize = $n; let n: usize = $n;
// setup // setup
let mut rng = thread_rng(); let mut rng = crate::bench_rng();
let mut vec = Vec::with_capacity(n); let mut vec = Vec::with_capacity(n);
for _ in 0..n { for _ in 0..n {
@ -106,7 +106,7 @@ macro_rules! map_find_rand_bench {
let n: usize = $n; let n: usize = $n;
// setup // setup
let mut rng = thread_rng(); let mut rng = crate::bench_rng();
let mut keys: Vec<_> = (0..n).map(|_| rng.gen::<usize>() % n).collect(); let mut keys: Vec<_> = (0..n).map(|_| rng.gen::<usize>() % n).collect();
for &k in &keys { 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) { fn bench_iteration(b: &mut Bencher, size: i32) {
let mut map = BTreeMap::<i32, i32>::new(); let mut map = BTreeMap::<i32, i32>::new();
let mut rng = thread_rng(); let mut rng = crate::bench_rng();
for _ in 0..size { for _ in 0..size {
map.insert(rng.gen(), rng.gen()); 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) { fn bench_iteration_mut(b: &mut Bencher, size: i32) {
let mut map = BTreeMap::<i32, i32>::new(); let mut map = BTreeMap::<i32, i32>::new();
let mut rng = thread_rng(); let mut rng = crate::bench_rng();
for _ in 0..size { for _ in 0..size {
map.insert(rng.gen(), rng.gen()); map.insert(rng.gen(), rng.gen());

View File

@ -1,10 +1,10 @@
use std::collections::BTreeSet; use std::collections::BTreeSet;
use rand::{thread_rng, Rng}; use rand::Rng;
use test::Bencher; use test::Bencher;
fn random(n: usize) -> BTreeSet<usize> { fn random(n: usize) -> BTreeSet<usize> {
let mut rng = thread_rng(); let mut rng = crate::bench_rng();
let mut set = BTreeSet::new(); let mut set = BTreeSet::new();
while set.len() < n { while set.len() < n {
set.insert(rng.gen()); set.insert(rng.gen());

View File

@ -17,3 +17,11 @@ mod str;
mod string; mod string;
mod vec; mod vec;
mod vec_deque; 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)
}

View File

@ -1,8 +1,7 @@
use std::{mem, ptr}; use std::{mem, ptr};
use rand::distributions::{Alphanumeric, Standard}; use rand::distributions::{Alphanumeric, Standard};
use rand::{thread_rng, Rng, SeedableRng}; use rand::Rng;
use rand_xorshift::XorShiftRng;
use test::{black_box, Bencher}; use test::{black_box, Bencher};
#[bench] #[bench]
@ -152,7 +151,7 @@ fn zero_1kb_mut_iter(b: &mut Bencher) {
#[bench] #[bench]
fn random_inserts(b: &mut Bencher) { fn random_inserts(b: &mut Bencher) {
let mut rng = thread_rng(); let mut rng = crate::bench_rng();
b.iter(|| { b.iter(|| {
let mut v = vec![(0, 0); 30]; let mut v = vec![(0, 0); 30];
for _ in 0..100 { for _ in 0..100 {
@ -164,7 +163,7 @@ fn random_inserts(b: &mut Bencher) {
#[bench] #[bench]
fn random_removes(b: &mut Bencher) { fn random_removes(b: &mut Bencher) {
let mut rng = thread_rng(); let mut rng = crate::bench_rng();
b.iter(|| { b.iter(|| {
let mut v = vec![(0, 0); 130]; let mut v = vec![(0, 0); 130];
for _ in 0..100 { for _ in 0..100 {
@ -182,20 +181,18 @@ fn gen_descending(len: usize) -> Vec<u64> {
(0..len as u64).rev().collect() (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<u64> { fn gen_random(len: usize) -> Vec<u64> {
let mut rng = XorShiftRng::from_seed(SEED); let mut rng = crate::bench_rng();
(&mut rng).sample_iter(&Standard).take(len).collect() (&mut rng).sample_iter(&Standard).take(len).collect()
} }
fn gen_random_bytes(len: usize) -> Vec<u8> { fn gen_random_bytes(len: usize) -> Vec<u8> {
let mut rng = XorShiftRng::from_seed(SEED); let mut rng = crate::bench_rng();
(&mut rng).sample_iter(&Standard).take(len).collect() (&mut rng).sample_iter(&Standard).take(len).collect()
} }
fn gen_mostly_ascending(len: usize) -> Vec<u64> { fn gen_mostly_ascending(len: usize) -> Vec<u64> {
let mut rng = XorShiftRng::from_seed(SEED); let mut rng = crate::bench_rng();
let mut v = gen_ascending(len); let mut v = gen_ascending(len);
for _ in (0usize..).take_while(|x| x * x <= len) { for _ in (0usize..).take_while(|x| x * x <= len) {
let x = rng.gen::<usize>() % len; let x = rng.gen::<usize>() % len;
@ -206,7 +203,7 @@ fn gen_mostly_ascending(len: usize) -> Vec<u64> {
} }
fn gen_mostly_descending(len: usize) -> Vec<u64> { fn gen_mostly_descending(len: usize) -> Vec<u64> {
let mut rng = XorShiftRng::from_seed(SEED); let mut rng = crate::bench_rng();
let mut v = gen_descending(len); let mut v = gen_descending(len);
for _ in (0usize..).take_while(|x| x * x <= len) { for _ in (0usize..).take_while(|x| x * x <= len) {
let x = rng.gen::<usize>() % len; let x = rng.gen::<usize>() % len;
@ -217,7 +214,7 @@ fn gen_mostly_descending(len: usize) -> Vec<u64> {
} }
fn gen_strings(len: usize) -> Vec<String> { fn gen_strings(len: usize) -> Vec<String> {
let mut rng = XorShiftRng::from_seed(SEED); let mut rng = crate::bench_rng();
let mut v = vec![]; let mut v = vec![];
for _ in 0..len { for _ in 0..len {
let n = rng.gen::<usize>() % 20 + 1; let n = rng.gen::<usize>() % 20 + 1;
@ -227,7 +224,7 @@ fn gen_strings(len: usize) -> Vec<String> {
} }
fn gen_big_random(len: usize) -> Vec<[u64; 16]> { 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() (&mut rng).sample_iter(&Standard).map(|x| [x; 16]).take(len).collect()
} }

View File

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

View File

@ -25,6 +25,7 @@ test = true
[dev-dependencies] [dev-dependencies]
rand = "0.7" rand = "0.7"
rand_xorshift = "0.2"
[features] [features]
# Make panics and failed asserts immediately abort without formatting any message # Make panics and failed asserts immediately abort without formatting any message

View File

@ -17,3 +17,11 @@ mod ops;
mod pattern; mod pattern;
mod slice; mod slice;
mod str; 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)
}

View File

@ -17,7 +17,7 @@ macro_rules! int_log_bench {
#[bench] #[bench]
fn $random(bench: &mut Bencher) { 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. */ /* Exponentially distributed random numbers from the whole range of the type. */
let numbers: Vec<$t> = (0..256) let numbers: Vec<$t> = (0..256)
.map(|_| { .map(|_| {
@ -34,7 +34,7 @@ macro_rules! int_log_bench {
#[bench] #[bench]
fn $random_small(bench: &mut Bencher) { 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. */ /* Exponentially distributed random numbers from the range 0..256. */
let numbers: Vec<$t> = (0..256) let numbers: Vec<$t> = (0..256)
.map(|_| { .map(|_| {