diff options
| author | bors <bors@rust-lang.org> | 2021-01-17 14:50:24 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-01-17 14:50:24 +0000 |
| commit | edeb631ad0cd6fdf31e2e31ec90e105d1768be28 (patch) | |
| tree | 48c316c067559b3c58d2b652aa836953f0dced5b /library/std/src | |
| parent | 7d3818152d8ab5649d2e5cc6d7851ed7c03055fe (diff) | |
| parent | 801684620bd4e0bc12b98a071851e3d3064429e4 (diff) | |
Auto merge of #81113 - m-ou-se:rollup-a1unz4x, r=m-ou-se
Rollup of 13 pull requests Successful merges: - #79298 (correctly deal with late-bound lifetimes in anon consts) - #80031 (resolve: Reject ambiguity built-in attr vs different built-in attr) - #80201 (Add benchmark and fast path for BufReader::read_exact) - #80635 (Improve diagnostics when closure doesn't meet trait bound) - #80765 (resolve: Simplify collection of traits in scope) - #80932 (Allow downloading LLVM on Windows and MacOS) - #80983 (Remove is_dllimport_foreign_item definition from cg_ssa) - #81064 (Support non-stage0 check) - #81080 (Force vec![] to expression position only) - #81082 (BTreeMap: clean up a few more comments) - #81084 (Use Option::map instead of open-coding it) - #81095 (Use Option::unwrap_or instead of open-coding it) - #81107 (Add NonZeroUn::is_power_of_two) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/io/buffered/bufreader.rs | 14 | ||||
| -rw-r--r-- | library/std/src/io/buffered/tests.rs | 12 | ||||
| -rw-r--r-- | library/std/src/io/mod.rs | 38 |
3 files changed, 47 insertions, 17 deletions
diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 16c18d6e146..8bae3da1273 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -271,6 +271,20 @@ impl<R: Read> Read for BufReader<R> { Ok(nread) } + // Small read_exacts from a BufReader are extremely common when used with a deserializer. + // The default implementation calls read in a loop, which results in surprisingly poor code + // generation for the common path where the buffer has enough bytes to fill the passed-in + // buffer. + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + if self.buffer().len() >= buf.len() { + buf.copy_from_slice(&self.buffer()[..buf.len()]); + self.consume(buf.len()); + return Ok(()); + } + + crate::io::default_read_exact(self, buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { let total_len = bufs.iter().map(|b| b.len()).sum::<usize>(); if self.pos == self.cap && total_len >= self.buf.len() { diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs index 66a64f667ba..f6c2b499567 100644 --- a/library/std/src/io/buffered/tests.rs +++ b/library/std/src/io/buffered/tests.rs @@ -444,6 +444,18 @@ fn bench_buffered_reader(b: &mut test::Bencher) { } #[bench] +fn bench_buffered_reader_small_reads(b: &mut test::Bencher) { + let data = (0..u8::MAX).cycle().take(1024 * 4).collect::<Vec<_>>(); + b.iter(|| { + let mut reader = BufReader::new(&data[..]); + let mut buf = [0u8; 4]; + for _ in 0..1024 { + reader.read_exact(&mut buf).unwrap(); + } + }); +} + +#[bench] fn bench_buffered_writer(b: &mut test::Bencher) { b.iter(|| BufWriter::new(io::sink())); } diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 3f5b7c0b29b..c87a56586c6 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -416,6 +416,25 @@ where write(buf) } +pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [u8]) -> Result<()> { + while !buf.is_empty() { + match this.read(buf) { + Ok(0) => break, + Ok(n) => { + let tmp = buf; + buf = &mut tmp[n..]; + } + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(e) => return Err(e), + } + } + if !buf.is_empty() { + Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer")) + } else { + Ok(()) + } +} + /// The `Read` trait allows for reading bytes from a source. /// /// Implementors of the `Read` trait are called 'readers'. @@ -766,23 +785,8 @@ pub trait Read { /// } /// ``` #[stable(feature = "read_exact", since = "1.6.0")] - fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> { - while !buf.is_empty() { - match self.read(buf) { - Ok(0) => break, - Ok(n) => { - let tmp = buf; - buf = &mut tmp[n..]; - } - Err(ref e) if e.kind() == ErrorKind::Interrupted => {} - Err(e) => return Err(e), - } - } - if !buf.is_empty() { - Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer")) - } else { - Ok(()) - } + fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { + default_read_exact(self, buf) } /// Creates a "by reference" adaptor for this instance of `Read`. |
