about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-05-05 05:08:44 +0000
committerbors <bors@rust-lang.org>2022-05-05 05:08:44 +0000
commit12d3f107c1634ed41a800e220ccf99b665d906d8 (patch)
treec30046c7af437b6f169af2040d0573b2be0c3fae
parent7d3e03666a93bd2b0f78b3933f9305832af771a5 (diff)
parent0812759840eb9c52e646729603a207c2a0ed1a65 (diff)
downloadrust-12d3f107c1634ed41a800e220ccf99b665d906d8.tar.gz
rust-12d3f107c1634ed41a800e220ccf99b665d906d8.zip
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.
-rw-r--r--Cargo.lock1
-rw-r--r--library/alloc/benches/binary_heap.rs8
-rw-r--r--library/alloc/benches/btree/map.rs12
-rw-r--r--library/alloc/benches/btree/set.rs4
-rw-r--r--library/alloc/benches/lib.rs8
-rw-r--r--library/alloc/benches/slice.rs21
-rw-r--r--library/alloc/benches/vec.rs4
-rw-r--r--library/core/Cargo.toml1
-rw-r--r--library/core/benches/lib.rs8
-rw-r--r--library/core/benches/num/int_log/mod.rs4
10 files changed, 43 insertions, 28 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 417f3300f0b..188db89bc6c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -828,6 +828,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 491243e22c7..917e71f250e 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<u32> = (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<u32> = (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<u32> = (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 89c21929dbc..1f6b87fb0e4 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::<usize>() % 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::<usize>() % 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::<i32, i32>::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::<i32, i32>::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 07bf5093727..3f4b0e0f14a 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<usize> {
-    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 38a8f65f169..7dc0f7cebd5 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 e20c043286e..bd6f38f2f10 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<u64> {
     (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> {
-    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<u8> {
-    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<u64> {
-    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::<usize>() % len;
@@ -206,7 +203,7 @@ fn gen_mostly_ascending(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);
     for _ in (0usize..).take_while(|x| x * x <= 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> {
-    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::<usize>() % 20 + 1;
@@ -227,7 +224,7 @@ fn gen_strings(len: usize) -> Vec<String> {
 }
 
 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 333b3c20d1d..efc47327e8a 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 6a0c6cd961d..2a7df9556cf 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 f1f1ae6e463..a6c174d2fca 100644
--- a/library/core/benches/lib.rs
+++ b/library/core/benches/lib.rs
@@ -18,3 +18,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 6a219bcdd55..19864d2d467 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(|_| {