diff options
author | Neal H. Walfield <neal@pep.foundation> | 2019-10-30 17:00:22 +0100 |
---|---|---|
committer | Neal H. Walfield <neal@pep.foundation> | 2019-10-30 17:10:55 +0100 |
commit | 001d04bfc89c3dc9ab06f703ff15cbb1c66f1dc9 (patch) | |
tree | 6db79487ee671d08157d37a488127d33e2965697 /buffered-reader/src | |
parent | f893274486c61e0a4709e8d36e88c72efdc1446e (diff) |
openpgp,buffered-reader: Optimize Vec<u8>::truncate manually
- On debug builds, Vec<u8>::truncate is very, very slow. For
instance, running the decrypt_test_stream test takes 51 seconds on
my (Neal's) computer using Vec<u8>::truncate and <0.1 seconds using
`unsafe { v.set_len(len); }`.
The issue is that the compiler calls drop on every element that is
dropped, even though a u8 doesn't have a drop implementation. The
compiler optimizes this away at high optimization levels, but
those levels make debugging harder.
Diffstat (limited to 'buffered-reader/src')
-rw-r--r-- | buffered-reader/src/generic.rs | 3 | ||||
-rw-r--r-- | buffered-reader/src/lib.rs | 19 |
2 files changed, 20 insertions, 2 deletions
diff --git a/buffered-reader/src/generic.rs b/buffered-reader/src/generic.rs index de1a52c7..7b5dd540 100644 --- a/buffered-reader/src/generic.rs +++ b/buffered-reader/src/generic.rs @@ -131,7 +131,6 @@ impl<T: io::Read, C> Generic<T, C> { if amount_read > 0 { // We read something. - if let Some(ref buffer) = self.buffer { // We need to copy in the old data. buffer_new[0..amount_buffered] @@ -139,7 +138,7 @@ impl<T: io::Read, C> Generic<T, C> { &buffer[self.cursor..self.cursor + amount_buffered]); } - buffer_new.truncate(amount_buffered + amount_read); + vec_truncate(&mut buffer_new, amount_buffered + amount_read); buffer_new.shrink_to_fit(); self.buffer = Some(buffer_new.into_boxed_slice()); diff --git a/buffered-reader/src/lib.rs b/buffered-reader/src/lib.rs index 129eaa9c..bf0f899f 100644 --- a/buffered-reader/src/lib.rs +++ b/buffered-reader/src/lib.rs @@ -275,6 +275,25 @@ pub use self::file_unix::File; // The default buffer size. const DEFAULT_BUF_SIZE: usize = 8 * 1024; +// On debug builds, Vec<u8>::truncate is very, very slow. For +// instance, running the decrypt_test_stream test takes 51 seconds on +// my (Neal's) computer using Vec<u8>::truncate and <0.1 seconds using +// `unsafe { v.set_len(len); }`. +// +// The issue is that the compiler calls drop on every element that is +// dropped, even though a u8 doesn't have a drop implementation. The +// compiler optimizes this away at high optimization levels, but those +// levels make debugging harder. +fn vec_truncate(v: &mut Vec<u8>, len: usize) { + if cfg!(debug_assertions) { + if len < v.len() { + unsafe { v.set_len(len); } + } + } else { + v.truncate(len); + } +} + /// The generic `BufferReader` interface. pub trait BufferedReader<C> : io::Read + fmt::Debug + fmt::Display { /// Returns a reference to the internal buffer. |