aboutsummaryrefslogtreecommitdiff
path: root/rand/benches
diff options
context:
space:
mode:
Diffstat (limited to 'rand/benches')
-rw-r--r--rand/benches/bench.rs34
-rw-r--r--rand/benches/distributions.rs237
-rw-r--r--rand/benches/distributions/exponential.rs18
-rw-r--r--rand/benches/distributions/gamma.rs31
-rw-r--r--rand/benches/distributions/mod.rs3
-rw-r--r--rand/benches/distributions/normal.rs18
-rw-r--r--rand/benches/generators.rs197
-rw-r--r--rand/benches/misc.rs152
-rw-r--r--rand/benches/seq.rs174
9 files changed, 668 insertions, 196 deletions
diff --git a/rand/benches/bench.rs b/rand/benches/bench.rs
deleted file mode 100644
index d396f25..0000000
--- a/rand/benches/bench.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-#![feature(test)]
-
-extern crate test;
-extern crate rand;
-
-const RAND_BENCH_N: u64 = 1000;
-
-mod distributions;
-
-use std::mem::size_of;
-use test::{black_box, Bencher};
-use rand::{StdRng, Rng};
-
-#[bench]
-fn rand_f32(b: &mut Bencher) {
- let mut rng = StdRng::new().unwrap();
- b.iter(|| {
- for _ in 0..RAND_BENCH_N {
- black_box(rng.next_f32());
- }
- });
- b.bytes = size_of::<f32>() as u64 * RAND_BENCH_N;
-}
-
-#[bench]
-fn rand_f64(b: &mut Bencher) {
- let mut rng = StdRng::new().unwrap();
- b.iter(|| {
- for _ in 0..RAND_BENCH_N {
- black_box(rng.next_f64());
- }
- });
- b.bytes = size_of::<f64>() as u64 * RAND_BENCH_N;
-}
diff --git a/rand/benches/distributions.rs b/rand/benches/distributions.rs
new file mode 100644
index 0000000..7ac1a6a
--- /dev/null
+++ b/rand/benches/distributions.rs
@@ -0,0 +1,237 @@
+// Copyright 2018 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(test)]
+
+extern crate test;
+extern crate rand;
+
+const RAND_BENCH_N: u64 = 1000;
+
+use std::mem::size_of;
+use test::Bencher;
+use std::time::Duration;
+
+use rand::{Rng, FromEntropy};
+use rand::rngs::SmallRng;
+use rand::distributions::*;
+
+macro_rules! distr_int {
+ ($fnn:ident, $ty:ty, $distr:expr) => {
+ #[bench]
+ fn $fnn(b: &mut Bencher) {
+ let mut rng = SmallRng::from_entropy();
+ let distr = $distr;
+
+ b.iter(|| {
+ let mut accum = 0 as $ty;
+ for _ in 0..::RAND_BENCH_N {
+ let x: $ty = distr.sample(&mut rng);
+ accum = accum.wrapping_add(x);
+ }
+ accum
+ });
+ b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N;
+ }
+ }
+}
+
+macro_rules! distr_float {
+ ($fnn:ident, $ty:ty, $distr:expr) => {
+ #[bench]
+ fn $fnn(b: &mut Bencher) {
+ let mut rng = SmallRng::from_entropy();
+ let distr = $distr;
+
+ b.iter(|| {
+ let mut accum = 0.0;
+ for _ in 0..::RAND_BENCH_N {
+ let x: $ty = distr.sample(&mut rng);
+ accum += x;
+ }
+ accum
+ });
+ b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N;
+ }
+ }
+}
+
+macro_rules! distr_duration {
+ ($fnn:ident, $distr:expr) => {
+ #[bench]
+ fn $fnn(b: &mut Bencher) {
+ let mut rng = SmallRng::from_entropy();
+ let distr = $distr;
+
+ b.iter(|| {
+ let mut accum = Duration::new(0, 0);
+ for _ in 0..::RAND_BENCH_N {
+ let x: Duration = distr.sample(&mut rng);
+ accum = accum.checked_add(x).unwrap_or(Duration::new(u64::max_value(), 999_999_999));
+ }
+ accum
+ });
+ b.bytes = size_of::<Duration>() as u64 * ::RAND_BENCH_N;
+ }
+ }
+}
+
+macro_rules! distr {
+ ($fnn:ident, $ty:ty, $distr:expr) => {
+ #[bench]
+ fn $fnn(b: &mut Bencher) {
+ let mut rng = SmallRng::from_entropy();
+ let distr = $distr;
+
+ b.iter(|| {
+ let mut accum = 0u32;
+ for _ in 0..::RAND_BENCH_N {
+ let x: $ty = distr.sample(&mut rng);
+ accum = accum.wrapping_add(x as u32);
+ }
+ accum
+ });
+ b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N;
+ }
+ }
+}
+
+// uniform
+distr_int!(distr_uniform_i8, i8, Uniform::new(20i8, 100));
+distr_int!(distr_uniform_i16, i16, Uniform::new(-500i16, 2000));
+distr_int!(distr_uniform_i32, i32, Uniform::new(-200_000_000i32, 800_000_000));
+distr_int!(distr_uniform_i64, i64, Uniform::new(3i64, 123_456_789_123));
+distr_int!(distr_uniform_i128, i128, Uniform::new(-123_456_789_123i128, 123_456_789_123_456_789));
+
+distr_float!(distr_uniform_f32, f32, Uniform::new(2.26f32, 2.319));
+distr_float!(distr_uniform_f64, f64, Uniform::new(2.26f64, 2.319));
+
+const LARGE_SEC: u64 = u64::max_value() / 1000;
+
+distr_duration!(distr_uniform_duration_largest,
+ Uniform::new_inclusive(Duration::new(0, 0), Duration::new(u64::max_value(), 999_999_999))
+);
+distr_duration!(distr_uniform_duration_large,
+ Uniform::new(Duration::new(0, 0), Duration::new(LARGE_SEC, 1_000_000_000 / 2))
+);
+distr_duration!(distr_uniform_duration_one,
+ Uniform::new(Duration::new(0, 0), Duration::new(1, 0))
+);
+distr_duration!(distr_uniform_duration_variety,
+ Uniform::new(Duration::new(10000, 423423), Duration::new(200000, 6969954))
+);
+distr_duration!(distr_uniform_duration_edge,
+ Uniform::new_inclusive(Duration::new(LARGE_SEC, 999_999_999), Duration::new(LARGE_SEC + 1, 1))
+);
+
+
+// standard
+distr_int!(distr_standard_i8, i8, Standard);
+distr_int!(distr_standard_i16, i16, Standard);
+distr_int!(distr_standard_i32, i32, Standard);
+distr_int!(distr_standard_i64, i64, Standard);
+distr_int!(distr_standard_i128, i128, Standard);
+
+distr!(distr_standard_bool, bool, Standard);
+distr!(distr_standard_alphanumeric, char, Alphanumeric);
+distr!(distr_standard_codepoint, char, Standard);
+
+distr_float!(distr_standard_f32, f32, Standard);
+distr_float!(distr_standard_f64, f64, Standard);
+distr_float!(distr_open01_f32, f32, Open01);
+distr_float!(distr_open01_f64, f64, Open01);
+distr_float!(distr_openclosed01_f32, f32, OpenClosed01);
+distr_float!(distr_openclosed01_f64, f64, OpenClosed01);
+
+// distributions
+distr_float!(distr_exp, f64, Exp::new(1.23 * 4.56));
+distr_float!(distr_normal, f64, Normal::new(-1.23, 4.56));
+distr_float!(distr_log_normal, f64, LogNormal::new(-1.23, 4.56));
+distr_float!(distr_gamma_large_shape, f64, Gamma::new(10., 1.0));
+distr_float!(distr_gamma_small_shape, f64, Gamma::new(0.1, 1.0));
+distr_float!(distr_cauchy, f64, Cauchy::new(4.2, 6.9));
+distr_int!(distr_binomial, u64, Binomial::new(20, 0.7));
+distr_int!(distr_poisson, u64, Poisson::new(4.0));
+distr!(distr_bernoulli, bool, Bernoulli::new(0.18));
+
+// Weighted
+distr_int!(distr_weighted_i8, usize, WeightedIndex::new(&[1i8, 2, 3, 4, 12, 0, 2, 1]).unwrap());
+distr_int!(distr_weighted_u32, usize, WeightedIndex::new(&[1u32, 2, 3, 4, 12, 0, 2, 1]).unwrap());
+distr_int!(distr_weighted_f64, usize, WeightedIndex::new(&[1.0f64, 0.001, 1.0/3.0, 4.01, 0.0, 3.3, 22.0, 0.001]).unwrap());
+distr_int!(distr_weighted_large_set, usize, WeightedIndex::new((0..10000).rev().chain(1..10001)).unwrap());
+
+// construct and sample from a range
+macro_rules! gen_range_int {
+ ($fnn:ident, $ty:ident, $low:expr, $high:expr) => {
+ #[bench]
+ fn $fnn(b: &mut Bencher) {
+ let mut rng = SmallRng::from_entropy();
+
+ b.iter(|| {
+ let mut high = $high;
+ let mut accum: $ty = 0;
+ for _ in 0..::RAND_BENCH_N {
+ accum = accum.wrapping_add(rng.gen_range($low, high));
+ // force recalculation of range each time
+ high = high.wrapping_add(1) & std::$ty::MAX;
+ }
+ accum
+ });
+ b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N;
+ }
+ }
+}
+
+gen_range_int!(gen_range_i8, i8, -20i8, 100);
+gen_range_int!(gen_range_i16, i16, -500i16, 2000);
+gen_range_int!(gen_range_i32, i32, -200_000_000i32, 800_000_000);
+gen_range_int!(gen_range_i64, i64, 3i64, 123_456_789_123);
+gen_range_int!(gen_range_i128, i128, -12345678901234i128, 123_456_789_123_456_789);
+
+// construct and sample from a floating-point range
+macro_rules! gen_range_float {
+ ($fnn:ident, $ty:ident, $low:expr, $high:expr) => {
+ #[bench]
+ fn $fnn(b: &mut Bencher) {
+ let mut rng = SmallRng::from_entropy();
+
+ b.iter(|| {
+ let mut high = $high;
+ let mut low = $low;
+ let mut accum: $ty = 0.0;
+ for _ in 0..::RAND_BENCH_N {
+ accum += rng.gen_range(low, high);
+ // force recalculation of range each time
+ low += 0.9;
+ high += 1.1;
+ }
+ accum
+ });
+ b.bytes = size_of::<$ty>() as u64 * ::RAND_BENCH_N;
+ }
+ }
+}
+
+gen_range_float!(gen_range_f32, f32, -20000.0f32, 100000.0);
+gen_range_float!(gen_range_f64, f64, 123.456f64, 7890.12);
+
+#[bench]
+fn dist_iter(b: &mut Bencher) {
+ let mut rng = SmallRng::from_entropy();
+ let distr = Normal::new(-2.71828, 3.14159);
+ let mut iter = distr.sample_iter(&mut rng);
+
+ b.iter(|| {
+ let mut accum = 0.0;
+ for _ in 0..::RAND_BENCH_N {
+ accum += iter.next().unwrap();
+ }
+ accum
+ });
+ b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
+}
diff --git a/rand/benches/distributions/exponential.rs b/rand/benches/distributions/exponential.rs
deleted file mode 100644
index 152615d..0000000
--- a/rand/benches/distributions/exponential.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-use std::mem::size_of;
-use test::Bencher;
-use rand;
-use rand::distributions::exponential::Exp;
-use rand::distributions::Sample;
-
-#[bench]
-fn rand_exp(b: &mut Bencher) {
- let mut rng = rand::weak_rng();
- let mut exp = Exp::new(2.71828 * 3.14159);
-
- b.iter(|| {
- for _ in 0..::RAND_BENCH_N {
- exp.sample(&mut rng);
- }
- });
- b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
-}
diff --git a/rand/benches/distributions/gamma.rs b/rand/benches/distributions/gamma.rs
deleted file mode 100644
index bf3fd36..0000000
--- a/rand/benches/distributions/gamma.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-use std::mem::size_of;
-use test::Bencher;
-use rand;
-use rand::distributions::IndependentSample;
-use rand::distributions::gamma::Gamma;
-
-#[bench]
-fn bench_gamma_large_shape(b: &mut Bencher) {
- let gamma = Gamma::new(10., 1.0);
- let mut rng = rand::weak_rng();
-
- b.iter(|| {
- for _ in 0..::RAND_BENCH_N {
- gamma.ind_sample(&mut rng);
- }
- });
- b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
-}
-
-#[bench]
-fn bench_gamma_small_shape(b: &mut Bencher) {
- let gamma = Gamma::new(0.1, 1.0);
- let mut rng = rand::weak_rng();
-
- b.iter(|| {
- for _ in 0..::RAND_BENCH_N {
- gamma.ind_sample(&mut rng);
- }
- });
- b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
-}
diff --git a/rand/benches/distributions/mod.rs b/rand/benches/distributions/mod.rs
deleted file mode 100644
index 49f6bd9..0000000
--- a/rand/benches/distributions/mod.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-mod exponential;
-mod normal;
-mod gamma;
diff --git a/rand/benches/distributions/normal.rs b/rand/benches/distributions/normal.rs
deleted file mode 100644
index 1c858b1..0000000
--- a/rand/benches/distributions/normal.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-use std::mem::size_of;
-use test::Bencher;
-use rand;
-use rand::distributions::Sample;
-use rand::distributions::normal::Normal;
-
-#[bench]
-fn rand_normal(b: &mut Bencher) {
- let mut rng = rand::weak_rng();
- let mut normal = Normal::new(-2.71828, 3.14159);
-
- b.iter(|| {
- for _ in 0..::RAND_BENCH_N {
- normal.sample(&mut rng);
- }
- });
- b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
-}
diff --git a/rand/benches/generators.rs b/rand/benches/generators.rs
index daee7c5..a12b5a6 100644
--- a/rand/benches/generators.rs
+++ b/rand/benches/generators.rs
@@ -1,7 +1,20 @@
+// Copyright 2018 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
#![feature(test)]
extern crate test;
extern crate rand;
+extern crate rand_isaac;
+extern crate rand_chacha;
+extern crate rand_hc;
+extern crate rand_pcg;
+extern crate rand_xorshift;
const RAND_BENCH_N: u64 = 1000;
const BYTES_LEN: usize = 1024;
@@ -9,31 +22,20 @@ const BYTES_LEN: usize = 1024;
use std::mem::size_of;
use test::{black_box, Bencher};
-use rand::{Rng, StdRng, OsRng, JitterRng};
-use rand::{XorShiftRng, IsaacRng, Isaac64Rng, ChaChaRng};
+use rand::prelude::*;
+use rand::rngs::adapter::ReseedingRng;
+use rand::rngs::{OsRng, JitterRng, EntropyRng};
+use rand_isaac::{IsaacRng, Isaac64Rng};
+use rand_chacha::ChaChaRng;
+use rand_hc::{Hc128Rng, Hc128Core};
+use rand_pcg::{Lcg64Xsh32, Mcg128Xsl64};
+use rand_xorshift::XorShiftRng;
macro_rules! gen_bytes {
- ($fnn:ident, $gen:ident) => {
- #[bench]
- fn $fnn(b: &mut Bencher) {
- let mut rng: $gen = OsRng::new().unwrap().gen();
- let mut buf = [0u8; BYTES_LEN];
- b.iter(|| {
- for _ in 0..RAND_BENCH_N {
- rng.fill_bytes(&mut buf);
- black_box(buf);
- }
- });
- b.bytes = BYTES_LEN as u64 * RAND_BENCH_N;
- }
- }
-}
-
-macro_rules! gen_bytes_new {
- ($fnn:ident, $gen:ident) => {
+ ($fnn:ident, $gen:expr) => {
#[bench]
fn $fnn(b: &mut Bencher) {
- let mut rng = $gen::new().unwrap();
+ let mut rng = $gen;
let mut buf = [0u8; BYTES_LEN];
b.iter(|| {
for _ in 0..RAND_BENCH_N {
@@ -46,63 +48,63 @@ macro_rules! gen_bytes_new {
}
}
-gen_bytes!(gen_bytes_xorshift, XorShiftRng);
-gen_bytes!(gen_bytes_isaac, IsaacRng);
-gen_bytes!(gen_bytes_isaac64, Isaac64Rng);
-gen_bytes!(gen_bytes_chacha, ChaChaRng);
-gen_bytes_new!(gen_bytes_std, StdRng);
-gen_bytes_new!(gen_bytes_os, OsRng);
-
+gen_bytes!(gen_bytes_xorshift, XorShiftRng::from_entropy());
+gen_bytes!(gen_bytes_lcg64_xsh32, Lcg64Xsh32::from_entropy());
+gen_bytes!(gen_bytes_mcg128_xsh64, Mcg128Xsl64::from_entropy());
+gen_bytes!(gen_bytes_chacha20, ChaChaRng::from_entropy());
+gen_bytes!(gen_bytes_hc128, Hc128Rng::from_entropy());
+gen_bytes!(gen_bytes_isaac, IsaacRng::from_entropy());
+gen_bytes!(gen_bytes_isaac64, Isaac64Rng::from_entropy());
+gen_bytes!(gen_bytes_std, StdRng::from_entropy());
+gen_bytes!(gen_bytes_small, SmallRng::from_entropy());
+gen_bytes!(gen_bytes_os, OsRng::new().unwrap());
macro_rules! gen_uint {
- ($fnn:ident, $ty:ty, $gen:ident) => {
- #[bench]
- fn $fnn(b: &mut Bencher) {
- let mut rng: $gen = OsRng::new().unwrap().gen();
- b.iter(|| {
- for _ in 0..RAND_BENCH_N {
- black_box(rng.gen::<$ty>());
- }
- });
- b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
- }
- }
-}
-
-macro_rules! gen_uint_new {
- ($fnn:ident, $ty:ty, $gen:ident) => {
+ ($fnn:ident, $ty:ty, $gen:expr) => {
#[bench]
fn $fnn(b: &mut Bencher) {
- let mut rng = $gen::new().unwrap();
+ let mut rng = $gen;
b.iter(|| {
+ let mut accum: $ty = 0;
for _ in 0..RAND_BENCH_N {
- black_box(rng.gen::<$ty>());
+ accum = accum.wrapping_add(rng.gen::<$ty>());
}
+ accum
});
b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
}
}
}
-gen_uint!(gen_u32_xorshift, u32, XorShiftRng);
-gen_uint!(gen_u32_isaac, u32, IsaacRng);
-gen_uint!(gen_u32_isaac64, u32, Isaac64Rng);
-gen_uint!(gen_u32_chacha, u32, ChaChaRng);
-gen_uint_new!(gen_u32_std, u32, StdRng);
-gen_uint_new!(gen_u32_os, u32, OsRng);
-
-gen_uint!(gen_u64_xorshift, u64, XorShiftRng);
-gen_uint!(gen_u64_isaac, u64, IsaacRng);
-gen_uint!(gen_u64_isaac64, u64, Isaac64Rng);
-gen_uint!(gen_u64_chacha, u64, ChaChaRng);
-gen_uint_new!(gen_u64_std, u64, StdRng);
-gen_uint_new!(gen_u64_os, u64, OsRng);
-
+gen_uint!(gen_u32_xorshift, u32, XorShiftRng::from_entropy());
+gen_uint!(gen_u32_lcg64_xsh32, u32, Lcg64Xsh32::from_entropy());
+gen_uint!(gen_u32_mcg128_xsh64, u32, Mcg128Xsl64::from_entropy());
+gen_uint!(gen_u32_chacha20, u32, ChaChaRng::from_entropy());
+gen_uint!(gen_u32_hc128, u32, Hc128Rng::from_entropy());
+gen_uint!(gen_u32_isaac, u32, IsaacRng::from_entropy());
+gen_uint!(gen_u32_isaac64, u32, Isaac64Rng::from_entropy());
+gen_uint!(gen_u32_std, u32, StdRng::from_entropy());
+gen_uint!(gen_u32_small, u32, SmallRng::from_entropy());
+gen_uint!(gen_u32_os, u32, OsRng::new().unwrap());
+
+gen_uint!(gen_u64_xorshift, u64, XorShiftRng::from_entropy());
+gen_uint!(gen_u64_lcg64_xsh32, u64, Lcg64Xsh32::from_entropy());
+gen_uint!(gen_u64_mcg128_xsh64, u64, Mcg128Xsl64::from_entropy());
+gen_uint!(gen_u64_chacha20, u64, ChaChaRng::from_entropy());
+gen_uint!(gen_u64_hc128, u64, Hc128Rng::from_entropy());
+gen_uint!(gen_u64_isaac, u64, IsaacRng::from_entropy());
+gen_uint!(gen_u64_isaac64, u64, Isaac64Rng::from_entropy());
+gen_uint!(gen_u64_std, u64, StdRng::from_entropy());
+gen_uint!(gen_u64_small, u64, SmallRng::from_entropy());
+gen_uint!(gen_u64_os, u64, OsRng::new().unwrap());
+
+// Do not test JitterRng like the others by running it RAND_BENCH_N times per,
+// measurement, because it is way too slow. Only run it once.
#[bench]
fn gen_u64_jitter(b: &mut Bencher) {
let mut rng = JitterRng::new().unwrap();
b.iter(|| {
- black_box(rng.gen::<u64>());
+ rng.gen::<u64>()
});
b.bytes = size_of::<u64>() as u64;
}
@@ -111,16 +113,19 @@ macro_rules! init_gen {
($fnn:ident, $gen:ident) => {
#[bench]
fn $fnn(b: &mut Bencher) {
- let mut rng: XorShiftRng = OsRng::new().unwrap().gen();
+ let mut rng = XorShiftRng::from_entropy();
b.iter(|| {
- let r2: $gen = rng.gen();
- black_box(r2);
+ let r2 = $gen::from_rng(&mut rng).unwrap();
+ r2
});
}
}
}
init_gen!(init_xorshift, XorShiftRng);
+init_gen!(init_lcg64_xsh32, Lcg64Xsh32);
+init_gen!(init_mcg128_xsh64, Mcg128Xsl64);
+init_gen!(init_hc128, Hc128Rng);
init_gen!(init_isaac, IsaacRng);
init_gen!(init_isaac64, Isaac64Rng);
init_gen!(init_chacha, ChaChaRng);
@@ -128,6 +133,68 @@ init_gen!(init_chacha, ChaChaRng);
#[bench]
fn init_jitter(b: &mut Bencher) {
b.iter(|| {
- black_box(JitterRng::new().unwrap());
+ JitterRng::new().unwrap()
+ });
+}
+
+
+const RESEEDING_THRESHOLD: u64 = 1024*1024*1024; // something high enough to get
+ // deterministic measurements
+
+#[bench]
+fn reseeding_hc128_bytes(b: &mut Bencher) {
+ let mut rng = ReseedingRng::new(Hc128Core::from_entropy(),
+ RESEEDING_THRESHOLD,
+ EntropyRng::new());
+ let mut buf = [0u8; BYTES_LEN];
+ b.iter(|| {
+ for _ in 0..RAND_BENCH_N {
+ rng.fill_bytes(&mut buf);
+ black_box(buf);
+ }
});
+ b.bytes = BYTES_LEN as u64 * RAND_BENCH_N;
+}
+
+macro_rules! reseeding_uint {
+ ($fnn:ident, $ty:ty) => {
+ #[bench]
+ fn $fnn(b: &mut Bencher) {
+ let mut rng = ReseedingRng::new(Hc128Core::from_entropy(),
+ RESEEDING_THRESHOLD,
+ EntropyRng::new());
+ b.iter(|| {
+ let mut accum: $ty = 0;
+ for _ in 0..RAND_BENCH_N {
+ accum = accum.wrapping_add(rng.gen::<$ty>());
+ }
+ accum
+ });
+ b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
+ }
+ }
+}
+
+reseeding_uint!(reseeding_hc128_u32, u32);
+reseeding_uint!(reseeding_hc128_u64, u64);
+
+
+macro_rules! threadrng_uint {
+ ($fnn:ident, $ty:ty) => {
+ #[bench]
+ fn $fnn(b: &mut Bencher) {
+ let mut rng = thread_rng();
+ b.iter(|| {
+ let mut accum: $ty = 0;
+ for _ in 0..RAND_BENCH_N {
+ accum = accum.wrapping_add(rng.gen::<$ty>());
+ }
+ accum
+ });
+ b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
+ }
+ }
}
+
+threadrng_uint!(thread_rng_u32, u32);
+threadrng_uint!(thread_rng_u64, u64);
diff --git a/rand/benches/misc.rs b/rand/benches/misc.rs
index 4251761..8fb3a83 100644
--- a/rand/benches/misc.rs
+++ b/rand/benches/misc.rs
@@ -1,62 +1,160 @@
+// Copyright 2018 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
#![feature(test)]
extern crate test;
extern crate rand;
-use test::{black_box, Bencher};
+const RAND_BENCH_N: u64 = 1000;
+
+use test::Bencher;
-use rand::{Rng, weak_rng};
-use rand::seq::*;
+use rand::prelude::*;
#[bench]
-fn misc_shuffle_100(b: &mut Bencher) {
- let mut rng = weak_rng();
- let x : &mut [usize] = &mut [1; 100];
+fn misc_gen_bool_const(b: &mut Bencher) {
+ let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap();
b.iter(|| {
- rng.shuffle(x);
- black_box(&x);
+ let mut accum = true;
+ for _ in 0..::RAND_BENCH_N {
+ accum ^= rng.gen_bool(0.18);
+ }
+ accum
})
}
#[bench]
-fn misc_sample_iter_10_of_100(b: &mut Bencher) {
- let mut rng = weak_rng();
- let x : &[usize] = &[1; 100];
+fn misc_gen_bool_var(b: &mut Bencher) {
+ let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap();
b.iter(|| {
- black_box(sample_iter(&mut rng, x, 10).unwrap_or_else(|e| e));
+ let mut accum = true;
+ let mut p = 0.18;
+ for _ in 0..::RAND_BENCH_N {
+ accum ^= rng.gen_bool(p);
+ p += 0.0001;
+ }
+ accum
})
}
#[bench]
-fn misc_sample_slice_10_of_100(b: &mut Bencher) {
- let mut rng = weak_rng();
- let x : &[usize] = &[1; 100];
+fn misc_gen_ratio_const(b: &mut Bencher) {
+ let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap();
b.iter(|| {
- black_box(sample_slice(&mut rng, x, 10));
+ let mut accum = true;
+ for _ in 0..::RAND_BENCH_N {
+ accum ^= rng.gen_ratio(2, 3);
+ }
+ accum
+ })
+}
+
+#[bench]
+fn misc_gen_ratio_var(b: &mut Bencher) {
+ let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap();
+ b.iter(|| {
+ let mut accum = true;
+ for i in 2..(::RAND_BENCH_N as u32 + 2) {
+ accum ^= rng.gen_ratio(i, i + 1);
+ }
+ accum
+ })
+}
+
+#[bench]
+fn misc_bernoulli_const(b: &mut Bencher) {
+ let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap();
+ b.iter(|| {
+ let d = rand::distributions::Bernoulli::new(0.18);
+ let mut accum = true;
+ for _ in 0..::RAND_BENCH_N {
+ accum ^= rng.sample(d);
+ }
+ accum
})
}
#[bench]
-fn misc_sample_slice_ref_10_of_100(b: &mut Bencher) {
- let mut rng = weak_rng();
- let x : &[usize] = &[1; 100];
+fn misc_bernoulli_var(b: &mut Bencher) {
+ let mut rng = StdRng::from_rng(&mut thread_rng()).unwrap();
b.iter(|| {
- black_box(sample_slice_ref(&mut rng, x, 10));
+ let mut accum = true;
+ let mut p = 0.18;
+ for _ in 0..::RAND_BENCH_N {
+ let d = rand::distributions::Bernoulli::new(p);
+ accum ^= rng.sample(d);
+ p += 0.0001;
+ }
+ accum
})
}
-macro_rules! sample_indices {
- ($name:ident, $amount:expr, $length:expr) => {
+macro_rules! sample_binomial {
+ ($name:ident, $n:expr, $p:expr) => {
#[bench]
fn $name(b: &mut Bencher) {
- let mut rng = weak_rng();
+ let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
+ let (n, p) = ($n, $p);
b.iter(|| {
- black_box(sample_indices(&mut rng, $length, $amount));
+ let d = rand::distributions::Binomial::new(n, p);
+ rng.sample(d)
})
}
}
}
-sample_indices!(misc_sample_indices_10_of_1k, 10, 1000);
-sample_indices!(misc_sample_indices_50_of_1k, 50, 1000);
-sample_indices!(misc_sample_indices_100_of_1k, 100, 1000);
+sample_binomial!(misc_binomial_1, 1, 0.9);
+sample_binomial!(misc_binomial_10, 10, 0.9);
+sample_binomial!(misc_binomial_100, 100, 0.99);
+sample_binomial!(misc_binomial_1000, 1000, 0.01);
+sample_binomial!(misc_binomial_1e12, 1000_000_000_000, 0.2);
+
+#[bench]
+fn gen_1k_iter_repeat(b: &mut Bencher) {
+ use std::iter;
+ let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
+ b.iter(|| {
+ let v: Vec<u64> = iter::repeat(()).map(|()| rng.gen()).take(128).collect();
+ v
+ });
+ b.bytes = 1024;
+}
+
+#[bench]
+fn gen_1k_sample_iter(b: &mut Bencher) {
+ use rand::distributions::{Distribution, Standard};
+ let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
+ b.iter(|| {
+ let v: Vec<u64> = Standard.sample_iter(&mut rng).take(128).collect();
+ v
+ });
+ b.bytes = 1024;
+}
+
+#[bench]
+fn gen_1k_gen_array(b: &mut Bencher) {
+ let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
+ b.iter(|| {
+ // max supported array length is 32!
+ let v: [[u64; 32]; 4] = rng.gen();
+ v
+ });
+ b.bytes = 1024;
+}
+
+#[bench]
+fn gen_1k_fill(b: &mut Bencher) {
+ let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
+ let mut buf = [0u64; 128];
+ b.iter(|| {
+ rng.fill(&mut buf[..]);
+ buf
+ });
+ b.bytes = 1024;
+}
diff --git a/rand/benches/seq.rs b/rand/benches/seq.rs
new file mode 100644
index 0000000..0ca3398
--- /dev/null
+++ b/rand/benches/seq.rs
@@ -0,0 +1,174 @@
+// Copyright 2018 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(test)]
+#![allow(non_snake_case)]
+
+extern crate test;
+extern crate rand;
+
+use test::Bencher;
+
+use rand::prelude::*;
+use rand::seq::*;
+use std::mem::size_of;
+
+const RAND_BENCH_N: u64 = 1000;
+
+#[bench]
+fn seq_shuffle_100(b: &mut Bencher) {
+ let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
+ let x : &mut [usize] = &mut [1; 100];
+ b.iter(|| {
+ x.shuffle(&mut rng);
+ x[0]
+ })
+}
+
+#[bench]
+fn seq_slice_choose_1_of_1000(b: &mut Bencher) {
+ let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
+ let x : &mut [usize] = &mut [1; 1000];
+ for i in 0..1000 {
+ x[i] = i;
+ }
+ b.iter(|| {
+ let mut s = 0;
+ for _ in 0..RAND_BENCH_N {
+ s += x.choose(&mut rng).unwrap();
+ }
+ s
+ });
+ b.bytes = size_of::<usize>() as u64 * ::RAND_BENCH_N;
+}
+
+macro_rules! seq_slice_choose_multiple {
+ ($name:ident, $amount:expr, $length:expr) => {
+ #[bench]
+ fn $name(b: &mut Bencher) {
+ let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
+ let x : &[i32] = &[$amount; $length];
+ let mut result = [0i32; $amount];
+ b.iter(|| {
+ // Collect full result to prevent unwanted shortcuts getting
+ // first element (in case sample_indices returns an iterator).
+ for (slot, sample) in result.iter_mut().zip(
+ x.choose_multiple(&mut rng, $amount)) {
+ *slot = *sample;
+ }
+ result[$amount-1]
+ })
+ }
+ }
+}
+
+seq_slice_choose_multiple!(seq_slice_choose_multiple_1_of_1000, 1, 1000);
+seq_slice_choose_multiple!(seq_slice_choose_multiple_950_of_1000, 950, 1000);
+seq_slice_choose_multiple!(seq_slice_choose_multiple_10_of_100, 10, 100);
+seq_slice_choose_multiple!(seq_slice_choose_multiple_90_of_100, 90, 100);
+
+#[bench]
+fn seq_iter_choose_from_1000(b: &mut Bencher) {
+ let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
+ let x : &mut [usize] = &mut [1; 1000];
+ for i in 0..1000 {
+ x[i] = i;
+ }
+ b.iter(|| {
+ let mut s = 0;
+ for _ in 0..RAND_BENCH_N {
+ s += x.iter().choose(&mut rng).unwrap();
+ }
+ s
+ });
+ b.bytes = size_of::<usize>() as u64 * ::RAND_BENCH_N;
+}
+
+#[derive(Clone)]
+struct UnhintedIterator<I: Iterator + Clone> {
+ iter: I,
+}
+impl<I: Iterator + Clone> Iterator for UnhintedIterator<I> {
+ type Item = I::Item;
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next()
+ }
+}
+
+#[derive(Clone)]
+struct WindowHintedIterator<I: ExactSizeIterator + Iterator + Clone> {
+ iter: I,
+ window_size: usize,
+}
+impl<I: ExactSizeIterator + Iterator + Clone> Iterator for WindowHintedIterator<I> {
+ type Item = I::Item;
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next()
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (std::cmp::min(self.iter.len(), self.window_size), None)
+ }
+}
+
+#[bench]
+fn seq_iter_unhinted_choose_from_1000(b: &mut Bencher) {
+ let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
+ let x : &[usize] = &[1; 1000];
+ b.iter(|| {
+ UnhintedIterator { iter: x.iter() }.choose(&mut rng).unwrap()
+ })
+}
+
+#[bench]
+fn seq_iter_window_hinted_choose_from_1000(b: &mut Bencher) {
+ let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
+ let x : &[usize] = &[1; 1000];
+ b.iter(|| {
+ WindowHintedIterator { iter: x.iter(), window_size: 7 }.choose(&mut rng)
+ })
+}
+
+#[bench]
+fn seq_iter_choose_multiple_10_of_100(b: &mut Bencher) {
+ let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
+ let x : &[usize] = &[1; 100];
+ b.iter(|| {
+ x.iter().cloned().choose_multiple(&mut rng, 10)
+ })
+}
+
+#[bench]
+fn seq_iter_choose_multiple_fill_10_of_100(b: &mut Bencher) {
+ let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
+ let x : &[usize] = &[1; 100];
+ let mut buf = [0; 10];
+ b.iter(|| {
+ x.iter().cloned().choose_multiple_fill(&mut rng, &mut buf)
+ })
+}
+
+macro_rules! sample_indices {
+ ($name:ident, $fn:ident, $amount:expr, $length:expr) => {
+ #[bench]
+ fn $name(b: &mut Bencher) {
+ let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
+ b.iter(|| {
+ index::$fn(&mut rng, $length, $amount)
+ })
+ }
+ }
+}
+
+sample_indices!(misc_sample_indices_1_of_1k, sample, 1, 1000);
+sample_indices!(misc_sample_indices_10_of_1k, sample, 10, 1000);
+sample_indices!(misc_sample_indices_100_of_1k, sample, 100, 1000);
+sample_indices!(misc_sample_indices_100_of_1M, sample, 100, 1000_000);
+sample_indices!(misc_sample_indices_100_of_1G, sample, 100, 1000_000_000);
+sample_indices!(misc_sample_indices_200_of_1G, sample, 200, 1000_000_000);
+sample_indices!(misc_sample_indices_400_of_1G, sample, 400, 1000_000_000);
+sample_indices!(misc_sample_indices_600_of_1G, sample, 600, 1000_000_000);