Open
Description
ByteQueue::push
uses the standard library's Read::read_to_end
. To avoid making uninitialized data available to the Read
implementation, it currently initializes the buffer before passing it to read
.
It looks like there's currently an internal / nightly API for marking a reader as promising not to read the buffer it's passed, in which case the initialization will be skipped.
- https://doc.rust-lang.org/src/std/io/mod.rs.html#391
- https://doc.rust-lang.org/std/io/trait.Read.html#method.initializer
In the meantime we may want to replace our usage of read_to_end
with something that doesn't pre-initialize.
Example from a perf
report, in a benchmark reading and writing 64 KB buffers via a pipe:
- 18.48% 0.26% 4 worker-0 shadow [.] shadow_rs::utility::byte_queue::ByteQueue::push
- 18.22% shadow_rs::utility::byte_queue::ByteQueue::push
- 16.16% <std::io::Take<T> as std::io::Read>::read_to_end
+ 8.80% <shadow_rs::host::memory_manager::MemoryReaderCursor as std::io::Read>::read
6.47% __memset_avx2_erms
We spend almost as much time zeroing the buffer (__memset_avx2_erms
) as copying the data (read
)