From a3c77e3fff771b168b53bd9b3a69c31a6775857b Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Wed, 3 Nov 2021 14:46:11 +0100 Subject: buffered-reader: Recycle buffers. - Previously, we spent a considerable amount of time callocing new buffers. --- buffered-reader/src/generic.rs | 16 ++++++++++++---- buffered-reader/src/lib.rs | 9 +++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'buffered-reader') diff --git a/buffered-reader/src/generic.rs b/buffered-reader/src/generic.rs index eed96d5e..f54fe6b2 100644 --- a/buffered-reader/src/generic.rs +++ b/buffered-reader/src/generic.rs @@ -12,9 +12,11 @@ use super::*; /// [`Memory`]. Both are more efficient than `Generic`. /// pub struct Generic { - buffer: Option>, + buffer: Option>, // The next byte to read in the buffer. cursor: usize, + /// Currently unused buffer. + unused_buffer: Option>, // The preferred chunk size. This is just a hint. preferred_chunk_size: usize, // The wrapped reader. @@ -71,6 +73,7 @@ impl Generic { Generic { buffer: None, cursor: 0, + unused_buffer: None, preferred_chunk_size: if let Some(s) = preferred_chunk_size { s } else { DEFAULT_BUF_SIZE }, @@ -135,7 +138,12 @@ impl Generic { DEFAULT_BUF_SIZE, 2 * self.preferred_chunk_size), amount); - let mut buffer_new : Vec = vec![0u8; capacity]; + let mut buffer_new = self.unused_buffer.take() + .map(|mut v| { + vec_resize(&mut v, capacity); + v + }) + .unwrap_or_else(|| vec![0u8; capacity]); let mut amount_read = 0; while amount_buffered + amount_read < amount { @@ -170,9 +178,9 @@ impl Generic { } vec_truncate(&mut buffer_new, amount_buffered + amount_read); - buffer_new.shrink_to_fit(); - self.buffer = Some(buffer_new.into_boxed_slice()); + self.unused_buffer = self.buffer.take(); + self.buffer = Some(buffer_new); self.cursor = 0; } } diff --git a/buffered-reader/src/lib.rs b/buffered-reader/src/lib.rs index 89b897ea..e973af4e 100644 --- a/buffered-reader/src/lib.rs +++ b/buffered-reader/src/lib.rs @@ -301,6 +301,15 @@ fn vec_truncate(v: &mut Vec, len: usize) { } } +/// Like `Vec::resize`, but fast in debug builds. +fn vec_resize(v: &mut Vec, new_size: usize) { + if v.len() < new_size { + v.resize(new_size, 0); + } else { + vec_truncate(v, new_size); + } +} + /// The generic `BufferReader` interface. pub trait BufferedReader : io::Read + fmt::Debug + fmt::Display + Send + Sync where C: fmt::Debug + Send + Sync -- cgit v1.2.3