From ca7eef71853e1e83bcaa663ebed2aab713a1e167 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 12 Oct 2023 10:49:32 +1100 Subject: [PATCH 1/3] Inline `Bytes::next` and `Bytes::size_hint`. This greatly increases its speed. --- library/std/src/io/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index c93bf0202523a..547c184a5c280 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2778,6 +2778,7 @@ pub struct Bytes { impl Iterator for Bytes { type Item = Result; + #[inline] fn next(&mut self) -> Option> { let mut byte = 0; loop { @@ -2790,6 +2791,7 @@ impl Iterator for Bytes { } } + #[inline] fn size_hint(&self) -> (usize, Option) { SizeHint::size_hint(&self.inner) } From 69ad06fad505b39158d5c7e576ffbe2bcc6a7c9e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 12 Oct 2023 11:25:29 +1100 Subject: [PATCH 2/3] Add `Bytes::byte` field. We can reuse this in `next`, avoiding the need to zero-initialize a local variable every time, for a small speed win. --- library/std/src/io/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 547c184a5c280..ce36ba7ca9e3f 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1000,7 +1000,7 @@ pub trait Read { where Self: Sized, { - Bytes { inner: self } + Bytes { inner: self, byte: 0 } } /// Creates an adapter which will chain this stream with another. @@ -2772,6 +2772,7 @@ impl SizeHint for Take { #[derive(Debug)] pub struct Bytes { inner: R, + byte: u8, } #[stable(feature = "rust1", since = "1.0.0")] @@ -2780,11 +2781,10 @@ impl Iterator for Bytes { #[inline] fn next(&mut self) -> Option> { - let mut byte = 0; loop { - return match self.inner.read(slice::from_mut(&mut byte)) { + return match self.inner.read(slice::from_mut(&mut self.byte)) { Ok(0) => None, - Ok(..) => Some(Ok(byte)), + Ok(..) => Some(Ok(self.byte)), Err(ref e) if e.is_interrupted() => continue, Err(e) => Some(Err(e)), }; From ed2a5871bb41e58b466818109bdae8eb04ea6fb1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 12 Oct 2023 21:50:28 +1100 Subject: [PATCH 3/3] Use `read_exact` in `Bytes::next`. This is much faster. --- library/std/src/io/mod.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index ce36ba7ca9e3f..3c5fa84b87f5b 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2781,13 +2781,10 @@ impl Iterator for Bytes { #[inline] fn next(&mut self) -> Option> { - loop { - return match self.inner.read(slice::from_mut(&mut self.byte)) { - Ok(0) => None, - Ok(..) => Some(Ok(self.byte)), - Err(ref e) if e.is_interrupted() => continue, - Err(e) => Some(Err(e)), - }; + match self.inner.read_exact(slice::from_mut(&mut self.byte)) { + Ok(()) => Some(Ok(self.byte)), + Err(e) if e.kind() == ErrorKind::UnexpectedEof => None, + Err(e) => Some(Err(e)), } }