mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 09:51:10 +00:00
State metrics possible changes (#5168)
* Registering state from overlay. * fix * fix2 * Apply suggestions from code review Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
@@ -206,13 +206,16 @@ pub trait Backend<H: Hasher>: std::fmt::Debug {
|
||||
(root, txs)
|
||||
}
|
||||
|
||||
/// Register stats from overlay of state machine.
|
||||
///
|
||||
/// By default nothing is registered.
|
||||
fn register_overlay_stats(&mut self, _stats: &crate::stats::StateMachineStats);
|
||||
|
||||
/// Query backend usage statistics (i/o, memory)
|
||||
///
|
||||
/// Not all implementations are expected to be able to do this. In the
|
||||
/// case when they don't, empty statistics is returned.
|
||||
fn usage_info(&self) -> UsageInfo {
|
||||
UsageInfo::empty()
|
||||
}
|
||||
fn usage_info(&self) -> UsageInfo;
|
||||
|
||||
/// Wipe the state database.
|
||||
fn wipe(&self) -> Result<(), Self::Error> {
|
||||
@@ -308,10 +311,12 @@ impl<'a, T: Backend<H>, H: Hasher> Backend<H> for &'a T {
|
||||
(*self).for_key_values_with_prefix(prefix, f);
|
||||
}
|
||||
|
||||
fn register_overlay_stats(&mut self, _stats: &crate::stats::StateMachineStats) { }
|
||||
|
||||
fn usage_info(&self) -> UsageInfo {
|
||||
(*self).usage_info()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait that allows consolidate two transactions together.
|
||||
pub trait Consolidate {
|
||||
|
||||
@@ -469,6 +469,7 @@ mod test {
|
||||
].into_iter().collect(),
|
||||
},
|
||||
collect_extrinsics: true,
|
||||
stats: Default::default(),
|
||||
};
|
||||
let config = Configuration { digest_interval: 4, digest_levels: 2 };
|
||||
|
||||
|
||||
@@ -587,6 +587,7 @@ mod tests {
|
||||
].into_iter().collect(),
|
||||
committed: Default::default(),
|
||||
collect_extrinsics: true,
|
||||
stats: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ use crate::{
|
||||
StorageKey, StorageValue, StorageCollection,
|
||||
trie_backend::TrieBackend,
|
||||
backend::{Backend, insert_into_memory_db},
|
||||
stats::UsageInfo,
|
||||
};
|
||||
use std::{error, fmt, collections::{BTreeMap, HashMap}, marker::PhantomData, ops};
|
||||
use hash_db::Hasher;
|
||||
@@ -357,6 +358,12 @@ impl<H: Hasher> Backend<H> for InMemory<H> where H::Out: Codec {
|
||||
self.trie = Some(TrieBackend::new(mdb, root));
|
||||
self.trie.as_ref()
|
||||
}
|
||||
|
||||
fn register_overlay_stats(&mut self, _stats: &crate::stats::StateMachineStats) { }
|
||||
|
||||
fn usage_info(&self) -> UsageInfo {
|
||||
UsageInfo::empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use std::{fmt, result, collections::HashMap, panic::UnwindSafe, marker::PhantomData};
|
||||
use std::{fmt, result, collections::HashMap, panic::UnwindSafe};
|
||||
use log::{warn, trace};
|
||||
use hash_db::Hasher;
|
||||
use codec::{Decode, Encode, Codec};
|
||||
@@ -73,7 +73,7 @@ pub use trie_backend_essence::{TrieBackendStorage, Storage};
|
||||
pub use trie_backend::TrieBackend;
|
||||
pub use error::{Error, ExecutionError};
|
||||
pub use in_memory_backend::InMemory as InMemoryBackend;
|
||||
pub use stats::{UsageInfo, UsageUnit};
|
||||
pub use stats::{UsageInfo, UsageUnit, StateMachineStats};
|
||||
pub use sp_core::traits::CloneableSpawn;
|
||||
|
||||
type CallResult<R, E> = Result<NativeOrEncoded<R>, E>;
|
||||
@@ -189,9 +189,19 @@ pub struct StateMachine<'a, B, H, N, Exec>
|
||||
overlay: &'a mut OverlayedChanges,
|
||||
extensions: Extensions,
|
||||
changes_trie_state: Option<ChangesTrieState<'a, H, N>>,
|
||||
_marker: PhantomData<(H, N)>,
|
||||
storage_transaction_cache: Option<&'a mut StorageTransactionCache<B::Transaction, H, N>>,
|
||||
runtime_code: &'a RuntimeCode<'a>,
|
||||
stats: StateMachineStats,
|
||||
}
|
||||
|
||||
impl<'a, B, H, N, Exec> Drop for StateMachine<'a, B, H, N, Exec> where
|
||||
H: Hasher,
|
||||
B: Backend<H>,
|
||||
N: ChangesTrieBlockNumber,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.backend.register_overlay_stats(&self.stats);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, B, H, N, Exec> StateMachine<'a, B, H, N, Exec> where
|
||||
@@ -224,9 +234,9 @@ impl<'a, B, H, N, Exec> StateMachine<'a, B, H, N, Exec> where
|
||||
extensions,
|
||||
overlay,
|
||||
changes_trie_state,
|
||||
_marker: PhantomData,
|
||||
storage_transaction_cache: None,
|
||||
runtime_code,
|
||||
stats: StateMachineStats::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ use crate::{
|
||||
NO_EXTRINSIC_INDEX, BlockNumber, build_changes_trie,
|
||||
State as ChangesTrieState,
|
||||
},
|
||||
stats::StateMachineStats,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -57,6 +58,8 @@ pub struct OverlayedChanges {
|
||||
pub(crate) committed: OverlayedChangeSet,
|
||||
/// True if extrinsics stats must be collected.
|
||||
pub(crate) collect_extrinsics: bool,
|
||||
/// Collect statistic on this execution.
|
||||
pub(crate) stats: StateMachineStats,
|
||||
}
|
||||
|
||||
/// The storage value, used inside OverlayedChanges.
|
||||
@@ -206,7 +209,11 @@ impl OverlayedChanges {
|
||||
pub fn storage(&self, key: &[u8]) -> Option<Option<&[u8]>> {
|
||||
self.prospective.top.get(key)
|
||||
.or_else(|| self.committed.top.get(key))
|
||||
.map(|x| x.value.as_ref().map(AsRef::as_ref))
|
||||
.map(|x| {
|
||||
let size_read = x.value.as_ref().map(|x| x.len() as u64).unwrap_or(0);
|
||||
self.stats.tally_read_modified(size_read);
|
||||
x.value.as_ref().map(AsRef::as_ref)
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a double-Option: None if the key is unknown (i.e. and the query should be referred
|
||||
@@ -215,12 +222,16 @@ impl OverlayedChanges {
|
||||
pub fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Option<Option<&[u8]>> {
|
||||
if let Some(map) = self.prospective.children.get(storage_key) {
|
||||
if let Some(val) = map.0.get(key) {
|
||||
let size_read = val.value.as_ref().map(|x| x.len() as u64).unwrap_or(0);
|
||||
self.stats.tally_read_modified(size_read);
|
||||
return Some(val.value.as_ref().map(AsRef::as_ref));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(map) = self.committed.children.get(storage_key) {
|
||||
if let Some(val) = map.0.get(key) {
|
||||
let size_read = val.value.as_ref().map(|x| x.len() as u64).unwrap_or(0);
|
||||
self.stats.tally_read_modified(size_read);
|
||||
return Some(val.value.as_ref().map(AsRef::as_ref));
|
||||
}
|
||||
}
|
||||
@@ -232,6 +243,8 @@ impl OverlayedChanges {
|
||||
///
|
||||
/// `None` can be used to delete a value specified by the given key.
|
||||
pub(crate) fn set_storage(&mut self, key: StorageKey, val: Option<StorageValue>) {
|
||||
let size_write = val.as_ref().map(|x| x.len() as u64).unwrap_or(0);
|
||||
self.stats.tally_write_overlay(size_write);
|
||||
let extrinsic_index = self.extrinsic_index();
|
||||
let entry = self.prospective.top.entry(key).or_default();
|
||||
entry.value = val;
|
||||
@@ -252,6 +265,8 @@ impl OverlayedChanges {
|
||||
key: StorageKey,
|
||||
val: Option<StorageValue>,
|
||||
) {
|
||||
let size_write = val.as_ref().map(|x| x.len() as u64).unwrap_or(0);
|
||||
self.stats.tally_write_overlay(size_write);
|
||||
let extrinsic_index = self.extrinsic_index();
|
||||
let map_entry = self.prospective.children.entry(storage_key)
|
||||
.or_insert_with(|| (Default::default(), child_info.to_owned()));
|
||||
|
||||
@@ -283,6 +283,12 @@ impl<'a, S, H> Backend<H> for ProvingBackend<'a, S, H>
|
||||
{
|
||||
self.0.child_storage_root(storage_key, child_info, delta)
|
||||
}
|
||||
|
||||
fn register_overlay_stats(&mut self, _stats: &crate::stats::StateMachineStats) { }
|
||||
|
||||
fn usage_info(&self) -> crate::stats::UsageInfo {
|
||||
self.0.usage_info()
|
||||
}
|
||||
}
|
||||
|
||||
/// Create proof check backend.
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
//! Usage statistics for state db
|
||||
|
||||
use std::time::{Instant, Duration};
|
||||
use std::cell::RefCell;
|
||||
|
||||
/// Measured count of operations and total bytes.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
@@ -32,10 +33,19 @@ pub struct UsageUnit {
|
||||
pub struct UsageInfo {
|
||||
/// Read statistics (total).
|
||||
pub reads: UsageUnit,
|
||||
/// Write statistics.
|
||||
/// Write statistics (total).
|
||||
pub writes: UsageUnit,
|
||||
/// Write trie nodes statistics.
|
||||
pub nodes_writes: UsageUnit,
|
||||
/// Write into cached state machine
|
||||
/// change overlay.
|
||||
pub overlay_writes: UsageUnit,
|
||||
/// Removed trie nodes statistics.
|
||||
pub removed_nodes: UsageUnit,
|
||||
/// Cache read statistics.
|
||||
pub cache_reads: UsageUnit,
|
||||
/// Modified value read statistics.
|
||||
pub modified_reads: UsageUnit,
|
||||
/// Memory used.
|
||||
pub memory: usize,
|
||||
|
||||
@@ -45,6 +55,35 @@ pub struct UsageInfo {
|
||||
pub span: Duration,
|
||||
}
|
||||
|
||||
/// Accumulated usage statistics specific to state machine
|
||||
/// crate.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct StateMachineStats {
|
||||
/// Number of read query from runtime
|
||||
/// that hit a modified value (in state
|
||||
/// machine overlay).
|
||||
pub reads_modified: RefCell<u64>,
|
||||
/// Size in byte of read queries that
|
||||
/// hit a modified value.
|
||||
pub bytes_read_modified: RefCell<u64>,
|
||||
/// Number of time a write operation
|
||||
/// occurs into the state machine overlay.
|
||||
pub writes_overlay: RefCell<u64>,
|
||||
/// Size in bytes of the writes overlay
|
||||
/// operation.
|
||||
pub bytes_writes_overlay: RefCell<u64>,
|
||||
}
|
||||
|
||||
impl StateMachineStats {
|
||||
/// Accumulates some registered stats.
|
||||
pub fn add(&self, other: &StateMachineStats) {
|
||||
*self.reads_modified.borrow_mut() += *other.reads_modified.borrow();
|
||||
*self.bytes_read_modified.borrow_mut() += *other.bytes_read_modified.borrow();
|
||||
*self.writes_overlay.borrow_mut() += *other.writes_overlay.borrow();
|
||||
*self.bytes_writes_overlay.borrow_mut() += *other.bytes_writes_overlay.borrow();
|
||||
}
|
||||
}
|
||||
|
||||
impl UsageInfo {
|
||||
/// Empty statistics.
|
||||
///
|
||||
@@ -53,10 +92,34 @@ impl UsageInfo {
|
||||
Self {
|
||||
reads: UsageUnit::default(),
|
||||
writes: UsageUnit::default(),
|
||||
overlay_writes: UsageUnit::default(),
|
||||
nodes_writes: UsageUnit::default(),
|
||||
removed_nodes: UsageUnit::default(),
|
||||
cache_reads: UsageUnit::default(),
|
||||
modified_reads: UsageUnit::default(),
|
||||
memory: 0,
|
||||
started: Instant::now(),
|
||||
span: Default::default(),
|
||||
}
|
||||
}
|
||||
/// Add collected state machine to this state.
|
||||
pub fn include_state_machine_states(&mut self, count: &StateMachineStats) {
|
||||
self.modified_reads.ops += *count.reads_modified.borrow();
|
||||
self.modified_reads.bytes += *count.bytes_read_modified.borrow();
|
||||
self.overlay_writes.ops += *count.writes_overlay.borrow();
|
||||
self.overlay_writes.bytes += *count.bytes_writes_overlay.borrow();
|
||||
}
|
||||
}
|
||||
|
||||
impl StateMachineStats {
|
||||
/// Tally one read modified operation, of some length.
|
||||
pub fn tally_read_modified(&self, data_bytes: u64) {
|
||||
*self.reads_modified.borrow_mut() += 1;
|
||||
*self.bytes_read_modified.borrow_mut() += data_bytes;
|
||||
}
|
||||
/// Tally one write overlay operation, of some length.
|
||||
pub fn tally_write_overlay(&self, data_bytes: u64) {
|
||||
*self.writes_overlay.borrow_mut() += 1;
|
||||
*self.bytes_writes_overlay.borrow_mut() += data_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +240,12 @@ impl<S: TrieBackendStorage<H>, H: Hasher> Backend<H> for TrieBackend<S, H> where
|
||||
fn as_trie_backend(&mut self) -> Option<&TrieBackend<Self::TrieBackendStorage, H>> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
fn register_overlay_stats(&mut self, _stats: &crate::stats::StateMachineStats) { }
|
||||
|
||||
fn usage_info(&self) -> crate::UsageInfo {
|
||||
crate::UsageInfo::empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user