From 02c1862fb55c6ae4198038b1b317bcdd06e395d1 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Sun, 3 Dec 2017 20:45:12 -0800 Subject: [PATCH] Add a specialization of read_exact for Cursor. The read_exact implementation for &[u8] is optimized and usually allows LLVM to reduce a read_exact call for small numbers of bytes to a bounds check and a register load instead of a generic memcpy. On a workload I have that decompresses, deserializes (via bincode), and processes some data, this leads to a 40% speedup by essentially eliminating the deserialization overhead entirely. --- src/libstd/io/cursor.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 32a92145aafed..b5ea5531b65a7 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -230,6 +230,13 @@ impl Read for Cursor where T: AsRef<[u8]> { Ok(n) } + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + let n = buf.len(); + Read::read_exact(&mut self.fill_buf()?, buf)?; + self.pos += n as u64; + Ok(()) + } + #[inline] unsafe fn initializer(&self) -> Initializer { Initializer::nop() @@ -475,6 +482,24 @@ mod tests { assert_eq!(reader.read(&mut buf).unwrap(), 0); } + #[test] + fn test_read_exact() { + let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; + let reader = &mut &in_buf[..]; + let mut buf = []; + assert!(reader.read_exact(&mut buf).is_ok()); + let mut buf = [8]; + assert!(reader.read_exact(&mut buf).is_ok()); + assert_eq!(buf[0], 0); + assert_eq!(reader.len(), 7); + let mut buf = [0, 0, 0, 0, 0, 0, 0]; + assert!(reader.read_exact(&mut buf).is_ok()); + assert_eq!(buf, [1, 2, 3, 4, 5, 6, 7]); + assert_eq!(reader.len(), 0); + let mut buf = [0]; + assert!(reader.read_exact(&mut buf).is_err()); + } + #[test] fn test_buf_reader() { let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];