Skip to content

Commit

Permalink
Implement Rng::fill (smol-rs#35)
Browse files Browse the repository at this point in the history
Fills a byte slice with random data.

Benchmarks:
  test fill             ... bench:          29 ns/iter (+/- 5)
  test fill_naive       ... bench:         343 ns/iter (+/- 33)
  • Loading branch information
cloudhead authored Sep 13, 2022
1 parent f53d813 commit 6fe2c33
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 1 deletion.
23 changes: 23 additions & 0 deletions benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
})
}
19 changes: 18 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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!(
Expand Down
13 changes: 13 additions & 0 deletions tests/smoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down

0 comments on commit 6fe2c33

Please sign in to comment.