mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-15 19:41:05 +00:00
State machine local child root cache. (#9107)
* cache root for child api. * minimal testing * Reset cache on test 'set_root'. * Update primitives/state-machine/src/trie_backend_essence.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update primitives/state-machine/src/trie_backend_essence.rs * Update primitives/state-machine/src/trie_backend_essence.rs * Renaming to 'reset_cache'. * correct rust fmt Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
@@ -326,6 +326,22 @@ pub mod tests {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
Some(vec![142u8]),
|
Some(vec![142u8]),
|
||||||
);
|
);
|
||||||
|
// Change cache entry to check that caching is active.
|
||||||
|
test_trie
|
||||||
|
.essence
|
||||||
|
.cache
|
||||||
|
.write()
|
||||||
|
.child_root
|
||||||
|
.entry(b"sub1".to_vec())
|
||||||
|
.and_modify(|value| {
|
||||||
|
*value = None;
|
||||||
|
});
|
||||||
|
assert_eq!(
|
||||||
|
test_trie
|
||||||
|
.child_storage(&ChildInfo::new_default(CHILD_KEY_1), b"value3")
|
||||||
|
.unwrap(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
use crate::{backend::Consolidate, debug, warn, StorageKey, StorageValue};
|
use crate::{backend::Consolidate, debug, warn, StorageKey, StorageValue};
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use hash_db::{self, Hasher, Prefix};
|
use hash_db::{self, Hasher, Prefix};
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use parking_lot::RwLock;
|
||||||
use sp_core::storage::ChildInfo;
|
use sp_core::storage::ChildInfo;
|
||||||
use sp_std::{boxed::Box, ops::Deref, vec::Vec};
|
use sp_std::{boxed::Box, ops::Deref, vec::Vec};
|
||||||
use sp_trie::{
|
use sp_trie::{
|
||||||
@@ -29,6 +31,8 @@ use sp_trie::{
|
|||||||
DBValue, KeySpacedDB, MemoryDB, PrefixedMemoryDB, Trie, TrieDBIterator,
|
DBValue, KeySpacedDB, MemoryDB, PrefixedMemoryDB, Trie, TrieDBIterator,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
use std::collections::HashMap;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
@@ -46,11 +50,26 @@ pub trait Storage<H: Hasher>: Send + Sync {
|
|||||||
fn get(&self, key: &H::Out, prefix: Prefix) -> Result<Option<DBValue>>;
|
fn get(&self, key: &H::Out, prefix: Prefix) -> Result<Option<DBValue>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Local cache for child root.
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub(crate) struct Cache {
|
||||||
|
pub child_root: HashMap<Vec<u8>, Option<Vec<u8>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl Cache {
|
||||||
|
fn new() -> Self {
|
||||||
|
Cache { child_root: HashMap::new() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Patricia trie-based pairs storage essence.
|
/// Patricia trie-based pairs storage essence.
|
||||||
pub struct TrieBackendEssence<S: TrieBackendStorage<H>, H: Hasher> {
|
pub struct TrieBackendEssence<S: TrieBackendStorage<H>, H: Hasher> {
|
||||||
storage: S,
|
storage: S,
|
||||||
root: H::Out,
|
root: H::Out,
|
||||||
empty: H::Out,
|
empty: H::Out,
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub(crate) cache: Arc<RwLock<Cache>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H>
|
impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H>
|
||||||
@@ -59,7 +78,13 @@ where
|
|||||||
{
|
{
|
||||||
/// Create new trie-based backend.
|
/// Create new trie-based backend.
|
||||||
pub fn new(storage: S, root: H::Out) -> Self {
|
pub fn new(storage: S, root: H::Out) -> Self {
|
||||||
TrieBackendEssence { storage, root, empty: H::hash(&[0u8]) }
|
TrieBackendEssence {
|
||||||
|
storage,
|
||||||
|
root,
|
||||||
|
empty: H::hash(&[0u8]),
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
cache: Arc::new(RwLock::new(Cache::new())),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get backend storage reference.
|
/// Get backend storage reference.
|
||||||
@@ -79,9 +104,19 @@ where
|
|||||||
|
|
||||||
/// Set trie root. This is useful for testing.
|
/// Set trie root. This is useful for testing.
|
||||||
pub fn set_root(&mut self, root: H::Out) {
|
pub fn set_root(&mut self, root: H::Out) {
|
||||||
|
// If root did change so can have cached content.
|
||||||
|
self.reset_cache();
|
||||||
self.root = root;
|
self.root = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
fn reset_cache(&mut self) {
|
||||||
|
self.cache = Arc::new(RwLock::new(Cache::new()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
fn reset_cache(&mut self) {}
|
||||||
|
|
||||||
/// Consumes self and returns underlying storage.
|
/// Consumes self and returns underlying storage.
|
||||||
pub fn into_storage(self) -> S {
|
pub fn into_storage(self) -> S {
|
||||||
self.storage
|
self.storage
|
||||||
@@ -95,7 +130,24 @@ where
|
|||||||
|
|
||||||
/// Access the root of the child storage in its parent trie
|
/// Access the root of the child storage in its parent trie
|
||||||
fn child_root(&self, child_info: &ChildInfo) -> Result<Option<StorageValue>> {
|
fn child_root(&self, child_info: &ChildInfo) -> Result<Option<StorageValue>> {
|
||||||
self.storage(child_info.prefixed_storage_key().as_slice())
|
#[cfg(feature = "std")]
|
||||||
|
{
|
||||||
|
if let Some(result) = self.cache.read().child_root.get(child_info.storage_key()) {
|
||||||
|
return Ok(result.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = self.storage(child_info.prefixed_storage_key().as_slice())?;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
{
|
||||||
|
self.cache
|
||||||
|
.write()
|
||||||
|
.child_root
|
||||||
|
.insert(child_info.storage_key().to_vec(), result.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the next key in the child trie i.e. the minimum key that is strictly superior to
|
/// Return the next key in the child trie i.e. the minimum key that is strictly superior to
|
||||||
|
|||||||
Reference in New Issue
Block a user