mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 15:11:03 +00:00
State cache and other performance optimizations (#1345)
* State caching * Better code caching * Execution optimizaton * More optimizations * Updated wasmi * Caching test * Style * Style * Reverted some minor changes * Style and typos * Style and typos * Removed panics on missing memory
This commit is contained in:
committed by
Gav Wood
parent
e0639c435b
commit
b104c02eb6
@@ -40,10 +40,15 @@ pub trait Backend<H: Hasher> {
|
||||
/// Type of trie backend storage.
|
||||
type TrieBackendStorage: TrieBackendStorage<H>;
|
||||
|
||||
/// Get keyed storage associated with specific address, or None if there is nothing associated.
|
||||
/// Get keyed storage or None if there is nothing associated.
|
||||
fn storage(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error>;
|
||||
|
||||
/// Get keyed child storage associated with specific address, or None if there is nothing associated.
|
||||
/// Get keyed storage value hash or None if there is nothing associated.
|
||||
fn storage_hash(&self, key: &[u8]) -> Result<Option<H::Out>, Self::Error> {
|
||||
self.storage(key).map(|v| v.map(|v| H::hash(&v)))
|
||||
}
|
||||
|
||||
/// Get keyed child storage or None if there is nothing associated.
|
||||
fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error>;
|
||||
|
||||
/// true if a key exists in storage.
|
||||
|
||||
@@ -184,6 +184,11 @@ where
|
||||
self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL))
|
||||
}
|
||||
|
||||
fn storage_hash(&self, key: &[u8]) -> Option<H::Out> {
|
||||
self.overlay.storage(key).map(|x| x.map(|x| H::hash(x))).unwrap_or_else(||
|
||||
self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL))
|
||||
}
|
||||
|
||||
fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Option<Vec<u8>> {
|
||||
self.overlay.child_storage(storage_key, key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(||
|
||||
self.backend.child_storage(storage_key, key).expect(EXT_NOT_ALLOWED_TO_FAIL))
|
||||
|
||||
@@ -65,9 +65,6 @@ pub use proving_backend::{create_proof_check_backend, create_proof_check_backend
|
||||
pub use trie_backend_essence::{TrieBackendStorage, Storage};
|
||||
pub use trie_backend::TrieBackend;
|
||||
|
||||
/// Default num of pages for the heap
|
||||
const DEFAULT_HEAP_PAGES :u64 = 1024;
|
||||
|
||||
/// State Machine Error bound.
|
||||
///
|
||||
/// This should reflect WASM error type bound for future compatibility.
|
||||
@@ -98,10 +95,15 @@ impl fmt::Display for ExecutionError {
|
||||
|
||||
/// Externalities: pinned to specific active address.
|
||||
pub trait Externalities<H: Hasher> {
|
||||
/// Read storage of current contract being called.
|
||||
/// Read runtime storage.
|
||||
fn storage(&self, key: &[u8]) -> Option<Vec<u8>>;
|
||||
|
||||
/// Read child storage of current contract being called.
|
||||
/// Get storage value hash. This may be optimized for large values.
|
||||
fn storage_hash(&self, key: &[u8]) -> Option<H::Out> {
|
||||
self.storage(key).map(|v| H::hash(&v))
|
||||
}
|
||||
|
||||
/// Read child runtime storage.
|
||||
fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Option<Vec<u8>>;
|
||||
|
||||
/// Set storage entry `key` of current contract being called (effective immediately).
|
||||
@@ -171,8 +173,6 @@ pub trait CodeExecutor<H: Hasher>: Sized + Send + Sync {
|
||||
fn call<E: Externalities<H>>(
|
||||
&self,
|
||||
ext: &mut E,
|
||||
heap_pages: usize,
|
||||
code: &[u8],
|
||||
method: &str,
|
||||
data: &[u8],
|
||||
use_native: bool
|
||||
@@ -297,14 +297,6 @@ where
|
||||
{
|
||||
let strategy: ExecutionStrategy = (&manager).into();
|
||||
|
||||
// make a copy.
|
||||
let code = try_read_overlay_value(overlay, backend, well_known_keys::CODE)?
|
||||
.ok_or_else(|| Box::new(ExecutionError::CodeEntryDoesNotExist) as Box<Error>)?
|
||||
.to_vec();
|
||||
|
||||
let heap_pages = try_read_overlay_value(overlay, backend, well_known_keys::HEAP_PAGES)?
|
||||
.and_then(|v| u64::decode(&mut &v[..])).unwrap_or(DEFAULT_HEAP_PAGES) as usize;
|
||||
|
||||
// read changes trie configuration. The reason why we're doing it here instead of the
|
||||
// `OverlayedChanges` constructor is that we need proofs for this read as a part of
|
||||
// proof-of-execution on light clients. And the proof is recorded by the backend which
|
||||
@@ -328,8 +320,6 @@ where
|
||||
let mut externalities = ext::Ext::new(overlay, backend, changes_trie_storage);
|
||||
let retval = exec.call(
|
||||
&mut externalities,
|
||||
heap_pages,
|
||||
&code,
|
||||
method,
|
||||
call_data,
|
||||
// attempt to run native first, if we're not directed to run wasm only
|
||||
@@ -357,8 +347,6 @@ where
|
||||
let mut externalities = ext::Ext::new(overlay, backend, changes_trie_storage);
|
||||
let retval = exec.call(
|
||||
&mut externalities,
|
||||
heap_pages,
|
||||
&code,
|
||||
method,
|
||||
call_data,
|
||||
false,
|
||||
@@ -614,8 +602,6 @@ mod tests {
|
||||
fn call<E: Externalities<H>>(
|
||||
&self,
|
||||
ext: &mut E,
|
||||
_heap_pages: usize,
|
||||
_code: &[u8],
|
||||
_method: &str,
|
||||
_data: &[u8],
|
||||
use_native: bool
|
||||
|
||||
@@ -44,7 +44,7 @@ pub struct OverlayedValue {
|
||||
/// Current value. None if value has been deleted.
|
||||
pub value: Option<Vec<u8>>,
|
||||
/// The set of extinsic indices where the values has been changed.
|
||||
/// Is filled only if runtime ahs announced changes trie support.
|
||||
/// Is filled only if runtime has announced changes trie support.
|
||||
pub extrinsics: Option<HashSet<u32>>,
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ use heapsize::HeapSizeOf;
|
||||
use trie::trie_root;
|
||||
use backend::InMemory;
|
||||
use changes_trie::{compute_changes_trie_root, InMemoryStorage as ChangesTrieInMemoryStorage, AnchorBlockId};
|
||||
use primitives::storage::well_known_keys::CHANGES_TRIE_CONFIG;
|
||||
use primitives::storage::well_known_keys::{CHANGES_TRIE_CONFIG, CODE, HEAP_PAGES};
|
||||
use codec::Encode;
|
||||
use super::{Externalities, OverlayedChanges};
|
||||
|
||||
/// Simple HashMap-based Externalities impl.
|
||||
@@ -31,11 +32,17 @@ pub struct TestExternalities<H: Hasher> where H::Out: HeapSizeOf {
|
||||
inner: HashMap<Vec<u8>, Vec<u8>>,
|
||||
changes_trie_storage: ChangesTrieInMemoryStorage<H>,
|
||||
changes: OverlayedChanges,
|
||||
code: Vec<u8>,
|
||||
}
|
||||
|
||||
impl<H: Hasher> TestExternalities<H> where H::Out: HeapSizeOf {
|
||||
/// Create a new instance of `TestExternalities`
|
||||
pub fn new(inner: HashMap<Vec<u8>, Vec<u8>>) -> Self {
|
||||
Self::new_with_code(&[], inner)
|
||||
}
|
||||
|
||||
/// Create a new instance of `TestExternalities`
|
||||
pub fn new_with_code(code: &[u8], inner: HashMap<Vec<u8>, Vec<u8>>) -> Self {
|
||||
let mut overlay = OverlayedChanges::default();
|
||||
super::set_changes_trie_config(
|
||||
&mut overlay,
|
||||
@@ -47,6 +54,7 @@ impl<H: Hasher> TestExternalities<H> where H::Out: HeapSizeOf {
|
||||
inner,
|
||||
changes_trie_storage: ChangesTrieInMemoryStorage::new(),
|
||||
changes: overlay,
|
||||
code: code.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,13 +102,18 @@ impl<H: Hasher> From< HashMap<Vec<u8>, Vec<u8>> > for TestExternalities<H> where
|
||||
inner: hashmap,
|
||||
changes_trie_storage: ChangesTrieInMemoryStorage::new(),
|
||||
changes: Default::default(),
|
||||
code: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: Hasher> Externalities<H> for TestExternalities<H> where H::Out: Ord + HeapSizeOf {
|
||||
fn storage(&self, key: &[u8]) -> Option<Vec<u8>> {
|
||||
self.inner.get(key).map(|x| x.to_vec())
|
||||
match key {
|
||||
CODE => Some(self.code.clone()),
|
||||
HEAP_PAGES => Some(8u64.encode()),
|
||||
_ => self.inner.get(key).map(|x| x.to_vec()),
|
||||
}
|
||||
}
|
||||
|
||||
fn child_storage(&self, _storage_key: &[u8], _key: &[u8]) -> Option<Vec<u8>> {
|
||||
|
||||
Reference in New Issue
Block a user