Implement `Rng::fill` (#35)

Fills a byte slice with random data.

Benchmarks:
  test fill             ... bench:          29 ns/iter (+/- 5)
  test fill_naive       ... bench:         343 ns/iter (+/- 33)
This commit is contained in:
Alexis Sellier 2022-09-13 14:15:58 +02:00 committed by GitHub
parent f53d813aa3
commit 6fe2c33a26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 1 deletions

View File

@ -73,3 +73,26 @@ fn u32_fastrand(b: &mut Bencher) {
sum
})
}
#[bench]
fn fill(b: &mut Bencher) {
let rng = fastrand::Rng::new();
b.iter(|| {
// Pick a size that isn't divisble by 8.
let mut bytes = [0u8; 367];
rng.fill(&mut bytes);
bytes
})
}
#[bench]
fn fill_naive(b: &mut Bencher) {
let rng = fastrand::Rng::new();
b.iter(|| {
let mut bytes = [0u8; 367];
for item in &mut bytes {
*item = rng.u8(..);
}
bytes
})
}

View File

@ -70,6 +70,7 @@
use std::cell::Cell;
use std::collections::hash_map::DefaultHasher;
use std::convert::TryInto;
use std::hash::{Hash, Hasher};
use std::ops::{Bound, RangeBounds};
use std::thread;
@ -441,6 +442,22 @@ impl Rng {
}
}
/// Fill a byte slice with random data.
pub fn fill(&self, slice: &mut [u8]) {
// Filling the buffer in chunks of 8 is much faster.
let mut chunks = slice.chunks_exact_mut(8);
for chunk in chunks.by_ref() {
let n = self.gen_u64();
// Safe because the chunks are always 8 bytes exactly.
let bytes: &mut [u8; 8] = chunk.try_into().unwrap();
*bytes = n.to_ne_bytes();
}
for item in chunks.into_remainder() {
*item = self.u8(..);
}
}
rng_integer!(
u8,
u8,
@ -528,7 +545,7 @@ impl Rng {
/// Panics if the range is empty.
#[inline]
pub fn char(&self, range: impl RangeBounds<char>) -> char {
use std::convert::{TryFrom, TryInto};
use std::convert::TryFrom;
let panic_empty_range = || {
panic!(

View File

@ -81,6 +81,19 @@ fn u128() {
}
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn fill() {
let r = fastrand::Rng::new();
let mut a = [0u8; 64];
let mut b = [0u8; 64];
r.fill(&mut a);
r.fill(&mut b);
assert_ne!(a, b);
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn rng() {