From 6a21decae2a8e0b13742cd80b453b90cf4009377 Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Tue, 12 May 2020 12:53:49 +0300 Subject: [PATCH] Fix unnecessary zeroing for AsyncRead implementors --- tokio/src/fs/file.rs | 6 ++++++ tokio/src/io/async_read.rs | 22 ++++++++++++++++++++++ tokio/src/io/blocking.rs | 4 ++++ tokio/src/io/mod.rs | 1 + tokio/src/io/poll_evented.rs | 4 ++++ tokio/src/io/stdin.rs | 5 +++++ tokio/src/io/util/chain.rs | 9 +++++++++ tokio/src/io/util/empty.rs | 3 +++ tokio/src/io/util/repeat.rs | 3 +++ tokio/src/process/mod.rs | 10 ++++++++++ 10 files changed, 67 insertions(+) diff --git a/tokio/src/fs/file.rs b/tokio/src/fs/file.rs index cc4a187d78f..b45d2f2445c 100644 --- a/tokio/src/fs/file.rs +++ b/tokio/src/fs/file.rs @@ -537,6 +537,12 @@ impl File { } impl AsyncRead for File { + unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [std::mem::MaybeUninit]) -> bool { + // std::fs::File does not need zeroing + // https://github.com/rust-lang/rust/blob/09c817eeb29e764cfc12d0a8d94841e3ffe34023/src/libstd/fs.rs#L668 + false + } + fn poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/tokio/src/io/async_read.rs b/tokio/src/io/async_read.rs index cc9091c99c1..5e94a4fb1cd 100644 --- a/tokio/src/io/async_read.rs +++ b/tokio/src/io/async_read.rs @@ -5,6 +5,28 @@ use std::ops::DerefMut; use std::pin::Pin; use std::task::{Context, Poll}; +/// This utility function shoyld be used to override `AsyncRead::prepare_uninitialized_buffer` +/// for any AsyncRead impl which wraps an `std::io::Read` instance. +pub(crate) fn prepare_uninitialized_buffer_std_read( + buf: &mut [MaybeUninit], +) -> bool { + // TODO: when std::io::Initializer is stable, it should be used + // to override `prepare_uninitialized_buffer` + /*use std::io::Read; + if !T::initializer::should_initialize() { + return false; + } + */ + for x in buf { + // we could use safe method x.write(0) here, but it is unstable. + // Safety: as_mut_ptr() returns valid writeable pointer. + unsafe { + x.as_mut_ptr().write(0); + } + } + true +} + /// Reads bytes from a source. /// /// This trait is analogous to the [`std::io::Read`] trait, but integrates with diff --git a/tokio/src/io/blocking.rs b/tokio/src/io/blocking.rs index 2491039a3f3..ff4445e76d0 100644 --- a/tokio/src/io/blocking.rs +++ b/tokio/src/io/blocking.rs @@ -50,6 +50,10 @@ impl AsyncRead for Blocking where T: Read + Unpin + Send + 'static, { + unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [std::mem::MaybeUninit]) -> bool { + crate::io::prepare_uninitialized_buffer_std_read::(buf) + } + fn poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/tokio/src/io/mod.rs b/tokio/src/io/mod.rs index 29d8bc5554e..59e278fd42b 100644 --- a/tokio/src/io/mod.rs +++ b/tokio/src/io/mod.rs @@ -163,6 +163,7 @@ pub use self::async_buf_read::AsyncBufRead; mod async_read; pub use self::async_read::AsyncRead; +pub(crate) use self::async_read::prepare_uninitialized_buffer_std_read; mod async_seek; pub use self::async_seek::AsyncSeek; diff --git a/tokio/src/io/poll_evented.rs b/tokio/src/io/poll_evented.rs index f8be6f2f755..c02302b4cb0 100644 --- a/tokio/src/io/poll_evented.rs +++ b/tokio/src/io/poll_evented.rs @@ -381,6 +381,10 @@ impl AsyncRead for PollEvented where E: Evented + Read + Unpin, { + unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [std::mem::MaybeUninit]) -> bool { + crate::io::prepare_uninitialized_buffer_std_read::(buf) + } + fn poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/tokio/src/io/stdin.rs b/tokio/src/io/stdin.rs index d986d3abeaf..325b8757ec1 100644 --- a/tokio/src/io/stdin.rs +++ b/tokio/src/io/stdin.rs @@ -63,6 +63,11 @@ impl std::os::windows::io::AsRawHandle for Stdin { } impl AsyncRead for Stdin { + unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [std::mem::MaybeUninit]) -> bool { + // https://github.com/rust-lang/rust/blob/09c817eeb29e764cfc12d0a8d94841e3ffe34023/src/libstd/io/stdio.rs#L97 + false + } + fn poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/tokio/src/io/util/chain.rs b/tokio/src/io/util/chain.rs index bc76af341da..8ba9194f5de 100644 --- a/tokio/src/io/util/chain.rs +++ b/tokio/src/io/util/chain.rs @@ -84,6 +84,15 @@ where T: AsyncRead, U: AsyncRead, { + unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [std::mem::MaybeUninit]) -> bool { + if self.first.prepare_uninitialized_buffer(buf) { + return true; + } + if self.second.prepare_uninitialized_buffer(buf) { + return true; + } + false + } fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/tokio/src/io/util/empty.rs b/tokio/src/io/util/empty.rs index 121102c78f2..576058d52d1 100644 --- a/tokio/src/io/util/empty.rs +++ b/tokio/src/io/util/empty.rs @@ -47,6 +47,9 @@ cfg_io_util! { } impl AsyncRead for Empty { + unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [std::mem::MaybeUninit]) -> bool { + false + } #[inline] fn poll_read( self: Pin<&mut Self>, diff --git a/tokio/src/io/util/repeat.rs b/tokio/src/io/util/repeat.rs index 6b9067e8534..eeef7cc187b 100644 --- a/tokio/src/io/util/repeat.rs +++ b/tokio/src/io/util/repeat.rs @@ -47,6 +47,9 @@ cfg_io_util! { } impl AsyncRead for Repeat { + unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [std::mem::MaybeUninit]) -> bool { + false + } #[inline] fn poll_read( self: Pin<&mut Self>, diff --git a/tokio/src/process/mod.rs b/tokio/src/process/mod.rs index 7231511235e..f32b8cbe3aa 100644 --- a/tokio/src/process/mod.rs +++ b/tokio/src/process/mod.rs @@ -872,6 +872,11 @@ impl AsyncWrite for ChildStdin { } impl AsyncRead for ChildStdout { + unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [std::mem::MaybeUninit]) -> bool { + // https://github.com/rust-lang/rust/blob/09c817eeb29e764cfc12d0a8d94841e3ffe34023/src/libstd/process.rs#L314 + false + } + fn poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, @@ -882,6 +887,11 @@ impl AsyncRead for ChildStdout { } impl AsyncRead for ChildStderr { + unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [std::mem::MaybeUninit]) -> bool { + // https://github.com/rust-lang/rust/blob/09c817eeb29e764cfc12d0a8d94841e3ffe34023/src/libstd/process.rs#L375 + false + } + fn poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>,