mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-04-30 03:01:58 -04:00
perf(db): decode and decompress directly from borrowed data instead (#2050)
This commit is contained in:
@@ -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`].
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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) })
|
||||
}
|
||||
|
||||
@@ -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)?,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user