Don't clone values when calculating storage root (#6108)

* Don't clone values when calculating storage root

Instead of cloning all the keys and values of the overlay when
calculating the storage root, we pass all the values by reference. This
should probably bring some performance improvements when calculating the
storage root.

* no cow version (#6113)

Co-authored-by: cheme <emericchevalier.pro@gmail.com>
This commit is contained in:
Bastian Köcher
2020-05-23 11:28:34 +02:00
committed by GitHub
parent 40f3c7348e
commit 82a832bc3a
12 changed files with 165 additions and 187 deletions
@@ -20,7 +20,6 @@
use hash_db::Hasher;
use codec::{Decode, Encode};
use sp_core::{traits::RuntimeCode, storage::{ChildInfo, well_known_keys}};
use crate::{
trie_backend::TrieBackend,
trie_backend_essence::TrieBackendStorage,
@@ -119,22 +118,19 @@ pub trait Backend<H: Hasher>: std::fmt::Debug {
/// Calculate the storage root, with given delta over what is already stored in
/// the backend, and produce a "transaction" that can be used to commit.
/// Does not include child storage updates.
fn storage_root<I>(&self, delta: I) -> (H::Out, Self::Transaction)
where
I: IntoIterator<Item=(StorageKey, Option<StorageValue>)>,
H::Out: Ord;
fn storage_root<'a>(
&self,
delta: impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
) -> (H::Out, Self::Transaction) where H::Out: Ord;
/// Calculate the child storage root, with given delta over what is already stored in
/// the backend, and produce a "transaction" that can be used to commit. The second argument
/// is true if child storage root equals default storage root.
fn child_storage_root<I>(
fn child_storage_root<'a>(
&self,
child_info: &ChildInfo,
delta: I,
) -> (H::Out, bool, Self::Transaction)
where
I: IntoIterator<Item=(StorageKey, Option<StorageValue>)>,
H::Out: Ord;
delta: impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
) -> (H::Out, bool, Self::Transaction) where H::Out: Ord;
/// Get all key/value pairs into a Vec.
fn pairs(&self) -> Vec<(StorageKey, StorageValue)>;
@@ -165,17 +161,14 @@ pub trait Backend<H: Hasher>: std::fmt::Debug {
/// Calculate the storage root, with given delta over what is already stored
/// in the backend, and produce a "transaction" that can be used to commit.
/// Does include child storage updates.
fn full_storage_root<I1, I2i, I2>(
fn full_storage_root<'a>(
&self,
delta: I1,
child_deltas: I2)
-> (H::Out, Self::Transaction)
where
I1: IntoIterator<Item=(StorageKey, Option<StorageValue>)>,
I2i: IntoIterator<Item=(StorageKey, Option<StorageValue>)>,
I2: IntoIterator<Item=(ChildInfo, I2i)>,
H::Out: Ord + Encode,
{
delta: impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
child_deltas: impl Iterator<Item = (
&'a ChildInfo,
impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
)>,
) -> (H::Out, Self::Transaction) where H::Out: Ord + Encode {
let mut txs: Self::Transaction = Default::default();
let mut child_roots: Vec<_> = Default::default();
// child first
@@ -190,8 +183,13 @@ pub trait Backend<H: Hasher>: std::fmt::Debug {
child_roots.push((prefixed_storage_key.into_inner(), Some(child_root.encode())));
}
}
let (root, parent_txs) = self.storage_root(
delta.into_iter().chain(child_roots.into_iter())
let (root, parent_txs) = self.storage_root(delta
.map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..])))
.chain(
child_roots
.iter()
.map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..])))
)
);
txs.consolidate(parent_txs);
(root, txs)
@@ -214,7 +212,7 @@ pub trait Backend<H: Hasher>: std::fmt::Debug {
}
/// Commit given transaction to storage.
fn commit(&self, _storage_root: H::Out, _transaction: Self::Transaction) -> Result<(), Self::Error> {
fn commit(&self, _: H::Out, _: Self::Transaction) -> Result<(), Self::Error> {
unimplemented!()
}
}
@@ -269,23 +267,18 @@ impl<'a, T: Backend<H>, H: Hasher> Backend<H> for &'a T {
(*self).for_child_keys_with_prefix(child_info, prefix, f)
}
fn storage_root<I>(&self, delta: I) -> (H::Out, Self::Transaction)
where
I: IntoIterator<Item=(StorageKey, Option<StorageValue>)>,
H::Out: Ord,
{
fn storage_root<'b>(
&self,
delta: impl Iterator<Item=(&'b [u8], Option<&'b [u8]>)>,
) -> (H::Out, Self::Transaction) where H::Out: Ord {
(*self).storage_root(delta)
}
fn child_storage_root<I>(
fn child_storage_root<'b>(
&self,
child_info: &ChildInfo,
delta: I,
) -> (H::Out, bool, Self::Transaction)
where
I: IntoIterator<Item=(StorageKey, Option<StorageValue>)>,
H::Out: Ord,
{
delta: impl Iterator<Item=(&'b [u8], Option<&'b [u8]>)>,
) -> (H::Out, bool, Self::Transaction) where H::Out: Ord {
(*self).child_storage_root(child_info, delta)
}