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
+11 -12
View File
@@ -79,12 +79,12 @@ impl<B: BlockT> BenchmarkingState<B> {
};
state.reopen()?;
let child_delta = genesis.children_default.into_iter().map(|(_storage_key, child_content)| (
child_content.child_info,
child_content.data.into_iter().map(|(k, v)| (k, Some(v))),
let child_delta = genesis.children_default.iter().map(|(_storage_key, child_content)| (
&child_content.child_info,
child_content.data.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))),
));
let (root, transaction): (B::Hash, _) = state.state.borrow_mut().as_mut().unwrap().full_storage_root(
genesis.top.into_iter().map(|(k, v)| (k, Some(v))),
genesis.top.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))),
child_delta,
);
state.genesis = transaction.clone().drain();
@@ -193,19 +193,18 @@ impl<B: BlockT> StateBackend<HashFor<B>> for BenchmarkingState<B> {
}
}
fn storage_root<I>(&self, delta: I) -> (B::Hash, Self::Transaction) where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>
{
fn storage_root<'a>(
&self,
delta: impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
) -> (B::Hash, Self::Transaction) where B::Hash: Ord {
self.state.borrow().as_ref().map_or(Default::default(), |s| s.storage_root(delta))
}
fn child_storage_root<I>(
fn child_storage_root<'a>(
&self,
child_info: &ChildInfo,
delta: I,
) -> (B::Hash, bool, Self::Transaction) where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
{
delta: impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord {
self.state.borrow().as_ref().map_or(Default::default(), |s| s.child_storage_root(child_info, delta))
}
+22 -30
View File
@@ -212,21 +212,18 @@ impl<B: BlockT> StateBackend<HashFor<B>> for RefTrackingState<B> {
self.state.for_child_keys_with_prefix(child_info, prefix, f)
}
fn storage_root<I>(&self, delta: I) -> (B::Hash, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>
{
fn storage_root<'a>(
&self,
delta: impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
) -> (B::Hash, Self::Transaction) where B::Hash: Ord {
self.state.storage_root(delta)
}
fn child_storage_root<I>(
fn child_storage_root<'a>(
&self,
child_info: &ChildInfo,
delta: I,
) -> (B::Hash, bool, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
{
delta: impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord {
self.state.child_storage_root(child_info, delta)
}
@@ -605,26 +602,25 @@ impl<Block: BlockT> sc_client_api::backend::BlockImportOperation<Block> for Bloc
&mut self,
storage: Storage,
) -> ClientResult<Block::Hash> {
if storage.top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) {
if storage.top.keys().any(|k| well_known_keys::is_child_storage_key(&k)) {
return Err(sp_blockchain::Error::GenesisInvalid.into());
}
let child_delta = storage.children_default.into_iter().map(|(_storage_key, child_content)|(
child_content.child_info,
child_content.data.into_iter().map(|(k, v)| (k, Some(v))),
let child_delta = storage.children_default.iter().map(|(_storage_key, child_content)|(
&child_content.child_info,
child_content.data.iter().map(|(k, v)| (&k[..], Some(&v[..]))),
));
let mut changes_trie_config: Option<ChangesTrieConfiguration> = None;
let (root, transaction) = self.old_state.full_storage_root(
storage.top.into_iter().map(|(k, v)| {
if k == well_known_keys::CHANGES_TRIE_CONFIG {
storage.top.iter().map(|(k, v)| {
if &k[..] == well_known_keys::CHANGES_TRIE_CONFIG {
changes_trie_config = Some(
Decode::decode(&mut &v[..])
.expect("changes trie configuration is encoded properly at genesis")
);
}
(k, Some(v))
(&k[..], Some(&v[..]))
}),
child_delta
);
@@ -1810,13 +1806,12 @@ pub(crate) mod tests {
header.state_root = op.old_state.storage_root(storage
.iter()
.cloned()
.map(|(x, y)| (x, Some(y)))
.map(|(x, y)| (&x[..], Some(&y[..])))
).0.into();
let hash = header.hash();
op.reset_storage(Storage {
top: storage.iter().cloned().collect(),
top: storage.into_iter().collect(),
children_default: Default::default(),
}).unwrap();
op.set_block_data(
@@ -1853,7 +1848,10 @@ pub(crate) mod tests {
(vec![5, 5, 5], Some(vec![4, 5, 6])),
];
let (root, overlay) = op.old_state.storage_root(storage.iter().cloned());
let (root, overlay) = op.old_state.storage_root(
storage.iter()
.map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..])))
);
op.update_db_storage(overlay).unwrap();
header.state_root = root.into();
@@ -1892,17 +1890,11 @@ pub(crate) mod tests {
extrinsics_root: Default::default(),
};
let storage: Vec<(_, _)> = vec![];
header.state_root = op.old_state.storage_root(storage
.iter()
.cloned()
.map(|(x, y)| (x, Some(y)))
).0.into();
header.state_root = op.old_state.storage_root(std::iter::empty()).0.into();
let hash = header.hash();
op.reset_storage(Storage {
top: storage.iter().cloned().collect(),
top: Default::default(),
children_default: Default::default(),
}).unwrap();
+14 -20
View File
@@ -621,21 +621,18 @@ impl<S: StateBackend<HashFor<B>>, B: BlockT> StateBackend<HashFor<B>> for Cachin
self.state.for_child_keys_with_prefix(child_info, prefix, f)
}
fn storage_root<I>(&self, delta: I) -> (B::Hash, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
{
fn storage_root<'a>(
&self,
delta: impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
) -> (B::Hash, Self::Transaction) where B::Hash: Ord {
self.state.storage_root(delta)
}
fn child_storage_root<I>(
fn child_storage_root<'a>(
&self,
child_info: &ChildInfo,
delta: I,
) -> (B::Hash, bool, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
{
delta: impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord {
self.state.child_storage_root(child_info, delta)
}
@@ -806,21 +803,18 @@ impl<S: StateBackend<HashFor<B>>, B: BlockT> StateBackend<HashFor<B>> for Syncin
self.caching_state().for_child_keys_with_prefix(child_info, prefix, f)
}
fn storage_root<I>(&self, delta: I) -> (B::Hash, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
{
fn storage_root<'a>(
&self,
delta: impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
) -> (B::Hash, Self::Transaction) where B::Hash: Ord {
self.caching_state().storage_root(delta)
}
fn child_storage_root<I>(
fn child_storage_root<'a>(
&self,
child_info: &ChildInfo,
delta: I,
) -> (B::Hash, bool, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
{
delta: impl Iterator<Item=(&'a [u8], Option<&'a [u8]>)>,
) -> (B::Hash, bool, Self::Transaction) where B::Hash: Ord {
self.caching_state().child_storage_root(child_info, delta)
}