From: Matt Corallo Date: Fri, 28 May 2021 14:07:39 +0000 (+0000) Subject: Add additional inline hints in serialization methods X-Git-Tag: v0.0.98~9^2 X-Git-Url: http://git.bitcoin.ninja/?a=commitdiff_plain;h=refs%2Fheads%2F2021-05-ser-fast;p=rust-lightning Add additional inline hints in serialization methods This substantially improves deserialization performance when LLVM decides not to inline many short methods, eg when not building with LTO/codegen-units=1. Even with the default bench params of LTO/codegen-units=1, the serialization benchmarks on an Intel 2687W v3 take: test routing::network_graph::benches::read_network_graph ... bench: 1,955,616,225 ns/iter (+/- 4,135,777) test routing::network_graph::benches::write_network_graph ... bench: 165,905,275 ns/iter (+/- 118,798) --- diff --git a/lightning/src/util/ser.rs b/lightning/src/util/ser.rs index 61cd1e60d..7bc09e7f8 100644 --- a/lightning/src/util/ser.rs +++ b/lightning/src/util/ser.rs @@ -60,13 +60,16 @@ impl Writer for W { pub(crate) struct WriterWriteAdaptor<'a, W: Writer + 'a>(pub &'a mut W); impl<'a, W: Writer + 'a> Write for WriterWriteAdaptor<'a, W> { + #[inline] fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> { self.0.write_all(buf) } + #[inline] fn write(&mut self, buf: &[u8]) -> Result { self.0.write_all(buf)?; Ok(buf.len()) } + #[inline] fn flush(&mut self) -> Result<(), ::std::io::Error> { Ok(()) } @@ -74,10 +77,12 @@ impl<'a, W: Writer + 'a> Write for WriterWriteAdaptor<'a, W> { pub(crate) struct VecWriter(pub Vec); impl Writer for VecWriter { + #[inline] fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> { self.0.extend_from_slice(buf); Ok(()) } + #[inline] fn size_hint(&mut self, size: usize) { self.0.reserve_exact(size); } @@ -108,10 +113,12 @@ impl FixedLengthReader { Self { read, bytes_read: 0, total_bytes } } + #[inline] pub fn bytes_remain(&mut self) -> bool { self.bytes_read != self.total_bytes } + #[inline] pub fn eat_remaining(&mut self) -> Result<(), DecodeError> { ::std::io::copy(self, &mut ::std::io::sink()).unwrap(); if self.bytes_read != self.total_bytes { @@ -122,6 +129,7 @@ impl FixedLengthReader { } } impl Read for FixedLengthReader { + #[inline] fn read(&mut self, dest: &mut [u8]) -> Result { if self.total_bytes == self.bytes_read { Ok(0) @@ -150,6 +158,7 @@ impl ReadTrackingReader { } } impl Read for ReadTrackingReader { + #[inline] fn read(&mut self, dest: &mut [u8]) -> Result { match self.read.read(dest) { Ok(0) => Ok(0), @@ -234,6 +243,7 @@ pub trait MaybeReadable pub(crate) struct OptionDeserWrapper(pub Option); impl Readable for OptionDeserWrapper { + #[inline] fn read(reader: &mut R) -> Result { Ok(Self(Some(Readable::read(reader)?))) } @@ -243,6 +253,7 @@ const MAX_ALLOC_SIZE: u64 = 64*1024; pub(crate) struct VecWriteWrapper<'a, T: Writeable>(pub &'a Vec); impl<'a, T: Writeable> Writeable for VecWriteWrapper<'a, T> { + #[inline] fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { (self.0.len() as u64).write(writer)?; for ref v in self.0.iter() { @@ -253,6 +264,7 @@ impl<'a, T: Writeable> Writeable for VecWriteWrapper<'a, T> { } pub(crate) struct VecReadWrapper(pub Vec); impl Readable for VecReadWrapper { + #[inline] fn read(reader: &mut R) -> Result { let count: u64 = Readable::read(reader)?; let mut values = Vec::with_capacity(cmp::min(count, MAX_ALLOC_SIZE / (core::mem::size_of::() as u64)) as usize);