Skip to content

Commit 5c6b860

Browse files
committed
Optimize Rng::fill
Benchmarks: test fill ... bench: 29 ns/iter (+/- 5) test fill_naive ... bench: 343 ns/iter (+/- 33)
1 parent 66b2491 commit 5c6b860

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

benches/bench.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,26 @@ fn u32_fastrand(b: &mut Bencher) {
7373
sum
7474
})
7575
}
76+
77+
#[bench]
78+
fn fill(b: &mut Bencher) {
79+
let rng = fastrand::Rng::new();
80+
b.iter(|| {
81+
// Pick a size that isn't divisble by 8.
82+
let mut bytes = [0u8; 367];
83+
rng.fill(&mut bytes);
84+
bytes
85+
})
86+
}
87+
88+
#[bench]
89+
fn fill_naive(b: &mut Bencher) {
90+
let rng = fastrand::Rng::new();
91+
b.iter(|| {
92+
let mut bytes = [0u8; 367];
93+
for item in &mut bytes {
94+
*item = rng.u8(..);
95+
}
96+
bytes
97+
})
98+
}

src/lib.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,15 @@ impl Rng {
444444
/// Fill a byte slice with random data.
445445
#[inline]
446446
pub fn fill(&self, slice: &mut [u8]) {
447-
for item in slice {
447+
// Filling the buffer in chunks of 8 is much faster.
448+
let mut chunks = slice.chunks_exact_mut(8);
449+
for items in chunks.by_ref() {
450+
let r = self.u64(..);
451+
items.copy_from_slice(&r.to_le_bytes());
452+
}
453+
454+
let remainder = chunks.into_remainder();
455+
for item in remainder {
448456
*item = self.u8(..);
449457
}
450458
}

0 commit comments

Comments
 (0)