]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Pre-allocate the full `Vec` prior to serializing as a `Vec<u8>`
authorMatt Corallo <git@bluematt.me>
Sat, 4 Nov 2023 21:01:18 +0000 (21:01 +0000)
committerMatt Corallo <git@bluematt.me>
Tue, 7 Nov 2023 04:12:30 +0000 (04:12 +0000)
We end up generating a substantial amount of allocations just
doubling `Vec`s when serializing to them, and our
`serialized_length` method is generally rather effecient, so we
just rely on it and allocate correctly up front.

lightning/src/util/ser.rs

index 85b991c61d43674970f588c93add1228722b219c..64d59da0d1c23c7712e9ac06e2ab65cf08326d52 100644 (file)
@@ -199,8 +199,14 @@ pub trait Writeable {
 
        /// Writes `self` out to a `Vec<u8>`.
        fn encode(&self) -> Vec<u8> {
-               let mut msg = VecWriter(Vec::new());
+               let len = self.serialized_length();
+               let mut msg = VecWriter(Vec::with_capacity(len));
                self.write(&mut msg).unwrap();
+               // Note that objects with interior mutability may change size between when we called
+               // serialized_length and when we called write. That's okay, but shouldn't happen during
+               // testing as most of our tests are not threaded.
+               #[cfg(test)]
+               debug_assert_eq!(len, msg.0.len());
                msg.0
        }
 
@@ -211,6 +217,7 @@ pub trait Writeable {
                0u16.write(&mut msg).unwrap();
                self.write(&mut msg).unwrap();
                let len = msg.0.len();
+               debug_assert_eq!(len - 2, self.serialized_length());
                msg.0[..2].copy_from_slice(&(len as u16 - 2).to_be_bytes());
                msg.0
        }