From fa1ec2028d48dd8ffe4d6efa3698ddd0242b9260 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 23 May 2019 13:14:43 -0400 Subject: [PATCH] Speed up Vec [d]e[n]code operations by dropping the generic --- src/consensus/encode.rs | 63 +++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 452a2708..90e4d2f1 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -45,6 +45,10 @@ use secp256k1; use util::base58; use util::psbt; +use blockdata::transaction::{TxOut, Transaction, TxIn}; +use network::message_blockdata::Inventory; +use network::address::Address; + /// Encoding error #[derive(Debug)] pub enum Error { @@ -551,27 +555,62 @@ impl Encodable for [u16; 8] { } // Vectors -impl> Encodable for Vec { +macro_rules! impl_vec { + ($type: ty) => { + impl Encodable for Vec<$type> { + #[inline] + fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { + VarInt(self.len() as u64).consensus_encode(s)?; + for c in self.iter() { c.consensus_encode(s)?; } + Ok(()) + } + } + + impl Decodable for Vec<$type> { + #[inline] + fn consensus_decode(d: &mut D) -> Result, self::Error> { + let len = VarInt::consensus_decode(d)?.0; + let byte_size = (len as usize) + .checked_mul(mem::size_of::<$type>()) + .ok_or(self::Error::ParseFailed("Invalid length"))?; + if byte_size > MAX_VEC_SIZE { + return Err(self::Error::OversizedVectorAllocation { requested: byte_size, max: MAX_VEC_SIZE }) + } + let mut ret = Vec::with_capacity(len as usize); + for _ in 0..len { ret.push(Decodable::consensus_decode(d)?); } + Ok(ret) + } + } + } +} +impl_vec!(sha256d::Hash); +impl_vec!(Transaction); +impl_vec!(TxOut); +impl_vec!(TxIn); +impl_vec!(Inventory); +impl_vec!(Vec); +impl_vec!((u32, Address)); +impl_vec!(u64); + +impl Encodable for Vec { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { VarInt(self.len() as u64).consensus_encode(s)?; - for c in self.iter() { c.consensus_encode(s)?; } - Ok(()) + s.emit_slice(&self) } } -impl> Decodable for Vec { +impl Decodable for Vec { #[inline] - fn consensus_decode(d: &mut D) -> Result, self::Error> { + fn consensus_decode(d: &mut D) -> Result, self::Error> { let len = VarInt::consensus_decode(d)?.0; - let byte_size = (len as usize) - .checked_mul(mem::size_of::()) - .ok_or(self::Error::ParseFailed("Invalid length"))?; - if byte_size > MAX_VEC_SIZE { - return Err(self::Error::OversizedVectorAllocation { requested: byte_size, max: MAX_VEC_SIZE }) + let len = len as usize; + if len > MAX_VEC_SIZE { + return Err(self::Error::OversizedVectorAllocation { requested: len, max: MAX_VEC_SIZE }) } - let mut ret = Vec::with_capacity(len as usize); - for _ in 0..len { ret.push(Decodable::consensus_decode(d)?); } + let mut ret = Vec::with_capacity(len); + ret.resize(len, 0); + d.read_slice(&mut ret)?; Ok(ret) } }