Migrate remaining benchmarks to Criterion (#1490)
Translate everything still using the old test harness to Criterion.
This commit is contained in:
parent
79f1b0ffdb
commit
9e030aa221
2
.github/workflows/benches.yml
vendored
2
.github/workflows/benches.yml
vendored
@ -23,4 +23,4 @@ jobs:
|
|||||||
- name: Clippy
|
- name: Clippy
|
||||||
run: cargo clippy --all-targets -- -D warnings
|
run: cargo clippy --all-targets -- -D warnings
|
||||||
- name: Build
|
- name: Build
|
||||||
run: RUSTFLAGS=-Dwarnings cargo build --all-targets
|
run: RUSTFLAGS=-Dwarnings cargo test --benches
|
||||||
|
@ -13,7 +13,7 @@ You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.
|
|||||||
- Add `IndexedRandom::choose_multiple_array`, `index::sample_array` (#1453, #1469)
|
- Add `IndexedRandom::choose_multiple_array`, `index::sample_array` (#1453, #1469)
|
||||||
- Bump the MSRV to 1.61.0
|
- Bump the MSRV to 1.61.0
|
||||||
- Rename `Rng::gen` to `Rng::random` to avoid conflict with the new `gen` keyword in Rust 2024 (#1435)
|
- Rename `Rng::gen` to `Rng::random` to avoid conflict with the new `gen` keyword in Rust 2024 (#1435)
|
||||||
- Move all benchmarks to new `benches` crate (#1439)
|
- Move all benchmarks to new `benches` crate (#1439) and migrate to Criterion (#1490)
|
||||||
- Annotate panicking methods with `#[track_caller]` (#1442, #1447)
|
- Annotate panicking methods with `#[track_caller]` (#1442, #1447)
|
||||||
- Enable feature `small_rng` by default (#1455)
|
- Enable feature `small_rng` by default (#1455)
|
||||||
- Allow `UniformFloat::new` samples and `UniformFloat::sample_single` to yield `high` (#1462)
|
- Allow `UniformFloat::new` samples and `UniformFloat::sample_single` to yield `high` (#1462)
|
||||||
|
@ -15,26 +15,41 @@ criterion = "0.5"
|
|||||||
criterion-cycles-per-byte = "0.6"
|
criterion-cycles-per-byte = "0.6"
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "distr"
|
name = "array"
|
||||||
path = "src/distr.rs"
|
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "uniform"
|
name = "bool"
|
||||||
path = "src/uniform.rs"
|
harness = false
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "distr"
|
||||||
|
harness = false
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "generators"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "seq_choose"
|
name = "seq_choose"
|
||||||
path = "src/seq_choose.rs"
|
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "shuffle"
|
name = "shuffle"
|
||||||
path = "src/shuffle.rs"
|
harness = false
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "standard"
|
||||||
|
harness = false
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "uniform"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "uniform_float"
|
name = "uniform_float"
|
||||||
path = "src/uniform_float.rs"
|
harness = false
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "weighted"
|
||||||
harness = false
|
harness = false
|
||||||
|
94
benches/benches/array.rs
Normal file
94
benches/benches/array.rs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
// Copyright 2018-2023 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.
|
||||||
|
|
||||||
|
//! Generating/filling arrays and iterators of output
|
||||||
|
|
||||||
|
use criterion::{criterion_group, criterion_main, Criterion};
|
||||||
|
use rand::distr::Standard;
|
||||||
|
use rand::prelude::*;
|
||||||
|
use rand_pcg::Pcg64Mcg;
|
||||||
|
|
||||||
|
criterion_group!(
|
||||||
|
name = benches;
|
||||||
|
config = Criterion::default();
|
||||||
|
targets = bench
|
||||||
|
);
|
||||||
|
criterion_main!(benches);
|
||||||
|
|
||||||
|
pub fn bench(c: &mut Criterion) {
|
||||||
|
let mut g = c.benchmark_group("gen_1kb");
|
||||||
|
g.throughput(criterion::Throughput::Bytes(1024));
|
||||||
|
|
||||||
|
g.bench_function("u16_iter_repeat", |b| {
|
||||||
|
use core::iter;
|
||||||
|
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
||||||
|
b.iter(|| {
|
||||||
|
let v: Vec<u16> = iter::repeat(()).map(|()| rng.random()).take(512).collect();
|
||||||
|
v
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
g.bench_function("u16_sample_iter", |b| {
|
||||||
|
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
||||||
|
b.iter(|| {
|
||||||
|
let v: Vec<u16> = Standard.sample_iter(&mut rng).take(512).collect();
|
||||||
|
v
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
g.bench_function("u16_gen_array", |b| {
|
||||||
|
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
||||||
|
b.iter(|| {
|
||||||
|
let v: [u16; 512] = rng.random();
|
||||||
|
v
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
g.bench_function("u16_fill", |b| {
|
||||||
|
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
||||||
|
let mut buf = [0u16; 512];
|
||||||
|
b.iter(|| {
|
||||||
|
rng.fill(&mut buf[..]);
|
||||||
|
buf
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
g.bench_function("u64_iter_repeat", |b| {
|
||||||
|
use core::iter;
|
||||||
|
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
||||||
|
b.iter(|| {
|
||||||
|
let v: Vec<u64> = iter::repeat(()).map(|()| rng.random()).take(128).collect();
|
||||||
|
v
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
g.bench_function("u64_sample_iter", |b| {
|
||||||
|
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
||||||
|
b.iter(|| {
|
||||||
|
let v: Vec<u64> = Standard.sample_iter(&mut rng).take(128).collect();
|
||||||
|
v
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
g.bench_function("u64_gen_array", |b| {
|
||||||
|
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
||||||
|
b.iter(|| {
|
||||||
|
let v: [u64; 128] = rng.random();
|
||||||
|
v
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
g.bench_function("u64_fill", |b| {
|
||||||
|
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
||||||
|
let mut buf = [0u64; 128];
|
||||||
|
b.iter(|| {
|
||||||
|
rng.fill(&mut buf[..]);
|
||||||
|
buf
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
@ -1,440 +0,0 @@
|
|||||||
// 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(custom_inner_attributes)]
|
|
||||||
#![feature(test)]
|
|
||||||
|
|
||||||
// Rustfmt splits macro invocations to shorten lines; in this case longer-lines are more readable
|
|
||||||
#![rustfmt::skip]
|
|
||||||
|
|
||||||
extern crate test;
|
|
||||||
|
|
||||||
const RAND_BENCH_N: u64 = 1000;
|
|
||||||
|
|
||||||
use rand::distr::{Alphanumeric, Open01, OpenClosed01, Standard, Uniform};
|
|
||||||
use rand::distr::uniform::{UniformInt, UniformSampler};
|
|
||||||
use core::mem::size_of;
|
|
||||||
use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8};
|
|
||||||
use core::time::Duration;
|
|
||||||
use test::{Bencher, black_box};
|
|
||||||
|
|
||||||
use rand::prelude::*;
|
|
||||||
|
|
||||||
// At this time, distributions are optimised for 64-bit platforms.
|
|
||||||
use rand_pcg::Pcg64Mcg;
|
|
||||||
|
|
||||||
macro_rules! distr_int {
|
|
||||||
($fnn:ident, $ty:ty, $distr:expr) => {
|
|
||||||
#[bench]
|
|
||||||
fn $fnn(b: &mut Bencher) {
|
|
||||||
let mut rng = Pcg64Mcg::from_os_rng();
|
|
||||||
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_nz_int {
|
|
||||||
($fnn:ident, $tynz:ty, $ty:ty, $distr:expr) => {
|
|
||||||
#[bench]
|
|
||||||
fn $fnn(b: &mut Bencher) {
|
|
||||||
let mut rng = Pcg64Mcg::from_os_rng();
|
|
||||||
let distr = $distr;
|
|
||||||
|
|
||||||
b.iter(|| {
|
|
||||||
let mut accum = 0 as $ty;
|
|
||||||
for _ in 0..RAND_BENCH_N {
|
|
||||||
let x: $tynz = distr.sample(&mut rng);
|
|
||||||
accum = accum.wrapping_add(x.get());
|
|
||||||
}
|
|
||||||
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 = Pcg64Mcg::from_os_rng();
|
|
||||||
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 = Pcg64Mcg::from_os_rng();
|
|
||||||
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, 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 = Pcg64Mcg::from_os_rng();
|
|
||||||
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).unwrap());
|
|
||||||
distr_int!(distr_uniform_i16, i16, Uniform::new(-500i16, 2000).unwrap());
|
|
||||||
distr_int!(distr_uniform_i32, i32, Uniform::new(-200_000_000i32, 800_000_000).unwrap());
|
|
||||||
distr_int!(distr_uniform_i64, i64, Uniform::new(3i64, 123_456_789_123).unwrap());
|
|
||||||
distr_int!(distr_uniform_i128, i128, Uniform::new(-123_456_789_123i128, 123_456_789_123_456_789).unwrap());
|
|
||||||
distr_int!(distr_uniform_usize16, usize, Uniform::new(0usize, 0xb9d7).unwrap());
|
|
||||||
distr_int!(distr_uniform_usize32, usize, Uniform::new(0usize, 0x548c0f43).unwrap());
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
|
||||||
distr_int!(distr_uniform_usize64, usize, Uniform::new(0usize, 0x3a42714f2bf927a8).unwrap());
|
|
||||||
distr_int!(distr_uniform_isize, isize, Uniform::new(-1060478432isize, 1858574057).unwrap());
|
|
||||||
|
|
||||||
distr_float!(distr_uniform_f32, f32, Uniform::new(2.26f32, 2.319).unwrap());
|
|
||||||
distr_float!(distr_uniform_f64, f64, Uniform::new(2.26f64, 2.319).unwrap());
|
|
||||||
|
|
||||||
const LARGE_SEC: u64 = u64::MAX / 1000;
|
|
||||||
|
|
||||||
distr_duration!(distr_uniform_duration_largest,
|
|
||||||
Uniform::new_inclusive(Duration::new(0, 0), Duration::new(u64::MAX, 999_999_999)).unwrap()
|
|
||||||
);
|
|
||||||
distr_duration!(distr_uniform_duration_large,
|
|
||||||
Uniform::new(Duration::new(0, 0), Duration::new(LARGE_SEC, 1_000_000_000 / 2)).unwrap()
|
|
||||||
);
|
|
||||||
distr_duration!(distr_uniform_duration_one,
|
|
||||||
Uniform::new(Duration::new(0, 0), Duration::new(1, 0)).unwrap()
|
|
||||||
);
|
|
||||||
distr_duration!(distr_uniform_duration_variety,
|
|
||||||
Uniform::new(Duration::new(10000, 423423), Duration::new(200000, 6969954)).unwrap()
|
|
||||||
);
|
|
||||||
distr_duration!(distr_uniform_duration_edge,
|
|
||||||
Uniform::new_inclusive(Duration::new(LARGE_SEC, 999_999_999), Duration::new(LARGE_SEC + 1, 1)).unwrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
// 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_nz_int!(distr_standard_nz8, NonZeroU8, u8, Standard);
|
|
||||||
distr_nz_int!(distr_standard_nz16, NonZeroU16, u16, Standard);
|
|
||||||
distr_nz_int!(distr_standard_nz32, NonZeroU32, u32, Standard);
|
|
||||||
distr_nz_int!(distr_standard_nz64, NonZeroU64, u64, Standard);
|
|
||||||
distr_nz_int!(distr_standard_nz128, NonZeroU128, u128, Standard);
|
|
||||||
|
|
||||||
distr!(distr_standard_bool, bool, Standard);
|
|
||||||
distr!(distr_standard_alphanumeric, u8, 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);
|
|
||||||
|
|
||||||
// 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 = Pcg64Mcg::from_os_rng();
|
|
||||||
|
|
||||||
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) & $ty::MAX;
|
|
||||||
}
|
|
||||||
accum
|
|
||||||
});
|
|
||||||
b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Algorithms such as Fisher–Yates shuffle often require uniform values from an
|
|
||||||
// incrementing range 0..n. We use -1..n here to prevent wrapping in the test
|
|
||||||
// from generating a 0-sized range.
|
|
||||||
gen_range_int!(gen_range_i8_low, i8, -1i8, 0);
|
|
||||||
gen_range_int!(gen_range_i16_low, i16, -1i16, 0);
|
|
||||||
gen_range_int!(gen_range_i32_low, i32, -1i32, 0);
|
|
||||||
gen_range_int!(gen_range_i64_low, i64, -1i64, 0);
|
|
||||||
gen_range_int!(gen_range_i128_low, i128, -1i128, 0);
|
|
||||||
|
|
||||||
// These were the initially tested ranges. They are likely to see fewer
|
|
||||||
// rejections than the low tests.
|
|
||||||
gen_range_int!(gen_range_i8_high, i8, -20i8, 100);
|
|
||||||
gen_range_int!(gen_range_i16_high, i16, -500i16, 2000);
|
|
||||||
gen_range_int!(gen_range_i32_high, i32, -200_000_000i32, 800_000_000);
|
|
||||||
gen_range_int!(gen_range_i64_high, i64, 3i64, 123_456_789_123);
|
|
||||||
gen_range_int!(gen_range_i128_high, 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 = Pcg64Mcg::from_os_rng();
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
// In src/distr/uniform.rs, we say:
|
|
||||||
// Implementation of [`uniform_single`] is optional, and is only useful when
|
|
||||||
// the implementation can be faster than `Self::new(low, high).sample(rng)`.
|
|
||||||
|
|
||||||
// `UniformSampler::uniform_single` compromises on the rejection range to be
|
|
||||||
// faster. This benchmark demonstrates both the speed gain of doing this, and
|
|
||||||
// the worst case behavior.
|
|
||||||
|
|
||||||
/// Sample random values from a pre-existing distribution. This uses the
|
|
||||||
/// half open `new` to be equivalent to the behavior of `uniform_single`.
|
|
||||||
macro_rules! uniform_sample {
|
|
||||||
($fnn:ident, $type:ident, $low:expr, $high:expr, $count:expr) => {
|
|
||||||
#[bench]
|
|
||||||
fn $fnn(b: &mut Bencher) {
|
|
||||||
let mut rng = Pcg64Mcg::from_os_rng();
|
|
||||||
let low = black_box($low);
|
|
||||||
let high = black_box($high);
|
|
||||||
b.iter(|| {
|
|
||||||
for _ in 0..10 {
|
|
||||||
let dist = UniformInt::<$type>::new(low, high).unwrap();
|
|
||||||
for _ in 0..$count {
|
|
||||||
black_box(dist.sample(&mut rng));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! uniform_inclusive {
|
|
||||||
($fnn:ident, $type:ident, $low:expr, $high:expr, $count:expr) => {
|
|
||||||
#[bench]
|
|
||||||
fn $fnn(b: &mut Bencher) {
|
|
||||||
let mut rng = Pcg64Mcg::from_os_rng();
|
|
||||||
let low = black_box($low);
|
|
||||||
let high = black_box($high);
|
|
||||||
b.iter(|| {
|
|
||||||
for _ in 0..10 {
|
|
||||||
let dist = UniformInt::<$type>::new_inclusive(low, high).unwrap();
|
|
||||||
for _ in 0..$count {
|
|
||||||
black_box(dist.sample(&mut rng));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Use `uniform_single` to create a one-off random value
|
|
||||||
macro_rules! uniform_single {
|
|
||||||
($fnn:ident, $type:ident, $low:expr, $high:expr, $count:expr) => {
|
|
||||||
#[bench]
|
|
||||||
fn $fnn(b: &mut Bencher) {
|
|
||||||
let mut rng = Pcg64Mcg::from_os_rng();
|
|
||||||
let low = black_box($low);
|
|
||||||
let high = black_box($high);
|
|
||||||
b.iter(|| {
|
|
||||||
for _ in 0..(10 * $count) {
|
|
||||||
black_box(UniformInt::<$type>::sample_single(low, high, &mut rng).unwrap());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Benchmark:
|
|
||||||
// n: can use the full generated range
|
|
||||||
// (n-1): only the max value is rejected: expect this to be fast
|
|
||||||
// n/2+1: almost half of the values are rejected, and we can do no better
|
|
||||||
// n/2: approximation rejects half the values but powers of 2 could have no rejection
|
|
||||||
// n/2-1: only a few values are rejected: expect this to be fast
|
|
||||||
// 6: approximation rejects 25% of values but could be faster. However modulo by
|
|
||||||
// low numbers is typically more expensive
|
|
||||||
|
|
||||||
// With the use of u32 as the minimum generated width, the worst-case u16 range
|
|
||||||
// (32769) will only reject 32769 / 4294967296 samples.
|
|
||||||
const HALF_16_BIT_UNSIGNED: u16 = 1 << 15;
|
|
||||||
|
|
||||||
uniform_sample!(uniform_u16x1_allm1_new, u16, 0, u16::MAX, 1);
|
|
||||||
uniform_sample!(uniform_u16x1_halfp1_new, u16, 0, HALF_16_BIT_UNSIGNED + 1, 1);
|
|
||||||
uniform_sample!(uniform_u16x1_half_new, u16, 0, HALF_16_BIT_UNSIGNED, 1);
|
|
||||||
uniform_sample!(uniform_u16x1_halfm1_new, u16, 0, HALF_16_BIT_UNSIGNED - 1, 1);
|
|
||||||
uniform_sample!(uniform_u16x1_6_new, u16, 0, 6u16, 1);
|
|
||||||
|
|
||||||
uniform_single!(uniform_u16x1_allm1_single, u16, 0, u16::MAX, 1);
|
|
||||||
uniform_single!(uniform_u16x1_halfp1_single, u16, 0, HALF_16_BIT_UNSIGNED + 1, 1);
|
|
||||||
uniform_single!(uniform_u16x1_half_single, u16, 0, HALF_16_BIT_UNSIGNED, 1);
|
|
||||||
uniform_single!(uniform_u16x1_halfm1_single, u16, 0, HALF_16_BIT_UNSIGNED - 1, 1);
|
|
||||||
uniform_single!(uniform_u16x1_6_single, u16, 0, 6u16, 1);
|
|
||||||
|
|
||||||
uniform_inclusive!(uniform_u16x10_all_new_inclusive, u16, 0, u16::MAX, 10);
|
|
||||||
uniform_sample!(uniform_u16x10_allm1_new, u16, 0, u16::MAX, 10);
|
|
||||||
uniform_sample!(uniform_u16x10_halfp1_new, u16, 0, HALF_16_BIT_UNSIGNED + 1, 10);
|
|
||||||
uniform_sample!(uniform_u16x10_half_new, u16, 0, HALF_16_BIT_UNSIGNED, 10);
|
|
||||||
uniform_sample!(uniform_u16x10_halfm1_new, u16, 0, HALF_16_BIT_UNSIGNED - 1, 10);
|
|
||||||
uniform_sample!(uniform_u16x10_6_new, u16, 0, 6u16, 10);
|
|
||||||
|
|
||||||
uniform_single!(uniform_u16x10_allm1_single, u16, 0, u16::MAX, 10);
|
|
||||||
uniform_single!(uniform_u16x10_halfp1_single, u16, 0, HALF_16_BIT_UNSIGNED + 1, 10);
|
|
||||||
uniform_single!(uniform_u16x10_half_single, u16, 0, HALF_16_BIT_UNSIGNED, 10);
|
|
||||||
uniform_single!(uniform_u16x10_halfm1_single, u16, 0, HALF_16_BIT_UNSIGNED - 1, 10);
|
|
||||||
uniform_single!(uniform_u16x10_6_single, u16, 0, 6u16, 10);
|
|
||||||
|
|
||||||
|
|
||||||
const HALF_32_BIT_UNSIGNED: u32 = 1 << 31;
|
|
||||||
|
|
||||||
uniform_sample!(uniform_u32x1_allm1_new, u32, 0, u32::MAX, 1);
|
|
||||||
uniform_sample!(uniform_u32x1_halfp1_new, u32, 0, HALF_32_BIT_UNSIGNED + 1, 1);
|
|
||||||
uniform_sample!(uniform_u32x1_half_new, u32, 0, HALF_32_BIT_UNSIGNED, 1);
|
|
||||||
uniform_sample!(uniform_u32x1_halfm1_new, u32, 0, HALF_32_BIT_UNSIGNED - 1, 1);
|
|
||||||
uniform_sample!(uniform_u32x1_6_new, u32, 0, 6u32, 1);
|
|
||||||
|
|
||||||
uniform_single!(uniform_u32x1_allm1_single, u32, 0, u32::MAX, 1);
|
|
||||||
uniform_single!(uniform_u32x1_halfp1_single, u32, 0, HALF_32_BIT_UNSIGNED + 1, 1);
|
|
||||||
uniform_single!(uniform_u32x1_half_single, u32, 0, HALF_32_BIT_UNSIGNED, 1);
|
|
||||||
uniform_single!(uniform_u32x1_halfm1_single, u32, 0, HALF_32_BIT_UNSIGNED - 1, 1);
|
|
||||||
uniform_single!(uniform_u32x1_6_single, u32, 0, 6u32, 1);
|
|
||||||
|
|
||||||
uniform_inclusive!(uniform_u32x10_all_new_inclusive, u32, 0, u32::MAX, 10);
|
|
||||||
uniform_sample!(uniform_u32x10_allm1_new, u32, 0, u32::MAX, 10);
|
|
||||||
uniform_sample!(uniform_u32x10_halfp1_new, u32, 0, HALF_32_BIT_UNSIGNED + 1, 10);
|
|
||||||
uniform_sample!(uniform_u32x10_half_new, u32, 0, HALF_32_BIT_UNSIGNED, 10);
|
|
||||||
uniform_sample!(uniform_u32x10_halfm1_new, u32, 0, HALF_32_BIT_UNSIGNED - 1, 10);
|
|
||||||
uniform_sample!(uniform_u32x10_6_new, u32, 0, 6u32, 10);
|
|
||||||
|
|
||||||
uniform_single!(uniform_u32x10_allm1_single, u32, 0, u32::MAX, 10);
|
|
||||||
uniform_single!(uniform_u32x10_halfp1_single, u32, 0, HALF_32_BIT_UNSIGNED + 1, 10);
|
|
||||||
uniform_single!(uniform_u32x10_half_single, u32, 0, HALF_32_BIT_UNSIGNED, 10);
|
|
||||||
uniform_single!(uniform_u32x10_halfm1_single, u32, 0, HALF_32_BIT_UNSIGNED - 1, 10);
|
|
||||||
uniform_single!(uniform_u32x10_6_single, u32, 0, 6u32, 10);
|
|
||||||
|
|
||||||
const HALF_64_BIT_UNSIGNED: u64 = 1 << 63;
|
|
||||||
|
|
||||||
uniform_sample!(uniform_u64x1_allm1_new, u64, 0, u64::MAX, 1);
|
|
||||||
uniform_sample!(uniform_u64x1_halfp1_new, u64, 0, HALF_64_BIT_UNSIGNED + 1, 1);
|
|
||||||
uniform_sample!(uniform_u64x1_half_new, u64, 0, HALF_64_BIT_UNSIGNED, 1);
|
|
||||||
uniform_sample!(uniform_u64x1_halfm1_new, u64, 0, HALF_64_BIT_UNSIGNED - 1, 1);
|
|
||||||
uniform_sample!(uniform_u64x1_6_new, u64, 0, 6u64, 1);
|
|
||||||
|
|
||||||
uniform_single!(uniform_u64x1_allm1_single, u64, 0, u64::MAX, 1);
|
|
||||||
uniform_single!(uniform_u64x1_halfp1_single, u64, 0, HALF_64_BIT_UNSIGNED + 1, 1);
|
|
||||||
uniform_single!(uniform_u64x1_half_single, u64, 0, HALF_64_BIT_UNSIGNED, 1);
|
|
||||||
uniform_single!(uniform_u64x1_halfm1_single, u64, 0, HALF_64_BIT_UNSIGNED - 1, 1);
|
|
||||||
uniform_single!(uniform_u64x1_6_single, u64, 0, 6u64, 1);
|
|
||||||
|
|
||||||
uniform_inclusive!(uniform_u64x10_all_new_inclusive, u64, 0, u64::MAX, 10);
|
|
||||||
uniform_sample!(uniform_u64x10_allm1_new, u64, 0, u64::MAX, 10);
|
|
||||||
uniform_sample!(uniform_u64x10_halfp1_new, u64, 0, HALF_64_BIT_UNSIGNED + 1, 10);
|
|
||||||
uniform_sample!(uniform_u64x10_half_new, u64, 0, HALF_64_BIT_UNSIGNED, 10);
|
|
||||||
uniform_sample!(uniform_u64x10_halfm1_new, u64, 0, HALF_64_BIT_UNSIGNED - 1, 10);
|
|
||||||
uniform_sample!(uniform_u64x10_6_new, u64, 0, 6u64, 10);
|
|
||||||
|
|
||||||
uniform_single!(uniform_u64x10_allm1_single, u64, 0, u64::MAX, 10);
|
|
||||||
uniform_single!(uniform_u64x10_halfp1_single, u64, 0, HALF_64_BIT_UNSIGNED + 1, 10);
|
|
||||||
uniform_single!(uniform_u64x10_half_single, u64, 0, HALF_64_BIT_UNSIGNED, 10);
|
|
||||||
uniform_single!(uniform_u64x10_halfm1_single, u64, 0, HALF_64_BIT_UNSIGNED - 1, 10);
|
|
||||||
uniform_single!(uniform_u64x10_6_single, u64, 0, 6u64, 10);
|
|
||||||
|
|
||||||
const HALF_128_BIT_UNSIGNED: u128 = 1 << 127;
|
|
||||||
|
|
||||||
uniform_sample!(uniform_u128x1_allm1_new, u128, 0, u128::MAX, 1);
|
|
||||||
uniform_sample!(uniform_u128x1_halfp1_new, u128, 0, HALF_128_BIT_UNSIGNED + 1, 1);
|
|
||||||
uniform_sample!(uniform_u128x1_half_new, u128, 0, HALF_128_BIT_UNSIGNED, 1);
|
|
||||||
uniform_sample!(uniform_u128x1_halfm1_new, u128, 0, HALF_128_BIT_UNSIGNED - 1, 1);
|
|
||||||
uniform_sample!(uniform_u128x1_6_new, u128, 0, 6u128, 1);
|
|
||||||
|
|
||||||
uniform_single!(uniform_u128x1_allm1_single, u128, 0, u128::MAX, 1);
|
|
||||||
uniform_single!(uniform_u128x1_halfp1_single, u128, 0, HALF_128_BIT_UNSIGNED + 1, 1);
|
|
||||||
uniform_single!(uniform_u128x1_half_single, u128, 0, HALF_128_BIT_UNSIGNED, 1);
|
|
||||||
uniform_single!(uniform_u128x1_halfm1_single, u128, 0, HALF_128_BIT_UNSIGNED - 1, 1);
|
|
||||||
uniform_single!(uniform_u128x1_6_single, u128, 0, 6u128, 1);
|
|
||||||
|
|
||||||
uniform_inclusive!(uniform_u128x10_all_new_inclusive, u128, 0, u128::MAX, 10);
|
|
||||||
uniform_sample!(uniform_u128x10_allm1_new, u128, 0, u128::MAX, 10);
|
|
||||||
uniform_sample!(uniform_u128x10_halfp1_new, u128, 0, HALF_128_BIT_UNSIGNED + 1, 10);
|
|
||||||
uniform_sample!(uniform_u128x10_half_new, u128, 0, HALF_128_BIT_UNSIGNED, 10);
|
|
||||||
uniform_sample!(uniform_u128x10_halfm1_new, u128, 0, HALF_128_BIT_UNSIGNED - 1, 10);
|
|
||||||
uniform_sample!(uniform_u128x10_6_new, u128, 0, 6u128, 10);
|
|
||||||
|
|
||||||
uniform_single!(uniform_u128x10_allm1_single, u128, 0, u128::MAX, 10);
|
|
||||||
uniform_single!(uniform_u128x10_halfp1_single, u128, 0, HALF_128_BIT_UNSIGNED + 1, 10);
|
|
||||||
uniform_single!(uniform_u128x10_half_single, u128, 0, HALF_128_BIT_UNSIGNED, 10);
|
|
||||||
uniform_single!(uniform_u128x10_halfm1_single, u128, 0, HALF_128_BIT_UNSIGNED - 1, 10);
|
|
||||||
uniform_single!(uniform_u128x10_6_single, u128, 0, 6u128, 10);
|
|
69
benches/benches/bool.rs
Normal file
69
benches/benches/bool.rs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
//! Generating/filling arrays and iterators of output
|
||||||
|
|
||||||
|
use criterion::{criterion_group, criterion_main, Criterion};
|
||||||
|
use rand::distr::Bernoulli;
|
||||||
|
use rand::prelude::*;
|
||||||
|
use rand_pcg::Pcg32;
|
||||||
|
|
||||||
|
criterion_group!(
|
||||||
|
name = benches;
|
||||||
|
config = Criterion::default();
|
||||||
|
targets = bench
|
||||||
|
);
|
||||||
|
criterion_main!(benches);
|
||||||
|
|
||||||
|
pub fn bench(c: &mut Criterion) {
|
||||||
|
let mut g = c.benchmark_group("gen_bool");
|
||||||
|
g.sample_size(1000);
|
||||||
|
g.warm_up_time(core::time::Duration::from_millis(500));
|
||||||
|
g.measurement_time(core::time::Duration::from_millis(1000));
|
||||||
|
|
||||||
|
g.bench_function("standard", |b| {
|
||||||
|
let mut rng = Pcg32::from_rng(&mut thread_rng());
|
||||||
|
b.iter(|| rng.sample::<bool, _>(rand::distr::Standard))
|
||||||
|
});
|
||||||
|
|
||||||
|
g.bench_function("const", |b| {
|
||||||
|
let mut rng = Pcg32::from_rng(&mut thread_rng());
|
||||||
|
b.iter(|| rng.gen_bool(0.18))
|
||||||
|
});
|
||||||
|
|
||||||
|
g.bench_function("var", |b| {
|
||||||
|
let mut rng = Pcg32::from_rng(&mut thread_rng());
|
||||||
|
let p = rng.random();
|
||||||
|
b.iter(|| rng.gen_bool(p))
|
||||||
|
});
|
||||||
|
|
||||||
|
g.bench_function("ratio_const", |b| {
|
||||||
|
let mut rng = Pcg32::from_rng(&mut thread_rng());
|
||||||
|
b.iter(|| rng.gen_ratio(2, 3))
|
||||||
|
});
|
||||||
|
|
||||||
|
g.bench_function("ratio_var", |b| {
|
||||||
|
let mut rng = Pcg32::from_rng(&mut thread_rng());
|
||||||
|
let d = rng.gen_range(1..=100);
|
||||||
|
let n = rng.gen_range(0..=d);
|
||||||
|
b.iter(|| rng.gen_ratio(n, d));
|
||||||
|
});
|
||||||
|
|
||||||
|
g.bench_function("bernoulli_const", |b| {
|
||||||
|
let mut rng = Pcg32::from_rng(&mut thread_rng());
|
||||||
|
let d = Bernoulli::new(0.18).unwrap();
|
||||||
|
b.iter(|| rng.sample(d))
|
||||||
|
});
|
||||||
|
|
||||||
|
g.bench_function("bernoulli_var", |b| {
|
||||||
|
let mut rng = Pcg32::from_rng(&mut thread_rng());
|
||||||
|
let p = rng.random();
|
||||||
|
let d = Bernoulli::new(p).unwrap();
|
||||||
|
b.iter(|| rng.sample(d))
|
||||||
|
});
|
||||||
|
}
|
@ -13,8 +13,7 @@
|
|||||||
|
|
||||||
const RAND_BENCH_N: u64 = 1000;
|
const RAND_BENCH_N: u64 = 1000;
|
||||||
|
|
||||||
use criterion::{criterion_group, criterion_main, Criterion,
|
use criterion::{criterion_group, criterion_main, Criterion, Throughput};
|
||||||
Throughput};
|
|
||||||
use criterion_cycles_per_byte::CyclesPerByte;
|
use criterion_cycles_per_byte::CyclesPerByte;
|
||||||
|
|
||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
@ -6,139 +6,160 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(test)]
|
use core::time::Duration;
|
||||||
#![allow(non_snake_case)]
|
use criterion::measurement::WallTime;
|
||||||
|
use criterion::{black_box, criterion_group, criterion_main, BenchmarkGroup, Criterion};
|
||||||
extern crate test;
|
|
||||||
|
|
||||||
const RAND_BENCH_N: u64 = 1000;
|
|
||||||
const BYTES_LEN: usize = 1024;
|
|
||||||
|
|
||||||
use core::mem::size_of;
|
|
||||||
use rand_chacha::rand_core::UnwrapErr;
|
|
||||||
use test::{black_box, Bencher};
|
|
||||||
|
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use rand::rngs::ReseedingRng;
|
use rand::rngs::ReseedingRng;
|
||||||
use rand::rngs::{mock::StepRng, OsRng};
|
use rand::rngs::{mock::StepRng, OsRng};
|
||||||
|
use rand_chacha::rand_core::UnwrapErr;
|
||||||
use rand_chacha::{ChaCha12Rng, ChaCha20Core, ChaCha20Rng, ChaCha8Rng};
|
use rand_chacha::{ChaCha12Rng, ChaCha20Core, ChaCha20Rng, ChaCha8Rng};
|
||||||
use rand_pcg::{Pcg32, Pcg64, Pcg64Dxsm, Pcg64Mcg};
|
use rand_pcg::{Pcg32, Pcg64, Pcg64Dxsm, Pcg64Mcg};
|
||||||
|
|
||||||
macro_rules! gen_bytes {
|
criterion_group!(
|
||||||
($fnn:ident, $gen:expr) => {
|
name = benches;
|
||||||
#[bench]
|
config = Criterion::default();
|
||||||
fn $fnn(b: &mut Bencher) {
|
targets = gen_bytes, gen_u32, gen_u64, init_gen, reseeding_bytes
|
||||||
let mut rng = $gen;
|
);
|
||||||
let mut buf = [0u8; BYTES_LEN];
|
criterion_main!(benches);
|
||||||
|
|
||||||
|
pub fn gen_bytes(c: &mut Criterion) {
|
||||||
|
let mut g = c.benchmark_group("gen_bytes");
|
||||||
|
g.warm_up_time(Duration::from_millis(500));
|
||||||
|
g.measurement_time(Duration::from_millis(1000));
|
||||||
|
g.throughput(criterion::Throughput::Bytes(1024));
|
||||||
|
|
||||||
|
fn bench(g: &mut BenchmarkGroup<WallTime>, name: &str, mut rng: impl Rng) {
|
||||||
|
g.bench_function(name, |b| {
|
||||||
|
let mut buf = [0u8; 1024];
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
for _ in 0..RAND_BENCH_N {
|
|
||||||
rng.fill_bytes(&mut buf);
|
rng.fill_bytes(&mut buf);
|
||||||
black_box(buf);
|
black_box(buf);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
b.bytes = BYTES_LEN as u64 * RAND_BENCH_N;
|
});
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
bench(&mut g, "step", StepRng::new(0, 1));
|
||||||
|
bench(&mut g, "pcg32", Pcg32::from_os_rng());
|
||||||
|
bench(&mut g, "pcg64", Pcg64::from_os_rng());
|
||||||
|
bench(&mut g, "pcg64mcg", Pcg64Mcg::from_os_rng());
|
||||||
|
bench(&mut g, "pcg64dxsm", Pcg64Dxsm::from_os_rng());
|
||||||
|
bench(&mut g, "chacha8", ChaCha8Rng::from_os_rng());
|
||||||
|
bench(&mut g, "chacha12", ChaCha12Rng::from_os_rng());
|
||||||
|
bench(&mut g, "chacha20", ChaCha20Rng::from_os_rng());
|
||||||
|
bench(&mut g, "std", StdRng::from_os_rng());
|
||||||
|
bench(&mut g, "small", SmallRng::from_thread_rng());
|
||||||
|
bench(&mut g, "os", UnwrapErr(OsRng));
|
||||||
|
bench(&mut g, "thread", thread_rng());
|
||||||
|
|
||||||
|
g.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_bytes!(gen_bytes_step, StepRng::new(0, 1));
|
pub fn gen_u32(c: &mut Criterion) {
|
||||||
gen_bytes!(gen_bytes_pcg32, Pcg32::from_os_rng());
|
let mut g = c.benchmark_group("gen_u32");
|
||||||
gen_bytes!(gen_bytes_pcg64, Pcg64::from_os_rng());
|
g.sample_size(1000);
|
||||||
gen_bytes!(gen_bytes_pcg64mcg, Pcg64Mcg::from_os_rng());
|
g.warm_up_time(Duration::from_millis(500));
|
||||||
gen_bytes!(gen_bytes_pcg64dxsm, Pcg64Dxsm::from_os_rng());
|
g.measurement_time(Duration::from_millis(1000));
|
||||||
gen_bytes!(gen_bytes_chacha8, ChaCha8Rng::from_os_rng());
|
g.throughput(criterion::Throughput::Bytes(4));
|
||||||
gen_bytes!(gen_bytes_chacha12, ChaCha12Rng::from_os_rng());
|
|
||||||
gen_bytes!(gen_bytes_chacha20, ChaCha20Rng::from_os_rng());
|
|
||||||
gen_bytes!(gen_bytes_std, StdRng::from_os_rng());
|
|
||||||
gen_bytes!(gen_bytes_small, SmallRng::from_thread_rng());
|
|
||||||
gen_bytes!(gen_bytes_os, UnwrapErr(OsRng));
|
|
||||||
gen_bytes!(gen_bytes_thread, thread_rng());
|
|
||||||
|
|
||||||
macro_rules! gen_uint {
|
fn bench(g: &mut BenchmarkGroup<WallTime>, name: &str, mut rng: impl Rng) {
|
||||||
($fnn:ident, $ty:ty, $gen:expr) => {
|
g.bench_function(name, |b| {
|
||||||
#[bench]
|
b.iter(|| rng.random::<u32>());
|
||||||
fn $fnn(b: &mut Bencher) {
|
|
||||||
let mut rng = $gen;
|
|
||||||
b.iter(|| {
|
|
||||||
let mut accum: $ty = 0;
|
|
||||||
for _ in 0..RAND_BENCH_N {
|
|
||||||
accum = accum.wrapping_add(rng.random::<$ty>());
|
|
||||||
}
|
|
||||||
accum
|
|
||||||
});
|
});
|
||||||
b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
bench(&mut g, "step", StepRng::new(0, 1));
|
||||||
|
bench(&mut g, "pcg32", Pcg32::from_os_rng());
|
||||||
|
bench(&mut g, "pcg64", Pcg64::from_os_rng());
|
||||||
|
bench(&mut g, "pcg64mcg", Pcg64Mcg::from_os_rng());
|
||||||
|
bench(&mut g, "pcg64dxsm", Pcg64Dxsm::from_os_rng());
|
||||||
|
bench(&mut g, "chacha8", ChaCha8Rng::from_os_rng());
|
||||||
|
bench(&mut g, "chacha12", ChaCha12Rng::from_os_rng());
|
||||||
|
bench(&mut g, "chacha20", ChaCha20Rng::from_os_rng());
|
||||||
|
bench(&mut g, "std", StdRng::from_os_rng());
|
||||||
|
bench(&mut g, "small", SmallRng::from_thread_rng());
|
||||||
|
bench(&mut g, "os", UnwrapErr(OsRng));
|
||||||
|
bench(&mut g, "thread", thread_rng());
|
||||||
|
|
||||||
|
g.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_uint!(gen_u32_step, u32, StepRng::new(0, 1));
|
pub fn gen_u64(c: &mut Criterion) {
|
||||||
gen_uint!(gen_u32_pcg32, u32, Pcg32::from_os_rng());
|
let mut g = c.benchmark_group("gen_u64");
|
||||||
gen_uint!(gen_u32_pcg64, u32, Pcg64::from_os_rng());
|
g.sample_size(1000);
|
||||||
gen_uint!(gen_u32_pcg64mcg, u32, Pcg64Mcg::from_os_rng());
|
g.warm_up_time(Duration::from_millis(500));
|
||||||
gen_uint!(gen_u32_pcg64dxsm, u32, Pcg64Dxsm::from_os_rng());
|
g.measurement_time(Duration::from_millis(1000));
|
||||||
gen_uint!(gen_u32_chacha8, u32, ChaCha8Rng::from_os_rng());
|
g.throughput(criterion::Throughput::Bytes(8));
|
||||||
gen_uint!(gen_u32_chacha12, u32, ChaCha12Rng::from_os_rng());
|
|
||||||
gen_uint!(gen_u32_chacha20, u32, ChaCha20Rng::from_os_rng());
|
|
||||||
gen_uint!(gen_u32_std, u32, StdRng::from_os_rng());
|
|
||||||
gen_uint!(gen_u32_small, u32, SmallRng::from_thread_rng());
|
|
||||||
gen_uint!(gen_u32_os, u32, UnwrapErr(OsRng));
|
|
||||||
gen_uint!(gen_u32_thread, u32, thread_rng());
|
|
||||||
|
|
||||||
gen_uint!(gen_u64_step, u64, StepRng::new(0, 1));
|
fn bench(g: &mut BenchmarkGroup<WallTime>, name: &str, mut rng: impl Rng) {
|
||||||
gen_uint!(gen_u64_pcg32, u64, Pcg32::from_os_rng());
|
g.bench_function(name, |b| {
|
||||||
gen_uint!(gen_u64_pcg64, u64, Pcg64::from_os_rng());
|
b.iter(|| rng.random::<u64>());
|
||||||
gen_uint!(gen_u64_pcg64mcg, u64, Pcg64Mcg::from_os_rng());
|
});
|
||||||
gen_uint!(gen_u64_pcg64dxsm, u64, Pcg64Dxsm::from_os_rng());
|
}
|
||||||
gen_uint!(gen_u64_chacha8, u64, ChaCha8Rng::from_os_rng());
|
|
||||||
gen_uint!(gen_u64_chacha12, u64, ChaCha12Rng::from_os_rng());
|
|
||||||
gen_uint!(gen_u64_chacha20, u64, ChaCha20Rng::from_os_rng());
|
|
||||||
gen_uint!(gen_u64_std, u64, StdRng::from_os_rng());
|
|
||||||
gen_uint!(gen_u64_small, u64, SmallRng::from_thread_rng());
|
|
||||||
gen_uint!(gen_u64_os, u64, UnwrapErr(OsRng));
|
|
||||||
gen_uint!(gen_u64_thread, u64, thread_rng());
|
|
||||||
|
|
||||||
macro_rules! init_gen {
|
bench(&mut g, "step", StepRng::new(0, 1));
|
||||||
($fnn:ident, $gen:ident) => {
|
bench(&mut g, "pcg32", Pcg32::from_os_rng());
|
||||||
#[bench]
|
bench(&mut g, "pcg64", Pcg64::from_os_rng());
|
||||||
fn $fnn(b: &mut Bencher) {
|
bench(&mut g, "pcg64mcg", Pcg64Mcg::from_os_rng());
|
||||||
|
bench(&mut g, "pcg64dxsm", Pcg64Dxsm::from_os_rng());
|
||||||
|
bench(&mut g, "chacha8", ChaCha8Rng::from_os_rng());
|
||||||
|
bench(&mut g, "chacha12", ChaCha12Rng::from_os_rng());
|
||||||
|
bench(&mut g, "chacha20", ChaCha20Rng::from_os_rng());
|
||||||
|
bench(&mut g, "std", StdRng::from_os_rng());
|
||||||
|
bench(&mut g, "small", SmallRng::from_thread_rng());
|
||||||
|
bench(&mut g, "os", UnwrapErr(OsRng));
|
||||||
|
bench(&mut g, "thread", thread_rng());
|
||||||
|
|
||||||
|
g.finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_gen(c: &mut Criterion) {
|
||||||
|
let mut g = c.benchmark_group("init_gen");
|
||||||
|
g.warm_up_time(Duration::from_millis(500));
|
||||||
|
g.measurement_time(Duration::from_millis(1000));
|
||||||
|
|
||||||
|
fn bench<R: SeedableRng>(g: &mut BenchmarkGroup<WallTime>, name: &str) {
|
||||||
|
g.bench_function(name, |b| {
|
||||||
let mut rng = Pcg32::from_os_rng();
|
let mut rng = Pcg32::from_os_rng();
|
||||||
b.iter(|| {
|
b.iter(|| R::from_rng(&mut rng));
|
||||||
let r2 = $gen::from_rng(&mut rng);
|
|
||||||
r2
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
bench::<Pcg32>(&mut g, "pcg32");
|
||||||
|
bench::<Pcg64>(&mut g, "pcg64");
|
||||||
|
bench::<Pcg64Mcg>(&mut g, "pcg64mcg");
|
||||||
|
bench::<Pcg64Dxsm>(&mut g, "pcg64dxsm");
|
||||||
|
bench::<ChaCha8Rng>(&mut g, "chacha8");
|
||||||
|
bench::<ChaCha12Rng>(&mut g, "chacha12");
|
||||||
|
bench::<ChaCha20Rng>(&mut g, "chacha20");
|
||||||
|
bench::<StdRng>(&mut g, "std");
|
||||||
|
|
||||||
|
g.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
init_gen!(init_pcg32, Pcg32);
|
pub fn reseeding_bytes(c: &mut Criterion) {
|
||||||
init_gen!(init_pcg64, Pcg64);
|
let mut g = c.benchmark_group("reseeding_bytes");
|
||||||
init_gen!(init_pcg64mcg, Pcg64Mcg);
|
g.warm_up_time(Duration::from_millis(500));
|
||||||
init_gen!(init_pcg64dxsm, Pcg64Dxsm);
|
g.throughput(criterion::Throughput::Bytes(1024 * 1024));
|
||||||
init_gen!(init_chacha, ChaCha20Rng);
|
|
||||||
|
|
||||||
const RESEEDING_BYTES_LEN: usize = 1024 * 1024;
|
fn bench(g: &mut BenchmarkGroup<WallTime>, thresh: u64) {
|
||||||
const RESEEDING_BENCH_N: u64 = 16;
|
let name = format!("chacha20_{}k", thresh);
|
||||||
|
g.bench_function(name.as_str(), |b| {
|
||||||
macro_rules! reseeding_bytes {
|
let mut rng = ReseedingRng::new(ChaCha20Core::from_os_rng(), thresh * 1024, OsRng);
|
||||||
($fnn:ident, $thresh:expr) => {
|
let mut buf = [0u8; 1024 * 1024];
|
||||||
#[bench]
|
|
||||||
fn $fnn(b: &mut Bencher) {
|
|
||||||
let mut rng = ReseedingRng::new(ChaCha20Core::from_os_rng(), $thresh * 1024, OsRng);
|
|
||||||
let mut buf = [0u8; RESEEDING_BYTES_LEN];
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
for _ in 0..RESEEDING_BENCH_N {
|
|
||||||
rng.fill_bytes(&mut buf);
|
rng.fill_bytes(&mut buf);
|
||||||
black_box(&buf);
|
black_box(&buf);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
b.bytes = RESEEDING_BYTES_LEN as u64 * RESEEDING_BENCH_N;
|
});
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
reseeding_bytes!(reseeding_chacha20_4k, 4);
|
bench(&mut g, 4);
|
||||||
reseeding_bytes!(reseeding_chacha20_16k, 16);
|
bench(&mut g, 16);
|
||||||
reseeding_bytes!(reseeding_chacha20_32k, 32);
|
bench(&mut g, 32);
|
||||||
reseeding_bytes!(reseeding_chacha20_64k, 64);
|
bench(&mut g, 64);
|
||||||
reseeding_bytes!(reseeding_chacha20_256k, 256);
|
bench(&mut g, 256);
|
||||||
reseeding_bytes!(reseeding_chacha20_1M, 1024);
|
bench(&mut g, 1024);
|
||||||
|
|
||||||
|
g.finish()
|
||||||
|
}
|
||||||
|
@ -1,183 +0,0 @@
|
|||||||
// 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;
|
|
||||||
|
|
||||||
const RAND_BENCH_N: u64 = 1000;
|
|
||||||
|
|
||||||
use test::Bencher;
|
|
||||||
|
|
||||||
use rand::distr::{Bernoulli, Distribution, Standard};
|
|
||||||
use rand::prelude::*;
|
|
||||||
use rand_pcg::{Pcg32, Pcg64Mcg};
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn misc_gen_bool_const(b: &mut Bencher) {
|
|
||||||
let mut rng = Pcg32::from_rng(&mut thread_rng());
|
|
||||||
b.iter(|| {
|
|
||||||
let mut accum = true;
|
|
||||||
for _ in 0..RAND_BENCH_N {
|
|
||||||
accum ^= rng.gen_bool(0.18);
|
|
||||||
}
|
|
||||||
accum
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn misc_gen_bool_var(b: &mut Bencher) {
|
|
||||||
let mut rng = Pcg32::from_rng(&mut thread_rng());
|
|
||||||
b.iter(|| {
|
|
||||||
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_gen_ratio_const(b: &mut Bencher) {
|
|
||||||
let mut rng = Pcg32::from_rng(&mut thread_rng());
|
|
||||||
b.iter(|| {
|
|
||||||
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 = Pcg32::from_rng(&mut thread_rng());
|
|
||||||
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 = Pcg32::from_rng(&mut thread_rng());
|
|
||||||
b.iter(|| {
|
|
||||||
let d = Bernoulli::new(0.18).unwrap();
|
|
||||||
let mut accum = true;
|
|
||||||
for _ in 0..RAND_BENCH_N {
|
|
||||||
accum ^= rng.sample(d);
|
|
||||||
}
|
|
||||||
accum
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn misc_bernoulli_var(b: &mut Bencher) {
|
|
||||||
let mut rng = Pcg32::from_rng(&mut thread_rng());
|
|
||||||
b.iter(|| {
|
|
||||||
let mut accum = true;
|
|
||||||
let mut p = 0.18;
|
|
||||||
for _ in 0..RAND_BENCH_N {
|
|
||||||
let d = Bernoulli::new(p).unwrap();
|
|
||||||
accum ^= rng.sample(d);
|
|
||||||
p += 0.0001;
|
|
||||||
}
|
|
||||||
accum
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn gen_1kb_u16_iter_repeat(b: &mut Bencher) {
|
|
||||||
use core::iter;
|
|
||||||
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
|
||||||
b.iter(|| {
|
|
||||||
let v: Vec<u16> = iter::repeat(()).map(|()| rng.random()).take(512).collect();
|
|
||||||
v
|
|
||||||
});
|
|
||||||
b.bytes = 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn gen_1kb_u16_sample_iter(b: &mut Bencher) {
|
|
||||||
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
|
||||||
b.iter(|| {
|
|
||||||
let v: Vec<u16> = Standard.sample_iter(&mut rng).take(512).collect();
|
|
||||||
v
|
|
||||||
});
|
|
||||||
b.bytes = 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn gen_1kb_u16_gen_array(b: &mut Bencher) {
|
|
||||||
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
|
||||||
b.iter(|| {
|
|
||||||
// max supported array length is 32!
|
|
||||||
let v: [[u16; 32]; 16] = rng.random();
|
|
||||||
v
|
|
||||||
});
|
|
||||||
b.bytes = 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn gen_1kb_u16_fill(b: &mut Bencher) {
|
|
||||||
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
|
||||||
let mut buf = [0u16; 512];
|
|
||||||
b.iter(|| {
|
|
||||||
rng.fill(&mut buf[..]);
|
|
||||||
buf
|
|
||||||
});
|
|
||||||
b.bytes = 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn gen_1kb_u64_iter_repeat(b: &mut Bencher) {
|
|
||||||
use core::iter;
|
|
||||||
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
|
||||||
b.iter(|| {
|
|
||||||
let v: Vec<u64> = iter::repeat(()).map(|()| rng.random()).take(128).collect();
|
|
||||||
v
|
|
||||||
});
|
|
||||||
b.bytes = 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn gen_1kb_u64_sample_iter(b: &mut Bencher) {
|
|
||||||
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
|
||||||
b.iter(|| {
|
|
||||||
let v: Vec<u64> = Standard.sample_iter(&mut rng).take(128).collect();
|
|
||||||
v
|
|
||||||
});
|
|
||||||
b.bytes = 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn gen_1kb_u64_gen_array(b: &mut Bencher) {
|
|
||||||
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
|
||||||
b.iter(|| {
|
|
||||||
// max supported array length is 32!
|
|
||||||
let v: [[u64; 32]; 4] = rng.random();
|
|
||||||
v
|
|
||||||
});
|
|
||||||
b.bytes = 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn gen_1kb_u64_fill(b: &mut Bencher) {
|
|
||||||
let mut rng = Pcg64Mcg::from_rng(&mut thread_rng());
|
|
||||||
let mut buf = [0u64; 128];
|
|
||||||
b.iter(|| {
|
|
||||||
rng.fill(&mut buf[..]);
|
|
||||||
buf
|
|
||||||
});
|
|
||||||
b.bytes = 1024;
|
|
||||||
}
|
|
@ -1,130 +0,0 @@
|
|||||||
// 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;
|
|
||||||
|
|
||||||
use test::Bencher;
|
|
||||||
|
|
||||||
use core::mem::size_of;
|
|
||||||
use rand::prelude::*;
|
|
||||||
use rand::seq::*;
|
|
||||||
|
|
||||||
// We force use of 32-bit RNG since seq code is optimised for use with 32-bit
|
|
||||||
// generators on all platforms.
|
|
||||||
use rand_pcg::Pcg32 as SmallRng;
|
|
||||||
|
|
||||||
const RAND_BENCH_N: u64 = 1000;
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn seq_shuffle_100(b: &mut Bencher) {
|
|
||||||
let mut rng = SmallRng::from_rng(thread_rng());
|
|
||||||
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());
|
|
||||||
let x: &mut [usize] = &mut [1; 1000];
|
|
||||||
for (i, r) in x.iter_mut().enumerate() {
|
|
||||||
*r = 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());
|
|
||||||
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_multiple_10_of_100(b: &mut Bencher) {
|
|
||||||
let mut rng = SmallRng::from_rng(thread_rng());
|
|
||||||
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());
|
|
||||||
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());
|
|
||||||
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, 1_000_000);
|
|
||||||
sample_indices!(misc_sample_indices_100_of_1G, sample, 100, 1_000_000_000);
|
|
||||||
sample_indices!(misc_sample_indices_200_of_1G, sample, 200, 1_000_000_000);
|
|
||||||
sample_indices!(misc_sample_indices_400_of_1G, sample, 400, 1_000_000_000);
|
|
||||||
sample_indices!(misc_sample_indices_600_of_1G, sample, 600, 1_000_000_000);
|
|
||||||
|
|
||||||
macro_rules! sample_indices_rand_weights {
|
|
||||||
($name:ident, $amount:expr, $length:expr) => {
|
|
||||||
#[bench]
|
|
||||||
fn $name(b: &mut Bencher) {
|
|
||||||
let mut rng = SmallRng::from_rng(thread_rng());
|
|
||||||
b.iter(|| {
|
|
||||||
index::sample_weighted(&mut rng, $length, |idx| (1 + (idx % 100)) as u32, $amount)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sample_indices_rand_weights!(misc_sample_weighted_indices_1_of_1k, 1, 1000);
|
|
||||||
sample_indices_rand_weights!(misc_sample_weighted_indices_10_of_1k, 10, 1000);
|
|
||||||
sample_indices_rand_weights!(misc_sample_weighted_indices_100_of_1k, 100, 1000);
|
|
||||||
sample_indices_rand_weights!(misc_sample_weighted_indices_100_of_1M, 100, 1_000_000);
|
|
||||||
sample_indices_rand_weights!(misc_sample_weighted_indices_200_of_1M, 200, 1_000_000);
|
|
||||||
sample_indices_rand_weights!(misc_sample_weighted_indices_400_of_1M, 400, 1_000_000);
|
|
||||||
sample_indices_rand_weights!(misc_sample_weighted_indices_600_of_1M, 600, 1_000_000);
|
|
||||||
sample_indices_rand_weights!(misc_sample_weighted_indices_1k_of_1M, 1000, 1_000_000);
|
|
155
benches/benches/seq_choose.rs
Normal file
155
benches/benches/seq_choose.rs
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
// Copyright 2018-2023 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.
|
||||||
|
|
||||||
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
|
use rand::prelude::*;
|
||||||
|
use rand::SeedableRng;
|
||||||
|
use rand_pcg::Pcg32;
|
||||||
|
|
||||||
|
criterion_group!(
|
||||||
|
name = benches;
|
||||||
|
config = Criterion::default();
|
||||||
|
targets = bench
|
||||||
|
);
|
||||||
|
criterion_main!(benches);
|
||||||
|
|
||||||
|
pub fn bench(c: &mut Criterion) {
|
||||||
|
c.bench_function("seq_slice_choose_1_of_1000", |b| {
|
||||||
|
let mut rng = Pcg32::from_rng(thread_rng());
|
||||||
|
let mut buf = [0i32; 100];
|
||||||
|
rng.fill(&mut buf);
|
||||||
|
let x = black_box(&mut buf);
|
||||||
|
|
||||||
|
b.iter(|| x.choose(&mut rng).unwrap());
|
||||||
|
});
|
||||||
|
|
||||||
|
let lens = [(1, 1000), (950, 1000), (10, 100), (90, 100)];
|
||||||
|
for (amount, len) in lens {
|
||||||
|
let name = format!("seq_slice_choose_multiple_{}_of_{}", amount, len);
|
||||||
|
c.bench_function(name.as_str(), |b| {
|
||||||
|
let mut rng = Pcg32::from_rng(thread_rng());
|
||||||
|
let mut buf = [0i32; 1000];
|
||||||
|
rng.fill(&mut buf);
|
||||||
|
let x = black_box(&buf[..len]);
|
||||||
|
|
||||||
|
let mut results_buf = [0i32; 950];
|
||||||
|
let y = black_box(&mut results_buf[..amount]);
|
||||||
|
let amount = black_box(amount);
|
||||||
|
|
||||||
|
b.iter(|| {
|
||||||
|
// Collect full result to prevent unwanted shortcuts getting
|
||||||
|
// first element (in case sample_indices returns an iterator).
|
||||||
|
for (slot, sample) in y.iter_mut().zip(x.choose_multiple(&mut rng, amount)) {
|
||||||
|
*slot = *sample;
|
||||||
|
}
|
||||||
|
y[amount - 1]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
c.bench_function("seq_iter_choose_multiple_10_of_100", |b| {
|
||||||
|
let mut rng = Pcg32::from_rng(thread_rng());
|
||||||
|
let mut buf = [0i32; 100];
|
||||||
|
rng.fill(&mut buf);
|
||||||
|
let x = black_box(&buf);
|
||||||
|
b.iter(|| x.iter().cloned().choose_multiple(&mut rng, 10))
|
||||||
|
});
|
||||||
|
|
||||||
|
c.bench_function("seq_iter_choose_multiple_fill_10_of_100", |b| {
|
||||||
|
let mut rng = Pcg32::from_rng(thread_rng());
|
||||||
|
let mut buf = [0i32; 100];
|
||||||
|
rng.fill(&mut buf);
|
||||||
|
let x = black_box(&buf);
|
||||||
|
let mut buf = [0; 10];
|
||||||
|
b.iter(|| x.iter().cloned().choose_multiple_fill(&mut rng, &mut buf))
|
||||||
|
});
|
||||||
|
|
||||||
|
bench_rng::<rand_chacha::ChaCha20Rng>(c, "ChaCha20");
|
||||||
|
bench_rng::<rand_pcg::Pcg32>(c, "Pcg32");
|
||||||
|
bench_rng::<rand_pcg::Pcg64>(c, "Pcg64");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bench_rng<Rng: RngCore + SeedableRng>(c: &mut Criterion, rng_name: &'static str) {
|
||||||
|
for length in [1, 2, 3, 10, 100, 1000].map(black_box) {
|
||||||
|
let name = format!("choose_size-hinted_from_{length}_{rng_name}");
|
||||||
|
c.bench_function(name.as_str(), |b| {
|
||||||
|
let mut rng = Rng::seed_from_u64(123);
|
||||||
|
b.iter(|| choose_size_hinted(length, &mut rng))
|
||||||
|
});
|
||||||
|
|
||||||
|
let name = format!("choose_stable_from_{length}_{rng_name}");
|
||||||
|
c.bench_function(name.as_str(), |b| {
|
||||||
|
let mut rng = Rng::seed_from_u64(123);
|
||||||
|
b.iter(|| choose_stable(length, &mut rng))
|
||||||
|
});
|
||||||
|
|
||||||
|
let name = format!("choose_unhinted_from_{length}_{rng_name}");
|
||||||
|
c.bench_function(name.as_str(), |b| {
|
||||||
|
let mut rng = Rng::seed_from_u64(123);
|
||||||
|
b.iter(|| choose_unhinted(length, &mut rng))
|
||||||
|
});
|
||||||
|
|
||||||
|
let name = format!("choose_windowed_from_{length}_{rng_name}");
|
||||||
|
c.bench_function(name.as_str(), |b| {
|
||||||
|
let mut rng = Rng::seed_from_u64(123);
|
||||||
|
b.iter(|| choose_windowed(length, 7, &mut rng))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn choose_size_hinted<R: Rng>(max: usize, rng: &mut R) -> Option<usize> {
|
||||||
|
let iterator = 0..max;
|
||||||
|
iterator.choose(rng)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn choose_stable<R: Rng>(max: usize, rng: &mut R) -> Option<usize> {
|
||||||
|
let iterator = 0..max;
|
||||||
|
iterator.choose_stable(rng)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn choose_unhinted<R: Rng>(max: usize, rng: &mut R) -> Option<usize> {
|
||||||
|
let iterator = UnhintedIterator { iter: (0..max) };
|
||||||
|
iterator.choose(rng)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn choose_windowed<R: Rng>(max: usize, window_size: usize, rng: &mut R) -> Option<usize> {
|
||||||
|
let iterator = WindowHintedIterator {
|
||||||
|
iter: (0..max),
|
||||||
|
window_size,
|
||||||
|
};
|
||||||
|
iterator.choose(rng)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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>) {
|
||||||
|
(core::cmp::min(self.iter.len(), self.window_size), None)
|
||||||
|
}
|
||||||
|
}
|
@ -5,18 +5,31 @@
|
|||||||
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
|
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use rand::SeedableRng;
|
use rand::SeedableRng;
|
||||||
|
use rand_pcg::Pcg32;
|
||||||
|
|
||||||
criterion_group!(
|
criterion_group!(
|
||||||
name = benches;
|
name = benches;
|
||||||
config = Criterion::default();
|
config = Criterion::default();
|
||||||
targets = bench
|
targets = bench
|
||||||
);
|
);
|
||||||
criterion_main!(benches);
|
criterion_main!(benches);
|
||||||
|
|
||||||
pub fn bench(c: &mut Criterion) {
|
pub fn bench(c: &mut Criterion) {
|
||||||
|
c.bench_function("seq_shuffle_100", |b| {
|
||||||
|
let mut rng = Pcg32::from_rng(thread_rng());
|
||||||
|
let mut buf = [0i32; 100];
|
||||||
|
rng.fill(&mut buf);
|
||||||
|
let x = black_box(&mut buf);
|
||||||
|
b.iter(|| {
|
||||||
|
x.shuffle(&mut rng);
|
||||||
|
x[0]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
bench_rng::<rand_chacha::ChaCha12Rng>(c, "ChaCha12");
|
bench_rng::<rand_chacha::ChaCha12Rng>(c, "ChaCha12");
|
||||||
bench_rng::<rand_pcg::Pcg32>(c, "Pcg32");
|
bench_rng::<rand_pcg::Pcg32>(c, "Pcg32");
|
||||||
bench_rng::<rand_pcg::Pcg64>(c, "Pcg64");
|
bench_rng::<rand_pcg::Pcg64>(c, "Pcg64");
|
||||||
@ -34,17 +47,15 @@ fn bench_rng<Rng: RngCore + SeedableRng>(c: &mut Criterion, rng_name: &'static s
|
|||||||
});
|
});
|
||||||
|
|
||||||
if length >= 10 {
|
if length >= 10 {
|
||||||
c.bench_function(
|
let name = format!("partial_shuffle_{length}_{rng_name}");
|
||||||
format!("partial_shuffle_{length}_{rng_name}").as_str(),
|
c.bench_function(name.as_str(), |b| {
|
||||||
|b| {
|
|
||||||
let mut rng = Rng::seed_from_u64(123);
|
let mut rng = Rng::seed_from_u64(123);
|
||||||
let mut vec: Vec<usize> = (0..length).collect();
|
let mut vec: Vec<usize> = (0..length).collect();
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
vec.partial_shuffle(&mut rng, length / 2);
|
vec.partial_shuffle(&mut rng, length / 2);
|
||||||
vec[0]
|
vec[0]
|
||||||
})
|
})
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
64
benches/benches/standard.rs
Normal file
64
benches/benches/standard.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// Copyright 2019 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.
|
||||||
|
|
||||||
|
use core::time::Duration;
|
||||||
|
use criterion::measurement::WallTime;
|
||||||
|
use criterion::{criterion_group, criterion_main, BenchmarkGroup, Criterion};
|
||||||
|
use rand::distr::{Alphanumeric, Standard};
|
||||||
|
use rand::prelude::*;
|
||||||
|
use rand_distr::{Open01, OpenClosed01};
|
||||||
|
use rand_pcg::Pcg64Mcg;
|
||||||
|
|
||||||
|
criterion_group!(
|
||||||
|
name = benches;
|
||||||
|
config = Criterion::default();
|
||||||
|
targets = bench
|
||||||
|
);
|
||||||
|
criterion_main!(benches);
|
||||||
|
|
||||||
|
fn bench_ty<T, D>(g: &mut BenchmarkGroup<WallTime>, name: &str)
|
||||||
|
where
|
||||||
|
D: Distribution<T> + Default,
|
||||||
|
{
|
||||||
|
g.throughput(criterion::Throughput::Bytes(size_of::<T>() as u64));
|
||||||
|
g.bench_function(name, |b| {
|
||||||
|
let mut rng = Pcg64Mcg::from_os_rng();
|
||||||
|
|
||||||
|
b.iter(|| rng.sample::<T, _>(D::default()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bench(c: &mut Criterion) {
|
||||||
|
let mut g = c.benchmark_group("Standard");
|
||||||
|
g.sample_size(1000);
|
||||||
|
g.warm_up_time(Duration::from_millis(500));
|
||||||
|
g.measurement_time(Duration::from_millis(1000));
|
||||||
|
|
||||||
|
macro_rules! do_ty {
|
||||||
|
($t:ty) => {
|
||||||
|
bench_ty::<$t, Standard>(&mut g, stringify!($t));
|
||||||
|
};
|
||||||
|
($t:ty, $($tt:ty),*) => {
|
||||||
|
do_ty!($t);
|
||||||
|
do_ty!($($tt),*);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
do_ty!(i8, i16, i32, i64, i128, isize);
|
||||||
|
do_ty!(f32, f64);
|
||||||
|
do_ty!(char);
|
||||||
|
|
||||||
|
bench_ty::<u8, Alphanumeric>(&mut g, "Alphanumeric");
|
||||||
|
|
||||||
|
bench_ty::<f32, Open01>(&mut g, "Open01/f32");
|
||||||
|
bench_ty::<f64, Open01>(&mut g, "Open01/f64");
|
||||||
|
bench_ty::<f32, OpenClosed01>(&mut g, "OpenClosed01/f32");
|
||||||
|
bench_ty::<f64, OpenClosed01>(&mut g, "OpenClosed01/f64");
|
||||||
|
|
||||||
|
g.finish();
|
||||||
|
}
|
@ -6,31 +6,55 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(test)]
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
|
|
||||||
extern crate test;
|
|
||||||
|
|
||||||
use rand::distr::WeightedIndex;
|
use rand::distr::WeightedIndex;
|
||||||
use rand::Rng;
|
use rand::prelude::*;
|
||||||
use test::Bencher;
|
use rand::seq::index::sample_weighted;
|
||||||
|
|
||||||
#[bench]
|
criterion_group!(
|
||||||
fn weighted_index_creation(b: &mut Bencher) {
|
name = benches;
|
||||||
|
config = Criterion::default();
|
||||||
|
targets = bench
|
||||||
|
);
|
||||||
|
criterion_main!(benches);
|
||||||
|
|
||||||
|
pub fn bench(c: &mut Criterion) {
|
||||||
|
c.bench_function("weighted_index_creation", |b| {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let weights = [1u32, 2, 4, 0, 5, 1, 7, 1, 2, 3, 4, 5, 6, 7];
|
let weights = black_box([1u32, 2, 4, 0, 5, 1, 7, 1, 2, 3, 4, 5, 6, 7]);
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let distr = WeightedIndex::new(weights.to_vec()).unwrap();
|
let distr = WeightedIndex::new(weights.to_vec()).unwrap();
|
||||||
rng.sample(distr)
|
rng.sample(distr)
|
||||||
})
|
})
|
||||||
}
|
});
|
||||||
|
|
||||||
#[bench]
|
c.bench_function("weighted_index_modification", |b| {
|
||||||
fn weighted_index_modification(b: &mut Bencher) {
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let weights = [1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7];
|
let weights = black_box([1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7]);
|
||||||
let mut distr = WeightedIndex::new(weights.to_vec()).unwrap();
|
let mut distr = WeightedIndex::new(weights.to_vec()).unwrap();
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
distr.update_weights(&[(2, &4), (5, &1)]).unwrap();
|
distr.update_weights(&[(2, &4), (5, &1)]).unwrap();
|
||||||
rng.sample(&distr)
|
rng.sample(&distr)
|
||||||
})
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
let lens = [
|
||||||
|
(1, 1000, "1k"),
|
||||||
|
(10, 1000, "1k"),
|
||||||
|
(100, 1000, "1k"),
|
||||||
|
(100, 1_000_000, "1M"),
|
||||||
|
(200, 1_000_000, "1M"),
|
||||||
|
(400, 1_000_000, "1M"),
|
||||||
|
(600, 1_000_000, "1M"),
|
||||||
|
(1000, 1_000_000, "1M"),
|
||||||
|
];
|
||||||
|
for (amount, length, len_name) in lens {
|
||||||
|
let name = format!("weighted_sample_indices_{}_of_{}", amount, len_name);
|
||||||
|
c.bench_function(name.as_str(), |b| {
|
||||||
|
let length = black_box(length);
|
||||||
|
let amount = black_box(amount);
|
||||||
|
let mut rng = SmallRng::from_rng(thread_rng());
|
||||||
|
b.iter(|| sample_weighted(&mut rng, length, |idx| (1 + (idx % 100)) as u32, amount))
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,111 +0,0 @@
|
|||||||
// Copyright 2018-2023 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.
|
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
|
||||||
use rand::prelude::*;
|
|
||||||
use rand::SeedableRng;
|
|
||||||
|
|
||||||
criterion_group!(
|
|
||||||
name = benches;
|
|
||||||
config = Criterion::default();
|
|
||||||
targets = bench
|
|
||||||
);
|
|
||||||
criterion_main!(benches);
|
|
||||||
|
|
||||||
pub fn bench(c: &mut Criterion) {
|
|
||||||
bench_rng::<rand_chacha::ChaCha20Rng>(c, "ChaCha20");
|
|
||||||
bench_rng::<rand_pcg::Pcg32>(c, "Pcg32");
|
|
||||||
bench_rng::<rand_pcg::Pcg64>(c, "Pcg64");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bench_rng<Rng: RngCore + SeedableRng>(c: &mut Criterion, rng_name: &'static str) {
|
|
||||||
for length in [1, 2, 3, 10, 100, 1000].map(black_box) {
|
|
||||||
c.bench_function(
|
|
||||||
format!("choose_size-hinted_from_{length}_{rng_name}").as_str(),
|
|
||||||
|b| {
|
|
||||||
let mut rng = Rng::seed_from_u64(123);
|
|
||||||
b.iter(|| choose_size_hinted(length, &mut rng))
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
c.bench_function(
|
|
||||||
format!("choose_stable_from_{length}_{rng_name}").as_str(),
|
|
||||||
|b| {
|
|
||||||
let mut rng = Rng::seed_from_u64(123);
|
|
||||||
b.iter(|| choose_stable(length, &mut rng))
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
c.bench_function(
|
|
||||||
format!("choose_unhinted_from_{length}_{rng_name}").as_str(),
|
|
||||||
|b| {
|
|
||||||
let mut rng = Rng::seed_from_u64(123);
|
|
||||||
b.iter(|| choose_unhinted(length, &mut rng))
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
c.bench_function(
|
|
||||||
format!("choose_windowed_from_{length}_{rng_name}").as_str(),
|
|
||||||
|b| {
|
|
||||||
let mut rng = Rng::seed_from_u64(123);
|
|
||||||
b.iter(|| choose_windowed(length, 7, &mut rng))
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn choose_size_hinted<R: Rng>(max: usize, rng: &mut R) -> Option<usize> {
|
|
||||||
let iterator = 0..max;
|
|
||||||
iterator.choose(rng)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn choose_stable<R: Rng>(max: usize, rng: &mut R) -> Option<usize> {
|
|
||||||
let iterator = 0..max;
|
|
||||||
iterator.choose_stable(rng)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn choose_unhinted<R: Rng>(max: usize, rng: &mut R) -> Option<usize> {
|
|
||||||
let iterator = UnhintedIterator { iter: (0..max) };
|
|
||||||
iterator.choose(rng)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn choose_windowed<R: Rng>(max: usize, window_size: usize, rng: &mut R) -> Option<usize> {
|
|
||||||
let iterator = WindowHintedIterator {
|
|
||||||
iter: (0..max),
|
|
||||||
window_size,
|
|
||||||
};
|
|
||||||
iterator.choose(rng)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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>) {
|
|
||||||
(core::cmp::min(self.iter.len(), self.window_size), None)
|
|
||||||
}
|
|
||||||
}
|
|
@ -42,7 +42,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
/// [`Standard`]: crate::distr::Standard
|
/// [`Standard`]: crate::distr::Standard
|
||||||
/// [`Open01`]: crate::distr::Open01
|
/// [`Open01`]: crate::distr::Open01
|
||||||
/// [`Uniform`]: crate::distr::uniform::Uniform
|
/// [`Uniform`]: crate::distr::uniform::Uniform
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct OpenClosed01;
|
pub struct OpenClosed01;
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ pub struct OpenClosed01;
|
|||||||
/// [`Standard`]: crate::distr::Standard
|
/// [`Standard`]: crate::distr::Standard
|
||||||
/// [`OpenClosed01`]: crate::distr::OpenClosed01
|
/// [`OpenClosed01`]: crate::distr::OpenClosed01
|
||||||
/// [`Uniform`]: crate::distr::uniform::Uniform
|
/// [`Uniform`]: crate::distr::uniform::Uniform
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct Open01;
|
pub struct Open01;
|
||||||
|
|
||||||
|
@ -217,6 +217,6 @@ use crate::Rng;
|
|||||||
/// [`f32x4`]: std::simd::f32x4
|
/// [`f32x4`]: std::simd::f32x4
|
||||||
/// [`mask32x4`]: std::simd::mask32x4
|
/// [`mask32x4`]: std::simd::mask32x4
|
||||||
/// [`simd_support`]: https://github.com/rust-random/rand#crate-features
|
/// [`simd_support`]: https://github.com/rust-random/rand#crate-features
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub struct Standard;
|
pub struct Standard;
|
||||||
|
@ -66,7 +66,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
///
|
///
|
||||||
/// - [Wikipedia article on Password Strength](https://en.wikipedia.org/wiki/Password_strength)
|
/// - [Wikipedia article on Password Strength](https://en.wikipedia.org/wiki/Password_strength)
|
||||||
/// - [Diceware for generating memorable passwords](https://en.wikipedia.org/wiki/Diceware)
|
/// - [Diceware for generating memorable passwords](https://en.wikipedia.org/wiki/Diceware)
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct Alphanumeric;
|
pub struct Alphanumeric;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user