Skip to content

Commit 3be2c3b

Browse files
committed
Move small-copy optimization into <&[u8] as Read>
Based on the discussion in #37573, it is likely better to keep this limited to std::io, instead of modifying a function which users expect to be a memcpy.
1 parent 3418052 commit 3be2c3b

File tree

2 files changed

+23
-15
lines changed

2 files changed

+23
-15
lines changed

src/libcore/slice.rs

+3-13
Original file line numberDiff line numberDiff line change
@@ -515,19 +515,9 @@ impl<T> SliceExt for [T] {
515515
fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
516516
assert!(self.len() == src.len(),
517517
"destination and source slices have different lengths");
518-
// First check if the amount of elements we want to copy is small:
519-
// `copy_nonoverlapping` will do a memcopy, which involves an indirect
520-
// function call when `memcpy` is in the dynamically-linked libc. For
521-
// small elements (such as a single byte or pointer), the overhead is
522-
// significant. If the element is big then the assignment is a memcopy
523-
// anyway.
524-
if self.len() == 1 {
525-
self[0] = src[0];
526-
} else {
527-
unsafe {
528-
ptr::copy_nonoverlapping(
529-
src.as_ptr(), self.as_mut_ptr(), self.len());
530-
}
518+
unsafe {
519+
ptr::copy_nonoverlapping(
520+
src.as_ptr(), self.as_mut_ptr(), self.len());
531521
}
532522
}
533523

src/libstd/io/impls.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,16 @@ impl<'a> Read for &'a [u8] {
157157
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
158158
let amt = cmp::min(buf.len(), self.len());
159159
let (a, b) = self.split_at(amt);
160-
buf[..amt].copy_from_slice(a);
160+
161+
// First check if the amount of bytes we want to read is small:
162+
// `copy_from_slice` will generally expand to a call to `memcpy`, and
163+
// for a single byte the overhead is significant.
164+
if amt == 1 {
165+
buf[0] = a[0];
166+
} else {
167+
buf[..amt].copy_from_slice(a);
168+
}
169+
161170
*self = b;
162171
Ok(amt)
163172
}
@@ -169,7 +178,16 @@ impl<'a> Read for &'a [u8] {
169178
"failed to fill whole buffer"));
170179
}
171180
let (a, b) = self.split_at(buf.len());
172-
buf.copy_from_slice(a);
181+
182+
// First check if the amount of bytes we want to read is small:
183+
// `copy_from_slice` will generally expand to a call to `memcpy`, and
184+
// for a single byte the overhead is significant.
185+
if buf.len() == 1 {
186+
buf[0] = a[0];
187+
} else {
188+
buf.copy_from_slice(a);
189+
}
190+
173191
*self = b;
174192
Ok(())
175193
}

0 commit comments

Comments
 (0)