diff options
Diffstat (limited to 'rand/benches')
| -rw-r--r-- | rand/benches/bench.rs | 34 | ||||
| -rw-r--r-- | rand/benches/distributions.rs | 237 | ||||
| -rw-r--r-- | rand/benches/distributions/exponential.rs | 18 | ||||
| -rw-r--r-- | rand/benches/distributions/gamma.rs | 31 | ||||
| -rw-r--r-- | rand/benches/distributions/mod.rs | 3 | ||||
| -rw-r--r-- | rand/benches/distributions/normal.rs | 18 | ||||
| -rw-r--r-- | rand/benches/generators.rs | 197 | ||||
| -rw-r--r-- | rand/benches/misc.rs | 152 | ||||
| -rw-r--r-- | rand/benches/seq.rs | 174 | 
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); | 
