]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Optimize `BufReader` somewhat for the only used case
authorMatt Corallo <git@bluematt.me>
Fri, 16 Aug 2024 18:47:38 +0000 (18:47 +0000)
committerMatt Corallo <git@bluematt.me>
Mon, 19 Aug 2024 14:55:28 +0000 (14:55 +0000)
`rust-bitcoin` doesn't ever actually *use* its `BufRead`
requirement when deserializing objects, and forcing it is somewhat
inefficient, so we optimize the only (actual) case here by passing
reads straight through to the backing stream.

lightning/src/util/ser.rs

index fbe1933a0cb18c00d4328dc7071d88d5d93a900d..de54a14f2f778db575a304a222f924c3601f6c55 100644 (file)
@@ -66,6 +66,7 @@ impl<W: Write> Writer for W {
        }
 }
 
+// TODO: Drop this entirely if rust-bitcoin releases a version bump with https://github.com/rust-bitcoin/rust-bitcoin/pull/3173
 /// Wrap buffering support for implementations of Read.
 /// A [`Read`]er which keeps an internal buffer to avoid hitting the underlying stream directly for
 /// every read, implementing [`BufRead`].
@@ -92,17 +93,21 @@ impl<'a, R: Read> BufReader<'a, R> {
 impl<'a, R: Read> Read for BufReader<'a, R> {
        #[inline]
        fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
-               let input = self.fill_buf()?;
-               let count = cmp::min(input.len(), output.len());
-               output[..count].copy_from_slice(&input[..count]);
-               self.consume(count);
-               Ok(count)
+               if output.is_empty() { return Ok(0); }
+               let mut offset = 0;
+               if !self.is_consumed {
+                       output[0] = self.buf[0];
+                       self.is_consumed = true;
+                       offset = 1;
+               }
+               self.inner.read(&mut output[offset..]).map(|len| len + offset)
        }
 }
 
 impl<'a, R: Read> BufRead for BufReader<'a, R> {
        #[inline]
        fn fill_buf(&mut self) -> io::Result<&[u8]> {
+               debug_assert!(false, "rust-bitcoin doesn't actually use this");
                if self.is_consumed {
                        let count = self.inner.read(&mut self.buf[..])?;
                        debug_assert!(count <= 1, "read gave us a garbage length");
@@ -120,6 +125,7 @@ impl<'a, R: Read> BufRead for BufReader<'a, R> {
 
        #[inline]
        fn consume(&mut self, amount: usize) {
+               debug_assert!(false, "rust-bitcoin doesn't actually use this");
                if amount >= 1 {
                        debug_assert_eq!(amount, 1, "Can only consume one byte");
                        debug_assert!(!self.is_consumed, "Cannot consume more than had been read");