summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2023-01-06 11:39:05 +0100
committerNeal H. Walfield <neal@pep.foundation>2023-01-06 12:41:41 +0100
commit3e188fb312ad4db1395f5e836bffaf2034b88a42 (patch)
tree9dd82f9c1b845a28b6da8b3ea8616b49bb1aa824
parent81c471292d3b15f48d236f8432aacf2b734f9d1e (diff)
buffered-reader, openpgp: Fix buffering.
- When `buffered_reader::Generic::data_helper` is called and the amount of data that is requested exceeds the amount of data that is available, we read from the underlying reader. - When determining how much to read from the underlying reader, we took the maximum of the amount requested and the default buffer size, and then subtracted the amount of data that is available. - This means that when the amount requested is greater than the buffer size, we would read exactly the amount requested. This is problematic for two reasons. First, it is not unusual for a user of a `BufferedReader` to not consume the data (e.g., a `buffer_reader::Dup` never consumes data). In that case, once calls to `BufferedReader::data` request more than the default buffer size, the `BufferedReader` would forward any reads to the underlying reader, and append the result to the available data to create a single continuous `Vec<u8>`. Second, many of these reads are for just one more byte than is available. The consequence is that once the amount requested exceeds the amount available, many subsequent reads would read from the underlying reader, and `memcpy` the data held by the `BufferedReader`, which destroyed the performance. - Avoid most of the reads and the `memcpy`s by changing the behavior of `buffered_reader::Generic::data_helper` as follows: if the amount requested exceeds the amount available, try to read the amount requested plus the buffer size minus what is available. - Make the same change to `openpgp::armor::Reader`. - Fixes #969. Co-authored-by: Justus Winter <justus@sequoia-pgp.org>
-rw-r--r--buffered-reader/src/generic.rs5
-rw-r--r--openpgp/src/armor.rs5
2 files changed, 4 insertions, 6 deletions
diff --git a/buffered-reader/src/generic.rs b/buffered-reader/src/generic.rs
index cff30b5e..309dfcf6 100644
--- a/buffered-reader/src/generic.rs
+++ b/buffered-reader/src/generic.rs
@@ -139,9 +139,8 @@ impl<T: io::Read + Send + Sync, C: fmt::Debug + Sync + Send> Generic<T, C> {
// The caller wants more data than we have readily
// available. Read some more.
- let capacity : usize = cmp::max(cmp::max(
- default_buf_size(),
- 2 * self.preferred_chunk_size), amount);
+ let capacity : usize = amount
+ + cmp::max(default_buf_size(), 2 * self.preferred_chunk_size);
let mut buffer_new = self.unused_buffer.take()
.map(|mut v| {
diff --git a/openpgp/src/armor.rs b/openpgp/src/armor.rs
index 144df004..08a16f46 100644
--- a/openpgp/src/armor.rs
+++ b/openpgp/src/armor.rs
@@ -1554,9 +1554,8 @@ impl<'a> Reader<'a> {
// The caller wants more data than we have readily
// available. Read some more.
- let capacity : usize = cmp::max(cmp::max(
- DEFAULT_BUF_SIZE,
- 2 * self.preferred_chunk_size), amount);
+ let capacity : usize = amount
+ + cmp::max(DEFAULT_BUF_SIZE, 2 * self.preferred_chunk_size);
let mut buffer_new = self.unused_buffer.take()
.map(|mut v| {