Skip to content

Commit 9684ebf

Browse files
committed
fill_via_chunks: use safe code via chunks_exact_mut on BE
This (specifically, using chunks_exact_mut) actually improves performance substantially.
1 parent 9a00a43 commit 9684ebf

File tree

1 file changed

+11
-11
lines changed

1 file changed

+11
-11
lines changed

rand_core/src/impls.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -58,25 +58,25 @@ macro_rules! fill_via_chunks {
5858
let chunk_size_u8 = min($src.len() * SIZE, $dst.len());
5959
let chunk_size = (chunk_size_u8 + SIZE - 1) / SIZE;
6060

61-
// The following can be replaced with safe code, but unfortunately it's
62-
// ca. 8% slower.
6361
if cfg!(target_endian = "little") {
62+
// On LE we can do a simple copy, which is 25-50% faster:
6463
unsafe {
6564
core::ptr::copy_nonoverlapping(
6665
$src.as_ptr() as *const u8,
6766
$dst.as_mut_ptr(),
6867
chunk_size_u8);
6968
}
7069
} else {
71-
for (&n, chunk) in $src.iter().zip($dst.chunks_mut(SIZE)) {
72-
let tmp = n.to_le();
73-
let src_ptr = &tmp as *const $ty as *const u8;
74-
unsafe {
75-
core::ptr::copy_nonoverlapping(
76-
src_ptr,
77-
chunk.as_mut_ptr(),
78-
chunk.len());
79-
}
70+
// This code is valid on all arches, but slower than the above:
71+
let mut i = 0;
72+
let mut iter = $dst[..chunk_size_u8].chunks_exact_mut(SIZE);
73+
while let Some(chunk) = iter.next() {
74+
chunk.copy_from_slice(&$src[i].to_le_bytes());
75+
i += 1;
76+
}
77+
let chunk = iter.into_remainder();
78+
if !chunk.is_empty() {
79+
chunk.copy_from_slice(&$src[i].to_le_bytes()[..chunk.len()]);
8080
}
8181
}
8282

0 commit comments

Comments
 (0)