perf(db): decode and decompress directly from borrowed data instead (#2050)

This commit is contained in:
joshieDo
2023-04-01 01:18:20 +08:00
committed by GitHub
parent e72b2864b2
commit 5900a7e1be
13 changed files with 84 additions and 63 deletions

View File

@@ -3,7 +3,7 @@ use crate::{
transaction::{DbTx, DbTxMut},
Error,
};
use reth_primitives::bytes::Bytes;
use serde::Serialize;
use std::{
fmt::Debug,
@@ -22,7 +22,7 @@ pub trait Compress: Send + Sync + Sized + Debug {
/// Trait that will transform the data to be read from the DB.
pub trait Decompress: Send + Sync + Sized + Debug {
/// Decompresses data coming from the database.
fn decompress<B: Into<Bytes>>(value: B) -> Result<Self, Error>;
fn decompress<B: AsRef<[u8]>>(value: B) -> Result<Self, Error>;
}
/// Trait that will transform the data to be saved in the DB.
@@ -37,7 +37,7 @@ pub trait Encode: Send + Sync + Sized + Debug {
/// Trait that will transform the data to be read from the DB.
pub trait Decode: Send + Sync + Sized + Debug {
/// Decodes data coming from the database.
fn decode<B: Into<Bytes>>(value: B) -> Result<Self, Error>;
fn decode<B: AsRef<[u8]>>(value: B) -> Result<Self, Error>;
}
/// Generic trait that enforces the database key to implement [`Encode`] and [`Decode`].

View File

@@ -23,8 +23,8 @@ macro_rules! impl_compression_for_compact {
impl Decompress for $name
{
fn decompress<B: Into<bytes::Bytes>>(value: B) -> Result<$name, Error> {
let value = value.into();
fn decompress<B: AsRef<[u8]>>(value: B) -> Result<$name, Error> {
let value = value.as_ref();
let (obj, _) = Compact::from_compact(&value, value.len());
Ok(obj)
}

View File

@@ -2,7 +2,6 @@ use crate::{
table::{Compress, Decompress},
Error,
};
use parity_scale_codec::decode_from_bytes;
use reth_primitives::*;
mod sealed {
@@ -27,8 +26,8 @@ impl<T> Decompress for T
where
T: ScaleValue + parity_scale_codec::Decode + Sync + Send + std::fmt::Debug,
{
fn decompress<B: Into<bytes::Bytes>>(value: B) -> Result<T, Error> {
decode_from_bytes(value.into()).map_err(|_| Error::DecodeError)
fn decompress<B: AsRef<[u8]>>(value: B) -> Result<T, Error> {
parity_scale_codec::Decode::decode(&mut value.as_ref()).map_err(|_| Error::DecodeError)
}
}

View File

@@ -6,10 +6,7 @@ use crate::{
Error,
};
use reth_codecs::Compact;
use reth_primitives::{
bytes::{BufMut, Bytes},
Account, Address, TransitionId,
};
use reth_primitives::{bytes::BufMut, Account, Address, TransitionId};
use serde::{Deserialize, Serialize};
/// Account as it is saved inside [`AccountChangeSet`][crate::tables::AccountChangeSet].
@@ -89,12 +86,10 @@ impl Encode for TransitionIdAddress {
}
impl Decode for TransitionIdAddress {
fn decode<B: Into<Bytes>>(value: B) -> Result<Self, Error> {
let value: Bytes = value.into();
let num =
u64::from_be_bytes(value.as_ref()[..8].try_into().map_err(|_| Error::DecodeError)?);
let hash = Address::from_slice(&value.slice(8..));
fn decode<B: AsRef<[u8]>>(value: B) -> Result<Self, Error> {
let value = value.as_ref();
let num = u64::from_be_bytes(value[..8].try_into().map_err(|_| Error::DecodeError)?);
let hash = Address::from_slice(&value[8..]);
Ok(TransitionIdAddress((num, hash)))
}
@@ -121,7 +116,7 @@ mod test {
let encoded = Encode::encode(key);
assert_eq!(encoded, bytes);
let decoded: TransitionIdAddress = Decode::decode(encoded.to_vec()).unwrap();
let decoded: TransitionIdAddress = Decode::decode(encoded).unwrap();
assert_eq!(decoded, key);
}

View File

@@ -4,7 +4,7 @@ use crate::{
table::{Compress, Decompress},
Error,
};
use reth_primitives::{bytes::Bytes, IntegerList};
use reth_primitives::IntegerList;
impl Compress for IntegerList {
type Compressed = Vec<u8>;
@@ -15,7 +15,7 @@ impl Compress for IntegerList {
}
impl Decompress for IntegerList {
fn decompress<B: Into<Bytes>>(value: B) -> Result<Self, Error> {
IntegerList::from_bytes(&value.into()).map_err(|_| Error::DecodeError)
fn decompress<B: AsRef<[u8]>>(value: B) -> Result<Self, Error> {
IntegerList::from_bytes(value.as_ref()).map_err(|_| Error::DecodeError)
}
}

View File

@@ -14,7 +14,7 @@ use crate::{
table::{Decode, Encode},
Error,
};
use reth_primitives::{bytes::Bytes, Address, H256};
use reth_primitives::{Address, H256};
/// Macro that implements [`Encode`] and [`Decode`] for uint types.
macro_rules! impl_uints {
@@ -31,8 +31,7 @@ macro_rules! impl_uints {
impl Decode for $name
{
fn decode<B: Into<Bytes>>(value: B) -> Result<Self, Error> {
let value: Bytes = value.into();
fn decode<B: AsRef<[u8]>>(value: B) -> Result<Self, Error> {
Ok(
$name::from_be_bytes(
value.as_ref().try_into().map_err(|_| Error::DecodeError)?
@@ -54,8 +53,8 @@ impl Encode for Vec<u8> {
}
impl Decode for Vec<u8> {
fn decode<B: Into<Bytes>>(value: B) -> Result<Self, Error> {
Ok(value.into().to_vec())
fn decode<B: AsRef<[u8]>>(value: B) -> Result<Self, Error> {
Ok(value.as_ref().to_vec())
}
}
@@ -67,8 +66,8 @@ impl Encode for Address {
}
impl Decode for Address {
fn decode<B: Into<Bytes>>(value: B) -> Result<Self, Error> {
Ok(Address::from_slice(&value.into()[..]))
fn decode<B: AsRef<[u8]>>(value: B) -> Result<Self, Error> {
Ok(Address::from_slice(value.as_ref()))
}
}
impl Encode for H256 {
@@ -79,8 +78,8 @@ impl Encode for H256 {
}
impl Decode for H256 {
fn decode<B: Into<Bytes>>(value: B) -> Result<Self, Error> {
Ok(H256::from_slice(&value.into()[..]))
fn decode<B: AsRef<[u8]>>(value: B) -> Result<Self, Error> {
Ok(H256::from_slice(value.as_ref()))
}
}
@@ -92,7 +91,7 @@ impl Encode for String {
}
impl Decode for String {
fn decode<B: Into<Bytes>>(value: B) -> Result<Self, Error> {
String::from_utf8(value.into().to_vec()).map_err(|_| Error::DecodeError)
fn decode<B: AsRef<[u8]>>(value: B) -> Result<Self, Error> {
String::from_utf8(value.as_ref().to_vec()).map_err(|_| Error::DecodeError)
}
}

View File

@@ -4,7 +4,7 @@ use crate::{
table::{Decode, Encode},
Error,
};
use reth_primitives::{bytes::Bytes, TransitionId};
use reth_primitives::TransitionId;
/// Number of indices in one shard.
pub const NUM_OF_INDICES_IN_SHARD: usize = 100;
@@ -48,14 +48,14 @@ impl<T> Decode for ShardedKey<T>
where
T: Decode,
{
fn decode<B: Into<Bytes>>(value: B) -> Result<Self, Error> {
let value: Bytes = value.into();
fn decode<B: AsRef<[u8]>>(value: B) -> Result<Self, Error> {
let value = value.as_ref();
let tx_num_index = value.len() - 8;
let highest_tx_number = u64::from_be_bytes(
value.as_ref()[tx_num_index..].try_into().map_err(|_| Error::DecodeError)?,
);
let key = T::decode(value.slice(..tx_num_index))?;
let highest_tx_number =
u64::from_be_bytes(value[tx_num_index..].try_into().map_err(|_| Error::DecodeError)?);
let key = T::decode(&value[..tx_num_index])?;
Ok(ShardedKey::new(key, highest_tx_number))
}

View File

@@ -4,7 +4,7 @@ use crate::{
table::{Decode, Encode},
Error,
};
use reth_primitives::{bytes::Bytes, TransitionId, H160, H256};
use reth_primitives::{TransitionId, H160, H256};
use super::ShardedKey;
@@ -44,15 +44,14 @@ impl Encode for StorageShardedKey {
}
impl Decode for StorageShardedKey {
fn decode<B: Into<Bytes>>(value: B) -> Result<Self, Error> {
let value: Bytes = value.into();
fn decode<B: AsRef<[u8]>>(value: B) -> Result<Self, Error> {
let value = value.as_ref();
let tx_num_index = value.len() - 8;
let highest_tx_number = u64::from_be_bytes(
value.as_ref()[tx_num_index..].try_into().map_err(|_| Error::DecodeError)?,
);
let address = H160::decode(value.slice(..20))?;
let storage_key = H256::decode(value.slice(20..52))?;
let highest_tx_number =
u64::from_be_bytes(value[tx_num_index..].try_into().map_err(|_| Error::DecodeError)?);
let address = H160::decode(&value[..20])?;
let storage_key = H256::decode(&value[20..52])?;
Ok(Self { address, sharded_key: ShardedKey::new(storage_key, highest_tx_number) })
}

View File

@@ -3,7 +3,7 @@ use crate::{
table::{Decode, Decompress, Table},
Error,
};
use reth_primitives::bytes::Bytes;
use std::borrow::Cow;
#[macro_export]
@@ -49,10 +49,15 @@ where
T::Key: Decode,
T::Value: Decompress,
{
Ok((
Decode::decode(Bytes::from(kv.0.into_owned()))?,
Decompress::decompress(Bytes::from(kv.1.into_owned()))?,
))
let key = match kv.0 {
Cow::Borrowed(k) => Decode::decode(k)?,
Cow::Owned(k) => Decode::decode(k)?,
};
let value = match kv.1 {
Cow::Borrowed(v) => Decompress::decompress(v)?,
Cow::Owned(v) => Decompress::decompress(v)?,
};
Ok((key, value))
}
/// Helper function to decode only a value from a `(key, value)` pair.
@@ -60,7 +65,10 @@ pub(crate) fn decode_value<'a, T>(kv: (Cow<'a, [u8]>, Cow<'a, [u8]>)) -> Result<
where
T: Table,
{
Decompress::decompress(Bytes::from(kv.1.into_owned()))
Ok(match kv.1 {
Cow::Borrowed(v) => Decompress::decompress(v)?,
Cow::Owned(v) => Decompress::decompress(v)?,
})
}
/// Helper function to decode a value. It can be a key or subkey.
@@ -68,5 +76,8 @@ pub(crate) fn decode_one<T>(value: Cow<'_, [u8]>) -> Result<T::Value, Error>
where
T: Table,
{
Decompress::decompress(Bytes::from(value.into_owned()))
Ok(match value {
Cow::Borrowed(v) => Decompress::decompress(v)?,
Cow::Owned(v) => Decompress::decompress(v)?,
})
}