summaryrefslogtreecommitdiffstats
path: root/buffered-reader
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2019-10-30 17:00:22 +0100
committerNeal H. Walfield <neal@pep.foundation>2019-10-30 17:10:55 +0100
commit001d04bfc89c3dc9ab06f703ff15cbb1c66f1dc9 (patch)
tree6db79487ee671d08157d37a488127d33e2965697 /buffered-reader
parentf893274486c61e0a4709e8d36e88c72efdc1446e (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')
-rw-r--r--buffered-reader/src/generic.rs3
-rw-r--r--buffered-reader/src/lib.rs19
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.