From 1f8cff8390e18a7eda1550e0536294951611f3b0 Mon Sep 17 00:00:00 2001 From: Tayfun Elmas Date: Fri, 26 Apr 2024 16:36:30 -0700 Subject: [PATCH 01/15] Initial commit. --- chain/chain/src/chain_update.rs | 6 +++-- chain/chain/src/runtime/mod.rs | 12 ++++++--- chain/chain/src/runtime/tests.rs | 1 + chain/chain/src/test_utils/kv_runtime.rs | 7 ++--- chain/chain/src/types.rs | 23 ++++++++++++++++ chain/chain/src/update_shard.rs | 11 ++++++-- .../chunk_validator/mod.rs | 6 +++-- runtime/runtime/src/metrics.rs | 27 ++++++++++++++++++- tools/state-viewer/src/apply_chain_range.rs | 6 +++-- tools/state-viewer/src/apply_chunk.rs | 5 ++-- tools/state-viewer/src/commands.rs | 11 ++++---- 11 files changed, 92 insertions(+), 23 deletions(-) diff --git a/chain/chain/src/chain_update.rs b/chain/chain/src/chain_update.rs index 3c0b1c37302..1fa6d3cd93d 100644 --- a/chain/chain/src/chain_update.rs +++ b/chain/chain/src/chain_update.rs @@ -4,8 +4,8 @@ use crate::metrics::{SHARD_LAYOUT_NUM_SHARDS, SHARD_LAYOUT_VERSION}; use crate::store::{ChainStore, ChainStoreAccess, ChainStoreUpdate}; use crate::types::{ - ApplyChunkBlockContext, ApplyChunkResult, ApplyChunkShardContext, ReshardingResults, - RuntimeAdapter, RuntimeStorageConfig, + ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, ApplyChunkShardContext, + ReshardingResults, RuntimeAdapter, RuntimeStorageConfig, }; use crate::update_shard::{NewChunkResult, OldChunkResult, ReshardingResult, ShardUpdateResult}; use crate::{metrics, DoomslugThresholdMode}; @@ -738,6 +738,7 @@ impl<'a> ChainUpdate<'a> { let apply_result = self.runtime_adapter.apply_chunk( RuntimeStorageConfig::new(chunk_header.prev_state_root(), true), + ApplyChunkReason::UpdateShard, ApplyChunkShardContext { shard_id, gas_limit, @@ -835,6 +836,7 @@ impl<'a> ChainUpdate<'a> { let apply_result = self.runtime_adapter.apply_chunk( RuntimeStorageConfig::new(*chunk_extra.state_root(), true), + ApplyChunkReason::UpdateShard, ApplyChunkShardContext { shard_id, last_validator_proposals: chunk_extra.validator_proposals(), diff --git a/chain/chain/src/runtime/mod.rs b/chain/chain/src/runtime/mod.rs index 401a462ba93..70a94a9d2dd 100644 --- a/chain/chain/src/runtime/mod.rs +++ b/chain/chain/src/runtime/mod.rs @@ -1,7 +1,8 @@ use crate::types::{ - ApplyChunkBlockContext, ApplyChunkResult, ApplyChunkShardContext, ApplyResultForResharding, - PrepareTransactionsBlockContext, PrepareTransactionsChunkContext, PrepareTransactionsLimit, - PreparedTransactions, RuntimeAdapter, RuntimeStorageConfig, StorageDataSource, Tip, + ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, ApplyChunkShardContext, + ApplyResultForResharding, PrepareTransactionsBlockContext, PrepareTransactionsChunkContext, + PrepareTransactionsLimit, PreparedTransactions, RuntimeAdapter, RuntimeStorageConfig, + StorageDataSource, Tip, }; use crate::Error; use borsh::BorshDeserialize; @@ -246,6 +247,7 @@ impl NightshadeRuntime { fn process_state_update( &self, trie: Trie, + apply_reason: ApplyChunkReason, chunk: ApplyChunkShardContext, block: ApplyChunkBlockContext, receipts: &[Receipt], @@ -420,7 +422,7 @@ impl NightshadeRuntime { .with_label_values(&[&shard_label]) .set(apply_result.delayed_receipts_count as i64); if let Some(mut metrics) = apply_result.metrics { - metrics.report(&shard_label); + metrics.report(&shard_label, &apply_reason.to_string()); } let total_balance_burnt = apply_result @@ -864,6 +866,7 @@ impl RuntimeAdapter for NightshadeRuntime { fn apply_chunk( &self, storage_config: RuntimeStorageConfig, + apply_reason: ApplyChunkReason, chunk: ApplyChunkShardContext, block: ApplyChunkBlockContext, receipts: &[Receipt], @@ -903,6 +906,7 @@ impl RuntimeAdapter for NightshadeRuntime { match self.process_state_update( trie, + apply_reason, chunk, block, receipts, diff --git a/chain/chain/src/runtime/tests.rs b/chain/chain/src/runtime/tests.rs index c5a3b8414ab..f98d0a0fe51 100644 --- a/chain/chain/src/runtime/tests.rs +++ b/chain/chain/src/runtime/tests.rs @@ -81,6 +81,7 @@ impl NightshadeRuntime { let mut result = self .apply_chunk( RuntimeStorageConfig::new(*state_root, true), + ApplyChunkReason::UpdateShard, ApplyChunkShardContext { shard_id, last_validator_proposals, diff --git a/chain/chain/src/test_utils/kv_runtime.rs b/chain/chain/src/test_utils/kv_runtime.rs index 561bce24571..a69822877f9 100644 --- a/chain/chain/src/test_utils/kv_runtime.rs +++ b/chain/chain/src/test_utils/kv_runtime.rs @@ -1,8 +1,8 @@ use super::ValidatorSchedule; use crate::types::{ - ApplyChunkBlockContext, ApplyChunkResult, ApplyChunkShardContext, ApplyResultForResharding, - PrepareTransactionsBlockContext, PrepareTransactionsChunkContext, PreparedTransactions, - RuntimeAdapter, RuntimeStorageConfig, + ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, ApplyChunkShardContext, + ApplyResultForResharding, PrepareTransactionsBlockContext, PrepareTransactionsChunkContext, + PreparedTransactions, RuntimeAdapter, RuntimeStorageConfig, }; use crate::BlockHeader; use borsh::{BorshDeserialize, BorshSerialize}; @@ -1101,6 +1101,7 @@ impl RuntimeAdapter for KeyValueRuntime { fn apply_chunk( &self, storage_config: RuntimeStorageConfig, + _apply_reason: ApplyChunkReason, chunk: ApplyChunkShardContext, block: ApplyChunkBlockContext, receipts: &[Receipt], diff --git a/chain/chain/src/types.rs b/chain/chain/src/types.rs index b657e68cfce..8405e959e9e 100644 --- a/chain/chain/src/types.rs +++ b/chain/chain/src/types.rs @@ -34,6 +34,7 @@ use near_store::flat::FlatStorageManager; use near_store::{PartialStorage, ShardTries, Store, Trie, WrappedTrieChanges}; use num_rational::Rational32; use std::collections::HashMap; +use std::fmt::{Display, Formatter}; #[derive(Eq, PartialEq, Debug, Clone)] pub enum BlockStatus { @@ -276,6 +277,27 @@ impl RuntimeStorageConfig { } } +/// Indicates in which phase of block production the apply is invoked. +/// This is currently used for debugging and tracking metrics. +/// TODO: Consider combining ApplyChunKReason, ApplyChunkBlockContext, and ApplyChunkBlockContext +/// under a common wrapper struct such as ApplyChunkContext. +#[derive(Clone, Debug)] +pub enum ApplyChunkReason { + /// Applying chunk to update the shards being tracked. + UpdateShard, + /// Applying chunk to validate the chunk in the case of stateless validation.n + ValidateChunk, +} + +impl Display for ApplyChunkReason { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + f.write_str(match self { + ApplyChunkReason::UpdateShard => "update_shard", + ApplyChunkReason::ValidateChunk => "validate_chunk", + }) + } +} + #[derive(Clone)] pub struct ApplyChunkBlockContext { pub height: BlockHeight, @@ -436,6 +458,7 @@ pub trait RuntimeAdapter: Send + Sync { fn apply_chunk( &self, storage: RuntimeStorageConfig, + apply_reason: ApplyChunkReason, chunk: ApplyChunkShardContext, block: ApplyChunkBlockContext, receipts: &[Receipt], diff --git a/chain/chain/src/update_shard.rs b/chain/chain/src/update_shard.rs index 33e5b1fe73b..dd2393ddd30 100644 --- a/chain/chain/src/update_shard.rs +++ b/chain/chain/src/update_shard.rs @@ -1,7 +1,8 @@ use crate::crypto_hash_timer::CryptoHashTimer; use crate::types::{ - ApplyChunkBlockContext, ApplyChunkResult, ApplyChunkShardContext, ApplyResultForResharding, - ReshardingResults, RuntimeAdapter, RuntimeStorageConfig, StorageDataSource, + ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, ApplyChunkShardContext, + ApplyResultForResharding, ReshardingResults, RuntimeAdapter, RuntimeStorageConfig, + StorageDataSource, }; use near_async::time::Clock; use near_chain_primitives::Error; @@ -128,6 +129,7 @@ pub(crate) fn process_shard_update( ) -> Result { Ok(match shard_update_reason { ShardUpdateReason::NewChunk(data) => ShardUpdateResult::NewChunk(apply_new_chunk( + ApplyChunkReason::UpdateShard, parent_span, data, shard_context, @@ -135,6 +137,7 @@ pub(crate) fn process_shard_update( epoch_manager, )?), ShardUpdateReason::OldChunk(data) => ShardUpdateResult::OldChunk(apply_old_chunk( + ApplyChunkReason::UpdateShard, parent_span, data, shard_context, @@ -154,6 +157,7 @@ pub(crate) fn process_shard_update( /// Applies new chunk, which includes applying transactions from chunk and /// receipts filtered from outgoing receipts from previous chunks. pub fn apply_new_chunk( + apply_reason: ApplyChunkReason, parent_span: &tracing::Span, data: NewChunkData, shard_context: ShardContext, @@ -187,6 +191,7 @@ pub fn apply_new_chunk( }; match runtime.apply_chunk( storage_config, + apply_reason, ApplyChunkShardContext { shard_id, last_validator_proposals: chunk_header.prev_validator_proposals(), @@ -225,6 +230,7 @@ pub fn apply_new_chunk( /// (logunov) From what I know, the state update may include only validator /// accounts update on epoch start. pub fn apply_old_chunk( + apply_reason: ApplyChunkReason, parent_span: &tracing::Span, data: OldChunkData, shard_context: ShardContext, @@ -248,6 +254,7 @@ pub fn apply_old_chunk( }; match runtime.apply_chunk( storage_config, + apply_reason, ApplyChunkShardContext { shard_id, last_validator_proposals: prev_chunk_extra.validator_proposals(), diff --git a/chain/client/src/stateless_validation/chunk_validator/mod.rs b/chain/client/src/stateless_validation/chunk_validator/mod.rs index c27565e9923..9ecc53f00fa 100644 --- a/chain/client/src/stateless_validation/chunk_validator/mod.rs +++ b/chain/client/src/stateless_validation/chunk_validator/mod.rs @@ -13,8 +13,8 @@ use near_chain::chain::{ }; use near_chain::sharding::shuffle_receipt_proofs; use near_chain::types::{ - ApplyChunkBlockContext, ApplyChunkResult, PreparedTransactions, RuntimeAdapter, - RuntimeStorageConfig, StorageDataSource, + ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, PreparedTransactions, + RuntimeAdapter, RuntimeStorageConfig, StorageDataSource, }; use near_chain::validate::validate_chunk_with_chunk_extra_and_receipts_root; use near_chain::{Block, Chain, ChainStoreAccess}; @@ -473,6 +473,7 @@ pub(crate) fn validate_chunk_state_witness( MainTransition::NewChunk(new_chunk_data) => { let chunk_header = new_chunk_data.chunk_header.clone(); let NewChunkResult { apply_result: mut main_apply_result, .. } = apply_new_chunk( + ApplyChunkReason::ValidateChunk, &span, new_chunk_data, ShardContext { @@ -518,6 +519,7 @@ pub(crate) fn validate_chunk_state_witness( }, }; let OldChunkResult { apply_result, .. } = apply_old_chunk( + ApplyChunkReason::ValidateChunk, &span, old_chunk_data, ShardContext { diff --git a/runtime/runtime/src/metrics.rs b/runtime/runtime/src/metrics.rs index 0d9edee67af..aadfc15e3a3 100644 --- a/runtime/runtime/src/metrics.rs +++ b/runtime/runtime/src/metrics.rs @@ -338,6 +338,22 @@ pub static CHUNK_RECORDED_SIZE_UPPER_BOUND_RATIO: Lazy = Lazy::new(|| ) .unwrap() }); +pub static COMPILED_CONTRACT_CACHE_HIT: Lazy = Lazy::new(|| { + try_create_int_counter_vec( + "near_compiled_contract_cache_hit", + "The number of times runtimes finds compiled code in cache", + &["shard_id"], + ) + .unwrap() +}); +pub static COMPILED_CONTRACT_CACHE_MISS: Lazy = Lazy::new(|| { + try_create_int_counter_vec( + "near_compiled_contract_cache_miss", + "The number of times runtimes cannot find compiled code in cache", + &["shard_id"], + ) + .unwrap() +}); /// Buckets used for burned gas in receipts. /// @@ -407,6 +423,8 @@ pub struct ApplyMetrics { yield_timeouts_gas: u64, yield_timeouts_processed_total: u64, yield_timeouts_processing_seconds_total: f64, + compiled_contract_cache_hits: u64, + compiled_contract_cache_misses: u64, } impl ApplyMetrics { @@ -482,7 +500,7 @@ impl ApplyMetrics { } /// Report statistics - pub fn report(&mut self, shard_id: &str) { + pub fn report(&mut self, shard_id: &str, apply_reason: &str) { const TERA: f64 = 1_000_000_000_000_f64; LOCAL_RECEIPT_PROCESSED_TOTAL @@ -556,5 +574,12 @@ impl ApplyMetrics { CHUNK_COMPUTE .with_label_values(&[shard_id]) .observe(self.accumulated_compute as f64 / TERA); + + COMPILED_CONTRACT_CACHE_HIT + .with_label_values(&[shard_id, apply_reason]) + .inc_by(self.compiled_contract_cache_hits); + COMPILED_CONTRACT_CACHE_MISS + .with_label_values(&[shard_id, apply_reason]) + .inc_by(self.compiled_contract_cache_misses); } } diff --git a/tools/state-viewer/src/apply_chain_range.rs b/tools/state-viewer/src/apply_chain_range.rs index e4ee3e5ac58..40f03f6e3f8 100644 --- a/tools/state-viewer/src/apply_chain_range.rs +++ b/tools/state-viewer/src/apply_chain_range.rs @@ -2,8 +2,8 @@ use crate::cli::ApplyRangeMode; use near_chain::chain::collect_receipts_from_response; use near_chain::migrations::check_if_block_is_first_with_chunk_of_version; use near_chain::types::{ - ApplyChunkBlockContext, ApplyChunkResult, ApplyChunkShardContext, RuntimeAdapter, - RuntimeStorageConfig, + ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, ApplyChunkShardContext, + RuntimeAdapter, RuntimeStorageConfig, }; use near_chain::{ChainStore, ChainStoreAccess, ChainStoreUpdate}; use near_chain_configs::Genesis; @@ -234,6 +234,7 @@ fn apply_block_from_range( runtime_adapter .apply_chunk( RuntimeStorageConfig::new(*chunk_inner.prev_state_root(), use_flat_storage), + ApplyChunkReason::UpdateShard, ApplyChunkShardContext { shard_id, last_validator_proposals: chunk_inner.prev_validator_proposals(), @@ -258,6 +259,7 @@ fn apply_block_from_range( runtime_adapter .apply_chunk( RuntimeStorageConfig::new(*chunk_extra.state_root(), use_flat_storage), + ApplyChunkReason::UpdateShard, ApplyChunkShardContext { shard_id, last_validator_proposals: chunk_extra.validator_proposals(), diff --git a/tools/state-viewer/src/apply_chunk.rs b/tools/state-viewer/src/apply_chunk.rs index 80130fcce63..64875d09b0d 100644 --- a/tools/state-viewer/src/apply_chunk.rs +++ b/tools/state-viewer/src/apply_chunk.rs @@ -3,8 +3,8 @@ use borsh::BorshDeserialize; use near_chain::chain::collect_receipts_from_response; use near_chain::migrations::check_if_block_is_first_with_chunk_of_version; use near_chain::types::{ - ApplyChunkBlockContext, ApplyChunkResult, ApplyChunkShardContext, RuntimeAdapter, - RuntimeStorageConfig, + ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, ApplyChunkShardContext, + RuntimeAdapter, RuntimeStorageConfig, }; use near_chain::{ChainStore, ChainStoreAccess}; use near_epoch_manager::{EpochManagerAdapter, EpochManagerHandle}; @@ -133,6 +133,7 @@ pub(crate) fn apply_chunk( Ok(( runtime.apply_chunk( RuntimeStorageConfig::new(prev_state_root, use_flat_storage), + ApplyChunkReason::UpdateShard, ApplyChunkShardContext { shard_id, last_validator_proposals: chunk_header.prev_validator_proposals(), diff --git a/tools/state-viewer/src/commands.rs b/tools/state-viewer/src/commands.rs index b4d00a39f49..4b5f6759822 100644 --- a/tools/state-viewer/src/commands.rs +++ b/tools/state-viewer/src/commands.rs @@ -13,11 +13,10 @@ use itertools::GroupBy; use itertools::Itertools; use near_chain::chain::collect_receipts_from_response; use near_chain::migrations::check_if_block_is_first_with_chunk_of_version; -use near_chain::types::ApplyChunkBlockContext; -use near_chain::types::ApplyChunkResult; -use near_chain::types::ApplyChunkShardContext; -use near_chain::types::RuntimeAdapter; -use near_chain::types::RuntimeStorageConfig; +use near_chain::types::{ + ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, ApplyChunkShardContext, + RuntimeAdapter, RuntimeStorageConfig, +}; use near_chain::{ChainStore, ChainStoreAccess, ChainStoreUpdate, Error}; use near_chain_configs::GenesisChangeConfig; use near_epoch_manager::types::BlockHeaderInfo; @@ -94,6 +93,7 @@ pub(crate) fn apply_block( runtime .apply_chunk( RuntimeStorageConfig::new(*chunk_inner.prev_state_root(), use_flat_storage), + ApplyChunkReason::UpdateShard, ApplyChunkShardContext { shard_id, last_validator_proposals: chunk_inner.prev_validator_proposals(), @@ -116,6 +116,7 @@ pub(crate) fn apply_block( runtime .apply_chunk( RuntimeStorageConfig::new(*chunk_extra.state_root(), use_flat_storage), + ApplyChunkReason::UpdateShard, ApplyChunkShardContext { shard_id, last_validator_proposals: chunk_extra.validator_proposals(), From 11e66e1334aa5e75fc999f5baf43fb4b99697e46 Mon Sep 17 00:00:00 2001 From: Tayfun Elmas Date: Fri, 26 Apr 2024 19:04:56 -0700 Subject: [PATCH 02/15] Connect pieces second commit. --- Cargo.lock | 1 + chain/chain/src/runtime/mod.rs | 5 +++- chain/chain/src/types.rs | 14 +++++++--- .../src/tests/runtime/state_viewer.rs | 5 ++++ integration-tests/src/user/runtime_user.rs | 3 +++ runtime/near-vm-runner/Cargo.toml | 1 + runtime/near-vm-runner/fuzz/src/lib.rs | 3 +++ runtime/near-vm-runner/src/logic/context.rs | 5 +++- .../src/logic/tests/vm_logic_builder.rs | 2 ++ .../src/near_vm_runner/metrics.rs | 19 +++++++++++++ .../near-vm-runner/src/near_vm_runner/mod.rs | 1 + .../src/near_vm_runner/runner.rs | 14 +++++++++- runtime/near-vm-runner/src/tests.rs | 2 ++ runtime/near-vm-runner/src/tests/fuzzers.rs | 2 ++ .../near-vm-runner/src/tests/test_builder.rs | 2 ++ .../src/estimator_context.rs | 2 ++ .../src/vm_estimator.rs | 3 +++ runtime/runtime/src/actions.rs | 5 ++++ runtime/runtime/src/lib.rs | 5 ++++ runtime/runtime/src/metrics.rs | 27 +------------------ runtime/runtime/src/state_viewer/mod.rs | 4 +++ .../runtime/tests/runtime_group_tools/mod.rs | 2 ++ 22 files changed, 94 insertions(+), 33 deletions(-) create mode 100644 runtime/near-vm-runner/src/near_vm_runner/metrics.rs diff --git a/Cargo.lock b/Cargo.lock index 9b7f3bf9d19..9897fe411a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4937,6 +4937,7 @@ dependencies = [ "lru 0.12.3", "memoffset 0.8.0", "near-crypto", + "near-o11y", "near-parameters", "near-primitives-core", "near-stdx", diff --git a/chain/chain/src/runtime/mod.rs b/chain/chain/src/runtime/mod.rs index 70a94a9d2dd..a4dc980ac81 100644 --- a/chain/chain/src/runtime/mod.rs +++ b/chain/chain/src/runtime/mod.rs @@ -362,6 +362,8 @@ impl NightshadeRuntime { ); let apply_state = ApplyState { + apply_reason: Some(apply_reason.as_str()), + shard_id: chunk.shard_id, block_height, prev_block_hash: *prev_block_hash, block_hash, @@ -422,7 +424,7 @@ impl NightshadeRuntime { .with_label_values(&[&shard_label]) .set(apply_result.delayed_receipts_count as i64); if let Some(mut metrics) = apply_result.metrics { - metrics.report(&shard_label, &apply_reason.to_string()); + metrics.report(&shard_label); } let total_balance_burnt = apply_result @@ -1319,6 +1321,7 @@ impl node_runtime::adapter::ViewRuntimeAdapter for NightshadeRuntime { cache: Some(Box::new(self.compiled_contract_cache.handle())), }; self.trie_viewer.call_function( + shard_uid.shard_id(), state_update, view_state, contract_id, diff --git a/chain/chain/src/types.rs b/chain/chain/src/types.rs index 8405e959e9e..3effd373e1c 100644 --- a/chain/chain/src/types.rs +++ b/chain/chain/src/types.rs @@ -289,12 +289,18 @@ pub enum ApplyChunkReason { ValidateChunk, } -impl Display for ApplyChunkReason { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { - f.write_str(match self { +impl ApplyChunkReason { + pub fn as_str(&self) -> &'static str { + match self { ApplyChunkReason::UpdateShard => "update_shard", ApplyChunkReason::ValidateChunk => "validate_chunk", - }) + } + } +} + +impl Display for ApplyChunkReason { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + f.write_str(self.as_str()) } } diff --git a/integration-tests/src/tests/runtime/state_viewer.rs b/integration-tests/src/tests/runtime/state_viewer.rs index 3179d1af3a6..68746ce17e9 100644 --- a/integration-tests/src/tests/runtime/state_viewer.rs +++ b/integration-tests/src/tests/runtime/state_viewer.rs @@ -3,6 +3,7 @@ use std::{collections::HashMap, io, sync::Arc}; use borsh::BorshDeserialize; use crate::runtime_utils::{get_runtime_and_trie, get_test_trie_viewer, TEST_SHARD_UID}; +use near_primitives::shard_layout::ShardUId; use near_primitives::{ account::Account, hash::hash as sha256, @@ -117,6 +118,7 @@ fn test_view_call() { cache: None, }; let result = viewer.call_function( + ShardUId::single_shard().shard_id(), root, view_state, &"test.contract".parse().unwrap(), @@ -145,6 +147,7 @@ fn test_view_call_try_changing_storage() { cache: None, }; let result = viewer.call_function( + ShardUId::single_shard().shard_id(), root, view_state, &"test.contract".parse().unwrap(), @@ -177,6 +180,7 @@ fn test_view_call_with_args() { cache: None, }; let view_call_result = viewer.call_function( + ShardUId::single_shard().shard_id(), root, view_state, &"test.contract".parse().unwrap(), @@ -399,6 +403,7 @@ fn test_log_when_panic() { let mut logs = vec![]; viewer .call_function( + ShardUId::single_shard().shard_id(), root, view_state, &"test.contract".parse().unwrap(), diff --git a/integration-tests/src/user/runtime_user.rs b/integration-tests/src/user/runtime_user.rs index c9d43a68ad3..7cda2a89979 100644 --- a/integration-tests/src/user/runtime_user.rs +++ b/integration-tests/src/user/runtime_user.rs @@ -152,6 +152,8 @@ impl RuntimeUser { fn apply_state(&self) -> ApplyState { ApplyState { + apply_reason: None, + shard_id: ShardUId::single_shard().shard_id(), block_height: 1, prev_block_hash: Default::default(), block_hash: Default::default(), @@ -293,6 +295,7 @@ impl User for RuntimeUser { result.result = self .trie_viewer .call_function( + ShardUId::single_shard().shard_id(), state_update, view_state, account_id, diff --git a/runtime/near-vm-runner/Cargo.toml b/runtime/near-vm-runner/Cargo.toml index 042bd0bab2c..4917da8f063 100644 --- a/runtime/near-vm-runner/Cargo.toml +++ b/runtime/near-vm-runner/Cargo.toml @@ -44,6 +44,7 @@ wasmtime = { workspace = true, optional = true } near-crypto.workspace = true near-primitives-core.workspace = true near-parameters.workspace = true +near-o11y.workspace = true bytesize.workspace = true # Old versions of pwasm-utils we need to preserve backwards compatibility under diff --git a/runtime/near-vm-runner/fuzz/src/lib.rs b/runtime/near-vm-runner/fuzz/src/lib.rs index a7eb0a8e92f..698b8711cac 100644 --- a/runtime/near-vm-runner/fuzz/src/lib.rs +++ b/runtime/near-vm-runner/fuzz/src/lib.rs @@ -1,4 +1,5 @@ use core::fmt; +use near_primitives::shard_layout::ShardUId; use near_vm_runner::internal::wasmparser::{Export, ExternalKind, Parser, Payload, TypeDef}; use near_vm_runner::logic::VMContext; use near_vm_runner::ContractCode; @@ -48,6 +49,8 @@ pub fn create_context(input: Vec) -> VMContext { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], + shard_id: ShardUId::single_shard().shard_id(), + metrics_context: None, } } diff --git a/runtime/near-vm-runner/src/logic/context.rs b/runtime/near-vm-runner/src/logic/context.rs index 869aa24554f..b3b640b078d 100644 --- a/runtime/near-vm-runner/src/logic/context.rs +++ b/runtime/near-vm-runner/src/logic/context.rs @@ -1,7 +1,7 @@ use super::types::PublicKey; use near_primitives_core::config::ViewConfig; use near_primitives_core::types::{ - AccountId, Balance, BlockHeight, EpochHeight, Gas, StorageUsage, + AccountId, Balance, BlockHeight, EpochHeight, Gas, ShardId, StorageUsage, }; #[derive(Clone)] @@ -51,6 +51,9 @@ pub struct VMContext { /// How many `DataReceipt`'s should receive this execution result. This should be empty if /// this function call is a part of a batch and it is not the last action. pub output_data_receivers: Vec, + + pub shard_id: ShardId, + pub metrics_context: Option<&'static str>, } impl VMContext { diff --git a/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs b/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs index b3358b1fa6b..c456c8dfc9d 100644 --- a/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs +++ b/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs @@ -81,6 +81,8 @@ fn get_context() -> VMContext { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], + shard_id: ShardUId::single_shard().shard_id(), + metrics_context: None, } } diff --git a/runtime/near-vm-runner/src/near_vm_runner/metrics.rs b/runtime/near-vm-runner/src/near_vm_runner/metrics.rs new file mode 100644 index 00000000000..2c94bc1cc59 --- /dev/null +++ b/runtime/near-vm-runner/src/near_vm_runner/metrics.rs @@ -0,0 +1,19 @@ +use near_o11y::metrics::{try_create_int_counter_vec, IntCounterVec}; +use once_cell::sync::Lazy; + +pub static COMPILED_CONTRACT_CACHE_HIT: Lazy = Lazy::new(|| { + try_create_int_counter_vec( + "near_compiled_contract_cache_hit", + "The number of times runtimes finds compiled code in cache", + &["shard_id"], + ) + .unwrap() +}); +pub static COMPILED_CONTRACT_CACHE_MISS: Lazy = Lazy::new(|| { + try_create_int_counter_vec( + "near_compiled_contract_cache_miss", + "The number of times runtimes cannot find compiled code in cache", + &["shard_id"], + ) + .unwrap() +}); diff --git a/runtime/near-vm-runner/src/near_vm_runner/mod.rs b/runtime/near-vm-runner/src/near_vm_runner/mod.rs index f2c7b48b5b4..c751534f0f7 100644 --- a/runtime/near-vm-runner/src/near_vm_runner/mod.rs +++ b/runtime/near-vm-runner/src/near_vm_runner/mod.rs @@ -1,4 +1,5 @@ mod memory; +mod metrics; mod runner; pub use memory::NearVmMemory; diff --git a/runtime/near-vm-runner/src/near_vm_runner/runner.rs b/runtime/near-vm-runner/src/near_vm_runner/runner.rs index b0a2a206249..0290f3eff4a 100644 --- a/runtime/near-vm-runner/src/near_vm_runner/runner.rs +++ b/runtime/near-vm-runner/src/near_vm_runner/runner.rs @@ -1,4 +1,4 @@ -use super::{NearVmMemory, VM_CONFIG}; +use super::{metrics, NearVmMemory, VM_CONFIG}; use crate::cache::CompiledContractInfo; use crate::errors::ContractPrecompilatonResult; use crate::imports::near_vm::NearVmImports; @@ -237,10 +237,22 @@ impl NearVM { let key = get_contract_cache_key(code_hash, &self.config); let cache_record = cache.get(&key).map_err(CacheError::ReadError)?; let Some(code) = cache_record else { + metrics::COMPILED_CONTRACT_CACHE_MISS + .with_label_values(&[ + &context.shard_id.to_string(), + &context.metrics_context.unwrap_or("unknown"), + ]) + .inc(); return Err(VMRunnerError::CacheError(CacheError::ReadError( std::io::Error::from(std::io::ErrorKind::NotFound), ))); }; + metrics::COMPILED_CONTRACT_CACHE_HIT + .with_label_values(&[ + &context.shard_id.to_string(), + &context.metrics_context.unwrap_or("unknown"), + ]) + .inc(); match &code.compiled { CompiledContract::CompileModuleError(err) => { diff --git a/runtime/near-vm-runner/src/tests.rs b/runtime/near-vm-runner/src/tests.rs index bacca8c2c10..b873f0ace55 100644 --- a/runtime/near-vm-runner/src/tests.rs +++ b/runtime/near-vm-runner/src/tests.rs @@ -70,5 +70,7 @@ fn create_context(input: Vec) -> VMContext { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], + shard_id: ShardUId::single_shard().shard_id(), + metrics_context: None, } } diff --git a/runtime/near-vm-runner/src/tests/fuzzers.rs b/runtime/near-vm-runner/src/tests/fuzzers.rs index 5d0ce4af948..fa144daa9f2 100644 --- a/runtime/near-vm-runner/src/tests/fuzzers.rs +++ b/runtime/near-vm-runner/src/tests/fuzzers.rs @@ -56,6 +56,8 @@ pub fn create_context(input: Vec) -> VMContext { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], + shard_id: ShardUId::single_shard().shard_id(), + metrics_context: None, } } diff --git a/runtime/near-vm-runner/src/tests/test_builder.rs b/runtime/near-vm-runner/src/tests/test_builder.rs index b765f89876d..903c0c6a8d0 100644 --- a/runtime/near-vm-runner/src/tests/test_builder.rs +++ b/runtime/near-vm-runner/src/tests/test_builder.rs @@ -27,6 +27,8 @@ pub(crate) fn test_builder() -> TestBuilder { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], + shard_id: ShardUId::single_shard().shard_id(), + metrics_context: None, }; let mut skip = HashSet::new(); for kind in [VMKind::Wasmer0, VMKind::Wasmer2, VMKind::NearVm, VMKind::Wasmtime] { diff --git a/runtime/runtime-params-estimator/src/estimator_context.rs b/runtime/runtime-params-estimator/src/estimator_context.rs index 684686d6ed7..c47bd9ba546 100644 --- a/runtime/runtime-params-estimator/src/estimator_context.rs +++ b/runtime/runtime-params-estimator/src/estimator_context.rs @@ -145,6 +145,8 @@ impl<'c> EstimatorContext<'c> { runtime_config.account_creation_config.min_allowed_top_level_account_length = 0; ApplyState { + apply_reason: None, + shard_id: ShardUId::single_shard().shard_id(), // Put each runtime into a separate shard. block_height: 1, // Epoch length is long enough to avoid corner cases. diff --git a/runtime/runtime-params-estimator/src/vm_estimator.rs b/runtime/runtime-params-estimator/src/vm_estimator.rs index 72bd4415ed6..00068a434b4 100644 --- a/runtime/runtime-params-estimator/src/vm_estimator.rs +++ b/runtime/runtime-params-estimator/src/vm_estimator.rs @@ -3,6 +3,7 @@ use crate::gas_cost::{GasCost, LeastSquaresTolerance}; use crate::{utils::read_resource, REAL_CONTRACTS_SAMPLE}; use near_parameters::vm::VMKind; use near_parameters::RuntimeConfigStore; +use near_primitives::shard_layout::ShardUId; use near_primitives::version::PROTOCOL_VERSION; use near_vm_runner::internal::VMKindExt; use near_vm_runner::logic::VMContext; @@ -33,6 +34,8 @@ pub(crate) fn create_context(input: Vec) -> VMContext { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], + shard_id: ShardUId::single_shard().shard_id(), + metrics_context: None, } } diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index 5f25f6af87c..b2137a48e2a 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -42,6 +42,7 @@ use near_vm_runner::precompile_contract; use near_vm_runner::ContractCode; use near_wallet_contract::{wallet_contract, wallet_contract_magic_bytes}; +use near_primitives::shard_layout::ShardUId; use std::sync::Arc; /// Returns `ContractCode` (if exists) for the given `account` or returns `StorageError`. @@ -109,6 +110,8 @@ pub(crate) fn execute_function_call( random_seed, view_config: view_config.clone(), output_data_receivers, + shard_id: ShardUId::single_shard().shard_id(), + metrics_context: None, }; // Enable caching chunk mode for the function call. This allows to charge for nodes touched in a chunk only once for @@ -1404,6 +1407,8 @@ mod tests { fn create_apply_state(block_height: BlockHeight) -> ApplyState { ApplyState { + apply_reason: None, + shard_id: ShardUId::single_shard().shard_id(), block_height, prev_block_hash: CryptoHash::default(), block_hash: CryptoHash::default(), diff --git a/runtime/runtime/src/lib.rs b/runtime/runtime/src/lib.rs index 18bf922a505..d59332dbdbf 100644 --- a/runtime/runtime/src/lib.rs +++ b/runtime/runtime/src/lib.rs @@ -42,6 +42,7 @@ use near_primitives::utils::{ create_receipt_id_from_transaction, }; use near_primitives::version::{ProtocolFeature, ProtocolVersion}; +use near_primitives_core::types::ShardId; use near_store::trie::receipts_column_helper::DelayedReceiptQueue; use near_store::{ get, get_account, get_postponed_receipt, get_promise_yield_receipt, get_received_data, @@ -77,6 +78,8 @@ const EXPECT_ACCOUNT_EXISTS: &str = "account exists, checked above"; #[derive(Debug)] pub struct ApplyState { + pub apply_reason: Option<&'static str>, + pub shard_id: ShardId, /// Currently building block height. pub block_height: BlockHeight, /// Prev block hash @@ -1960,6 +1963,8 @@ mod tests { store_update.commit().unwrap(); let contract_cache = FilesystemContractRuntimeCache::test().unwrap(); let apply_state = ApplyState { + apply_reason: None, + shard_id: ShardUId::single_shard().shard_id(), block_height: 1, prev_block_hash: Default::default(), block_hash: Default::default(), diff --git a/runtime/runtime/src/metrics.rs b/runtime/runtime/src/metrics.rs index aadfc15e3a3..0d9edee67af 100644 --- a/runtime/runtime/src/metrics.rs +++ b/runtime/runtime/src/metrics.rs @@ -338,22 +338,6 @@ pub static CHUNK_RECORDED_SIZE_UPPER_BOUND_RATIO: Lazy = Lazy::new(|| ) .unwrap() }); -pub static COMPILED_CONTRACT_CACHE_HIT: Lazy = Lazy::new(|| { - try_create_int_counter_vec( - "near_compiled_contract_cache_hit", - "The number of times runtimes finds compiled code in cache", - &["shard_id"], - ) - .unwrap() -}); -pub static COMPILED_CONTRACT_CACHE_MISS: Lazy = Lazy::new(|| { - try_create_int_counter_vec( - "near_compiled_contract_cache_miss", - "The number of times runtimes cannot find compiled code in cache", - &["shard_id"], - ) - .unwrap() -}); /// Buckets used for burned gas in receipts. /// @@ -423,8 +407,6 @@ pub struct ApplyMetrics { yield_timeouts_gas: u64, yield_timeouts_processed_total: u64, yield_timeouts_processing_seconds_total: f64, - compiled_contract_cache_hits: u64, - compiled_contract_cache_misses: u64, } impl ApplyMetrics { @@ -500,7 +482,7 @@ impl ApplyMetrics { } /// Report statistics - pub fn report(&mut self, shard_id: &str, apply_reason: &str) { + pub fn report(&mut self, shard_id: &str) { const TERA: f64 = 1_000_000_000_000_f64; LOCAL_RECEIPT_PROCESSED_TOTAL @@ -574,12 +556,5 @@ impl ApplyMetrics { CHUNK_COMPUTE .with_label_values(&[shard_id]) .observe(self.accumulated_compute as f64 / TERA); - - COMPILED_CONTRACT_CACHE_HIT - .with_label_values(&[shard_id, apply_reason]) - .inc_by(self.compiled_contract_cache_hits); - COMPILED_CONTRACT_CACHE_MISS - .with_label_values(&[shard_id, apply_reason]) - .inc_by(self.compiled_contract_cache_misses); } } diff --git a/runtime/runtime/src/state_viewer/mod.rs b/runtime/runtime/src/state_viewer/mod.rs index ecb731deea1..c5527cfa28a 100644 --- a/runtime/runtime/src/state_viewer/mod.rs +++ b/runtime/runtime/src/state_viewer/mod.rs @@ -15,6 +15,7 @@ use near_primitives::types::{AccountId, EpochInfoProvider, Gas}; use near_primitives::version::PROTOCOL_VERSION; use near_primitives::views::{StateItem, ViewApplyState, ViewStateResult}; use near_primitives_core::config::ViewConfig; +use near_primitives_core::types::ShardId; use near_store::{get_access_key, get_account, get_code, TrieUpdate}; use near_vm_runner::logic::ReturnData; use near_vm_runner::ContractCode; @@ -155,6 +156,7 @@ impl TrieViewer { pub fn call_function( &self, + shard_id: ShardId, mut state_update: TrieUpdate, view_state: ViewApplyState, contract_id: &AccountId, @@ -189,6 +191,8 @@ impl TrieViewer { let config_store = RuntimeConfigStore::new(None); let config = config_store.get_config(PROTOCOL_VERSION); let apply_state = ApplyState { + apply_reason: None, + shard_id: shard_id, block_height: view_state.block_height, // Used for legacy reasons prev_block_hash: view_state.prev_block_hash, diff --git a/runtime/runtime/tests/runtime_group_tools/mod.rs b/runtime/runtime/tests/runtime_group_tools/mod.rs index 25ed48d00ad..a8f58b59767 100644 --- a/runtime/runtime/tests/runtime_group_tools/mod.rs +++ b/runtime/runtime/tests/runtime_group_tools/mod.rs @@ -89,6 +89,8 @@ impl StandaloneRuntime { ); let apply_state = ApplyState { + apply_reason: None, + shard_id: ShardUId::single_shard().shard_id(), block_height: 1, prev_block_hash: Default::default(), block_hash: Default::default(), From deccb30318b3a0d3d69430381677b44343f96b73 Mon Sep 17 00:00:00 2001 From: Tayfun Elmas Date: Sat, 27 Apr 2024 11:59:39 -0700 Subject: [PATCH 03/15] Move reason to primitives and not use string. --- chain/chain/src/chain_update.rs | 9 +++--- chain/chain/src/runtime/mod.rs | 8 ++--- chain/chain/src/runtime/tests.rs | 3 +- chain/chain/src/test_utils/kv_runtime.rs | 7 +++-- chain/chain/src/types.rs | 29 +----------------- chain/chain/src/update_shard.rs | 10 +++---- .../chunk_validator/mod.rs | 9 +++--- core/primitives-core/src/apply.rs | 30 +++++++++++++++++++ core/primitives-core/src/lib.rs | 1 + core/primitives/src/lib.rs | 1 + runtime/near-vm-runner/fuzz/src/lib.rs | 2 +- runtime/near-vm-runner/src/logic/context.rs | 5 +++- .../src/logic/tests/vm_logic_builder.rs | 2 +- .../src/near_vm_runner/metrics.rs | 4 +-- .../src/near_vm_runner/runner.rs | 4 +-- runtime/near-vm-runner/src/tests.rs | 2 +- runtime/near-vm-runner/src/tests/fuzzers.rs | 2 +- .../near-vm-runner/src/tests/test_builder.rs | 2 +- .../src/vm_estimator.rs | 2 +- runtime/runtime/src/actions.rs | 2 +- runtime/runtime/src/lib.rs | 5 +++- tools/state-viewer/src/apply_chain_range.rs | 9 +++--- tools/state-viewer/src/apply_chunk.rs | 7 +++-- tools/state-viewer/src/commands.rs | 9 +++--- 24 files changed, 91 insertions(+), 73 deletions(-) create mode 100644 core/primitives-core/src/apply.rs diff --git a/chain/chain/src/chain_update.rs b/chain/chain/src/chain_update.rs index 1fa6d3cd93d..b9856b86ae8 100644 --- a/chain/chain/src/chain_update.rs +++ b/chain/chain/src/chain_update.rs @@ -4,8 +4,8 @@ use crate::metrics::{SHARD_LAYOUT_NUM_SHARDS, SHARD_LAYOUT_VERSION}; use crate::store::{ChainStore, ChainStoreAccess, ChainStoreUpdate}; use crate::types::{ - ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, ApplyChunkShardContext, - ReshardingResults, RuntimeAdapter, RuntimeStorageConfig, + ApplyChunkBlockContext, ApplyChunkResult, ApplyChunkShardContext, ReshardingResults, + RuntimeAdapter, RuntimeStorageConfig, }; use crate::update_shard::{NewChunkResult, OldChunkResult, ReshardingResult, ShardUpdateResult}; use crate::{metrics, DoomslugThresholdMode}; @@ -14,6 +14,7 @@ use near_chain_primitives::error::Error; use near_epoch_manager::shard_tracker::ShardTracker; use near_epoch_manager::types::BlockHeaderInfo; use near_epoch_manager::EpochManagerAdapter; +use near_primitives::apply::ApplyChunkReason; use near_primitives::block::{Block, Tip}; use near_primitives::block_header::BlockHeader; #[cfg(feature = "new_epoch_sync")] @@ -738,7 +739,7 @@ impl<'a> ChainUpdate<'a> { let apply_result = self.runtime_adapter.apply_chunk( RuntimeStorageConfig::new(chunk_header.prev_state_root(), true), - ApplyChunkReason::UpdateShard, + ApplyChunkReason::UpdateTrackedShard, ApplyChunkShardContext { shard_id, gas_limit, @@ -836,7 +837,7 @@ impl<'a> ChainUpdate<'a> { let apply_result = self.runtime_adapter.apply_chunk( RuntimeStorageConfig::new(*chunk_extra.state_root(), true), - ApplyChunkReason::UpdateShard, + ApplyChunkReason::UpdateTrackedShard, ApplyChunkShardContext { shard_id, last_validator_proposals: chunk_extra.validator_proposals(), diff --git a/chain/chain/src/runtime/mod.rs b/chain/chain/src/runtime/mod.rs index a4dc980ac81..e8e21c61769 100644 --- a/chain/chain/src/runtime/mod.rs +++ b/chain/chain/src/runtime/mod.rs @@ -1,8 +1,7 @@ use crate::types::{ - ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, ApplyChunkShardContext, - ApplyResultForResharding, PrepareTransactionsBlockContext, PrepareTransactionsChunkContext, - PrepareTransactionsLimit, PreparedTransactions, RuntimeAdapter, RuntimeStorageConfig, - StorageDataSource, Tip, + ApplyChunkBlockContext, ApplyChunkResult, ApplyChunkShardContext, ApplyResultForResharding, + PrepareTransactionsBlockContext, PrepareTransactionsChunkContext, PrepareTransactionsLimit, + PreparedTransactions, RuntimeAdapter, RuntimeStorageConfig, StorageDataSource, Tip, }; use crate::Error; use borsh::BorshDeserialize; @@ -16,6 +15,7 @@ use near_epoch_manager::{EpochManagerAdapter, EpochManagerHandle}; use near_parameters::{ActionCosts, ExtCosts, RuntimeConfigStore}; use near_pool::types::TransactionGroupIterator; use near_primitives::account::{AccessKey, Account}; +use near_primitives::apply::ApplyChunkReason; use near_primitives::checked_feature; use near_primitives::errors::{InvalidTxError, RuntimeError, StorageError}; use near_primitives::hash::{hash, CryptoHash}; diff --git a/chain/chain/src/runtime/tests.rs b/chain/chain/src/runtime/tests.rs index f98d0a0fe51..4771acd8368 100644 --- a/chain/chain/src/runtime/tests.rs +++ b/chain/chain/src/runtime/tests.rs @@ -9,6 +9,7 @@ use near_epoch_manager::{EpochManager, RngSeed}; use near_pool::{ InsertTransactionResult, PoolIteratorWrapper, TransactionGroupIteratorWrapper, TransactionPool, }; +use near_primitives::apply::ApplyChunkReason; use near_primitives::checked_feature; use near_primitives::test_utils::create_test_signer; use near_primitives::types::validator_stake::{ValidatorStake, ValidatorStakeIter}; @@ -81,7 +82,7 @@ impl NightshadeRuntime { let mut result = self .apply_chunk( RuntimeStorageConfig::new(*state_root, true), - ApplyChunkReason::UpdateShard, + ApplyChunkReason::UpdateTrackedShard, ApplyChunkShardContext { shard_id, last_validator_proposals, diff --git a/chain/chain/src/test_utils/kv_runtime.rs b/chain/chain/src/test_utils/kv_runtime.rs index a69822877f9..79cc72e0027 100644 --- a/chain/chain/src/test_utils/kv_runtime.rs +++ b/chain/chain/src/test_utils/kv_runtime.rs @@ -1,8 +1,8 @@ use super::ValidatorSchedule; use crate::types::{ - ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, ApplyChunkShardContext, - ApplyResultForResharding, PrepareTransactionsBlockContext, PrepareTransactionsChunkContext, - PreparedTransactions, RuntimeAdapter, RuntimeStorageConfig, + ApplyChunkBlockContext, ApplyChunkResult, ApplyChunkShardContext, ApplyResultForResharding, + PrepareTransactionsBlockContext, PrepareTransactionsChunkContext, PreparedTransactions, + RuntimeAdapter, RuntimeStorageConfig, }; use crate::BlockHeader; use borsh::{BorshDeserialize, BorshSerialize}; @@ -14,6 +14,7 @@ use near_epoch_manager::types::BlockHeaderInfo; use near_epoch_manager::{EpochManagerAdapter, RngSeed}; use near_pool::types::TransactionGroupIterator; use near_primitives::account::{AccessKey, Account}; +use near_primitives::apply::ApplyChunkReason; use near_primitives::block::Tip; use near_primitives::block_header::{Approval, ApprovalInner}; use near_primitives::epoch_manager::block_info::BlockInfo; diff --git a/chain/chain/src/types.rs b/chain/chain/src/types.rs index 3effd373e1c..fe95cc048d5 100644 --- a/chain/chain/src/types.rs +++ b/chain/chain/src/types.rs @@ -7,6 +7,7 @@ use near_chain_configs::ReshardingConfig; use near_chain_primitives::Error; pub use near_epoch_manager::EpochManagerAdapter; use near_pool::types::TransactionGroupIterator; +use near_primitives::apply::ApplyChunkReason; pub use near_primitives::block::{Block, BlockHeader, Tip}; use near_primitives::challenge::{ChallengesResult, PartialState}; use near_primitives::checked_feature; @@ -34,7 +35,6 @@ use near_store::flat::FlatStorageManager; use near_store::{PartialStorage, ShardTries, Store, Trie, WrappedTrieChanges}; use num_rational::Rational32; use std::collections::HashMap; -use std::fmt::{Display, Formatter}; #[derive(Eq, PartialEq, Debug, Clone)] pub enum BlockStatus { @@ -277,33 +277,6 @@ impl RuntimeStorageConfig { } } -/// Indicates in which phase of block production the apply is invoked. -/// This is currently used for debugging and tracking metrics. -/// TODO: Consider combining ApplyChunKReason, ApplyChunkBlockContext, and ApplyChunkBlockContext -/// under a common wrapper struct such as ApplyChunkContext. -#[derive(Clone, Debug)] -pub enum ApplyChunkReason { - /// Applying chunk to update the shards being tracked. - UpdateShard, - /// Applying chunk to validate the chunk in the case of stateless validation.n - ValidateChunk, -} - -impl ApplyChunkReason { - pub fn as_str(&self) -> &'static str { - match self { - ApplyChunkReason::UpdateShard => "update_shard", - ApplyChunkReason::ValidateChunk => "validate_chunk", - } - } -} - -impl Display for ApplyChunkReason { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { - f.write_str(self.as_str()) - } -} - #[derive(Clone)] pub struct ApplyChunkBlockContext { pub height: BlockHeight, diff --git a/chain/chain/src/update_shard.rs b/chain/chain/src/update_shard.rs index dd2393ddd30..d1e7b213811 100644 --- a/chain/chain/src/update_shard.rs +++ b/chain/chain/src/update_shard.rs @@ -1,12 +1,12 @@ use crate::crypto_hash_timer::CryptoHashTimer; use crate::types::{ - ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, ApplyChunkShardContext, - ApplyResultForResharding, ReshardingResults, RuntimeAdapter, RuntimeStorageConfig, - StorageDataSource, + ApplyChunkBlockContext, ApplyChunkResult, ApplyChunkShardContext, ApplyResultForResharding, + ReshardingResults, RuntimeAdapter, RuntimeStorageConfig, StorageDataSource, }; use near_async::time::Clock; use near_chain_primitives::Error; use near_epoch_manager::EpochManagerAdapter; +use near_primitives::apply::ApplyChunkReason; use near_primitives::hash::CryptoHash; use near_primitives::receipt::Receipt; use near_primitives::sandbox::state_patch::SandboxStatePatch; @@ -129,7 +129,7 @@ pub(crate) fn process_shard_update( ) -> Result { Ok(match shard_update_reason { ShardUpdateReason::NewChunk(data) => ShardUpdateResult::NewChunk(apply_new_chunk( - ApplyChunkReason::UpdateShard, + ApplyChunkReason::UpdateTrackedShard, parent_span, data, shard_context, @@ -137,7 +137,7 @@ pub(crate) fn process_shard_update( epoch_manager, )?), ShardUpdateReason::OldChunk(data) => ShardUpdateResult::OldChunk(apply_old_chunk( - ApplyChunkReason::UpdateShard, + ApplyChunkReason::UpdateTrackedShard, parent_span, data, shard_context, diff --git a/chain/client/src/stateless_validation/chunk_validator/mod.rs b/chain/client/src/stateless_validation/chunk_validator/mod.rs index 9ecc53f00fa..2ac5cbcbb63 100644 --- a/chain/client/src/stateless_validation/chunk_validator/mod.rs +++ b/chain/client/src/stateless_validation/chunk_validator/mod.rs @@ -13,8 +13,8 @@ use near_chain::chain::{ }; use near_chain::sharding::shuffle_receipt_proofs; use near_chain::types::{ - ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, PreparedTransactions, - RuntimeAdapter, RuntimeStorageConfig, StorageDataSource, + ApplyChunkBlockContext, ApplyChunkResult, PreparedTransactions, RuntimeAdapter, + RuntimeStorageConfig, StorageDataSource, }; use near_chain::validate::validate_chunk_with_chunk_extra_and_receipts_root; use near_chain::{Block, Chain, ChainStoreAccess}; @@ -22,6 +22,7 @@ use near_chain_primitives::Error; use near_epoch_manager::EpochManagerAdapter; use near_network::types::{NetworkRequests, PeerManagerMessageRequest}; use near_pool::TransactionGroupIteratorWrapper; +use near_primitives::apply::ApplyChunkReason; use near_primitives::hash::{hash, CryptoHash}; use near_primitives::merkle::merklize; use near_primitives::receipt::Receipt; @@ -473,7 +474,7 @@ pub(crate) fn validate_chunk_state_witness( MainTransition::NewChunk(new_chunk_data) => { let chunk_header = new_chunk_data.chunk_header.clone(); let NewChunkResult { apply_result: mut main_apply_result, .. } = apply_new_chunk( - ApplyChunkReason::ValidateChunk, + ApplyChunkReason::ValidateChunkStateWitness, &span, new_chunk_data, ShardContext { @@ -519,7 +520,7 @@ pub(crate) fn validate_chunk_state_witness( }, }; let OldChunkResult { apply_result, .. } = apply_old_chunk( - ApplyChunkReason::ValidateChunk, + ApplyChunkReason::ValidateChunkStateWitness, &span, old_chunk_data, ShardContext { diff --git a/core/primitives-core/src/apply.rs b/core/primitives-core/src/apply.rs new file mode 100644 index 00000000000..fedc472d1f2 --- /dev/null +++ b/core/primitives-core/src/apply.rs @@ -0,0 +1,30 @@ +use std::fmt::{Display, Formatter}; + +/// Indicates the phase of block production the apply-chunk operation is invoked. +/// This is currently used to analyze and compare the metrics collected while applying the receipts +/// for different purposes, eg. while updating state of a tracked shard vs. validating a chunk. +/// TODO: Consider combining ApplyChunkReason, ApplyChunkBlockContext, and ApplyChunkBlockContext +/// under a common wrapper struct such as ApplyChunkContext. +#[derive(Clone, Debug)] +pub enum ApplyChunkReason { + /// Apply-chunk is invoked to update the state of a shards being tracked. + UpdateTrackedShard, + /// Apply-chunk is invoked to validate the state witness for a shard in the context of stateless validation. + ValidateChunkStateWitness, +} + +impl ApplyChunkReason { + /// Returns a static, short string representation of the reason, to be used for metrics. + pub fn as_str(&self) -> &'static str { + match self { + ApplyChunkReason::UpdateTrackedShard => "update_shard", + ApplyChunkReason::ValidateChunkStateWitness => "validate_chunk", + } + } +} + +impl Display for ApplyChunkReason { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + f.write_str(self.as_str()) + } +} diff --git a/core/primitives-core/src/lib.rs b/core/primitives-core/src/lib.rs index ff82fde18b1..abd0605510f 100644 --- a/core/primitives-core/src/lib.rs +++ b/core/primitives-core/src/lib.rs @@ -2,6 +2,7 @@ pub use borsh; pub use num_rational; pub mod account; +pub mod apply; pub mod chains; pub mod config; pub mod hash; diff --git a/core/primitives/src/lib.rs b/core/primitives/src/lib.rs index a30512457d7..73bd0a5228c 100644 --- a/core/primitives/src/lib.rs +++ b/core/primitives/src/lib.rs @@ -1,4 +1,5 @@ pub use near_primitives_core::account; +pub use near_primitives_core::apply; pub use near_primitives_core::borsh; pub use near_primitives_core::config; pub use near_primitives_core::hash; diff --git a/runtime/near-vm-runner/fuzz/src/lib.rs b/runtime/near-vm-runner/fuzz/src/lib.rs index 698b8711cac..91d917c1757 100644 --- a/runtime/near-vm-runner/fuzz/src/lib.rs +++ b/runtime/near-vm-runner/fuzz/src/lib.rs @@ -50,7 +50,7 @@ pub fn create_context(input: Vec) -> VMContext { view_config: None, output_data_receivers: vec![], shard_id: ShardUId::single_shard().shard_id(), - metrics_context: None, + apply_reason: None, } } diff --git a/runtime/near-vm-runner/src/logic/context.rs b/runtime/near-vm-runner/src/logic/context.rs index b3b640b078d..190f3e59e48 100644 --- a/runtime/near-vm-runner/src/logic/context.rs +++ b/runtime/near-vm-runner/src/logic/context.rs @@ -1,4 +1,5 @@ use super::types::PublicKey; +use near_primitives_core::apply::ApplyChunkReason; use near_primitives_core::config::ViewConfig; use near_primitives_core::types::{ AccountId, Balance, BlockHeight, EpochHeight, Gas, ShardId, StorageUsage, @@ -52,8 +53,10 @@ pub struct VMContext { /// this function call is a part of a batch and it is not the last action. pub output_data_receivers: Vec, + /// The shard that the VM is running on. pub shard_id: ShardId, - pub metrics_context: Option<&'static str>, + /// Reason for running the apply-chunk operation, where this VM runs as part of. + pub apply_reason: Option, } impl VMContext { diff --git a/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs b/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs index c456c8dfc9d..7e6a312be20 100644 --- a/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs +++ b/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs @@ -82,7 +82,7 @@ fn get_context() -> VMContext { view_config: None, output_data_receivers: vec![], shard_id: ShardUId::single_shard().shard_id(), - metrics_context: None, + apply_reason: None, } } diff --git a/runtime/near-vm-runner/src/near_vm_runner/metrics.rs b/runtime/near-vm-runner/src/near_vm_runner/metrics.rs index 2c94bc1cc59..c9558e91f1b 100644 --- a/runtime/near-vm-runner/src/near_vm_runner/metrics.rs +++ b/runtime/near-vm-runner/src/near_vm_runner/metrics.rs @@ -4,7 +4,7 @@ use once_cell::sync::Lazy; pub static COMPILED_CONTRACT_CACHE_HIT: Lazy = Lazy::new(|| { try_create_int_counter_vec( "near_compiled_contract_cache_hit", - "The number of times runtimes finds compiled code in cache", + "The number of times the runtime finds compiled code in cache", &["shard_id"], ) .unwrap() @@ -12,7 +12,7 @@ pub static COMPILED_CONTRACT_CACHE_HIT: Lazy = Lazy::new(|| { pub static COMPILED_CONTRACT_CACHE_MISS: Lazy = Lazy::new(|| { try_create_int_counter_vec( "near_compiled_contract_cache_miss", - "The number of times runtimes cannot find compiled code in cache", + "The number of times the runtime cannot find compiled code in cache", &["shard_id"], ) .unwrap() diff --git a/runtime/near-vm-runner/src/near_vm_runner/runner.rs b/runtime/near-vm-runner/src/near_vm_runner/runner.rs index 0290f3eff4a..932d5829002 100644 --- a/runtime/near-vm-runner/src/near_vm_runner/runner.rs +++ b/runtime/near-vm-runner/src/near_vm_runner/runner.rs @@ -240,7 +240,7 @@ impl NearVM { metrics::COMPILED_CONTRACT_CACHE_MISS .with_label_values(&[ &context.shard_id.to_string(), - &context.metrics_context.unwrap_or("unknown"), + context.apply_reason.as_ref().map_or("unknown", |r| r.as_str()), ]) .inc(); return Err(VMRunnerError::CacheError(CacheError::ReadError( @@ -250,7 +250,7 @@ impl NearVM { metrics::COMPILED_CONTRACT_CACHE_HIT .with_label_values(&[ &context.shard_id.to_string(), - &context.metrics_context.unwrap_or("unknown"), + context.apply_reason.as_ref().map_or("unknown", |r| r.as_str()), ]) .inc(); diff --git a/runtime/near-vm-runner/src/tests.rs b/runtime/near-vm-runner/src/tests.rs index b873f0ace55..72e467beb50 100644 --- a/runtime/near-vm-runner/src/tests.rs +++ b/runtime/near-vm-runner/src/tests.rs @@ -71,6 +71,6 @@ fn create_context(input: Vec) -> VMContext { view_config: None, output_data_receivers: vec![], shard_id: ShardUId::single_shard().shard_id(), - metrics_context: None, + apply_reason: None, } } diff --git a/runtime/near-vm-runner/src/tests/fuzzers.rs b/runtime/near-vm-runner/src/tests/fuzzers.rs index fa144daa9f2..4339cc37b5f 100644 --- a/runtime/near-vm-runner/src/tests/fuzzers.rs +++ b/runtime/near-vm-runner/src/tests/fuzzers.rs @@ -57,7 +57,7 @@ pub fn create_context(input: Vec) -> VMContext { view_config: None, output_data_receivers: vec![], shard_id: ShardUId::single_shard().shard_id(), - metrics_context: None, + apply_reason: None, } } diff --git a/runtime/near-vm-runner/src/tests/test_builder.rs b/runtime/near-vm-runner/src/tests/test_builder.rs index 903c0c6a8d0..d43e9c8151a 100644 --- a/runtime/near-vm-runner/src/tests/test_builder.rs +++ b/runtime/near-vm-runner/src/tests/test_builder.rs @@ -28,7 +28,7 @@ pub(crate) fn test_builder() -> TestBuilder { view_config: None, output_data_receivers: vec![], shard_id: ShardUId::single_shard().shard_id(), - metrics_context: None, + apply_reason: None, }; let mut skip = HashSet::new(); for kind in [VMKind::Wasmer0, VMKind::Wasmer2, VMKind::NearVm, VMKind::Wasmtime] { diff --git a/runtime/runtime-params-estimator/src/vm_estimator.rs b/runtime/runtime-params-estimator/src/vm_estimator.rs index 00068a434b4..4ed599267d7 100644 --- a/runtime/runtime-params-estimator/src/vm_estimator.rs +++ b/runtime/runtime-params-estimator/src/vm_estimator.rs @@ -35,7 +35,7 @@ pub(crate) fn create_context(input: Vec) -> VMContext { view_config: None, output_data_receivers: vec![], shard_id: ShardUId::single_shard().shard_id(), - metrics_context: None, + apply_reason: None, } } diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index b2137a48e2a..ad787179f43 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -111,7 +111,7 @@ pub(crate) fn execute_function_call( view_config: view_config.clone(), output_data_receivers, shard_id: ShardUId::single_shard().shard_id(), - metrics_context: None, + apply_reason: None, }; // Enable caching chunk mode for the function call. This allows to charge for nodes touched in a chunk only once for diff --git a/runtime/runtime/src/lib.rs b/runtime/runtime/src/lib.rs index d59332dbdbf..c6341bf0a1d 100644 --- a/runtime/runtime/src/lib.rs +++ b/runtime/runtime/src/lib.rs @@ -78,8 +78,11 @@ const EXPECT_ACCOUNT_EXISTS: &str = "account exists, checked above"; #[derive(Debug)] pub struct ApplyState { - pub apply_reason: Option<&'static str>, + /// The shard whose state is the apply operations is running on. pub shard_id: ShardId, + /// Represents a phase of the chain lifecycle that we want to run apply for. + /// This is currently represented as a static string and used as dimension in some metrics. + pub apply_reason: Option<&'static str>, /// Currently building block height. pub block_height: BlockHeight, /// Prev block hash diff --git a/tools/state-viewer/src/apply_chain_range.rs b/tools/state-viewer/src/apply_chain_range.rs index 40f03f6e3f8..07163197d2e 100644 --- a/tools/state-viewer/src/apply_chain_range.rs +++ b/tools/state-viewer/src/apply_chain_range.rs @@ -2,12 +2,13 @@ use crate::cli::ApplyRangeMode; use near_chain::chain::collect_receipts_from_response; use near_chain::migrations::check_if_block_is_first_with_chunk_of_version; use near_chain::types::{ - ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, ApplyChunkShardContext, - RuntimeAdapter, RuntimeStorageConfig, + ApplyChunkBlockContext, ApplyChunkResult, ApplyChunkShardContext, RuntimeAdapter, + RuntimeStorageConfig, }; use near_chain::{ChainStore, ChainStoreAccess, ChainStoreUpdate}; use near_chain_configs::Genesis; use near_epoch_manager::{EpochManagerAdapter, EpochManagerHandle}; +use near_primitives::apply::ApplyChunkReason; use near_primitives::receipt::DelayedReceiptIndices; use near_primitives::transaction::{Action, ExecutionOutcomeWithId, ExecutionOutcomeWithProof}; use near_primitives::trie_key::TrieKey; @@ -234,7 +235,7 @@ fn apply_block_from_range( runtime_adapter .apply_chunk( RuntimeStorageConfig::new(*chunk_inner.prev_state_root(), use_flat_storage), - ApplyChunkReason::UpdateShard, + ApplyChunkReason::UpdateTrackedShard, ApplyChunkShardContext { shard_id, last_validator_proposals: chunk_inner.prev_validator_proposals(), @@ -259,7 +260,7 @@ fn apply_block_from_range( runtime_adapter .apply_chunk( RuntimeStorageConfig::new(*chunk_extra.state_root(), use_flat_storage), - ApplyChunkReason::UpdateShard, + ApplyChunkReason::UpdateTrackedShard, ApplyChunkShardContext { shard_id, last_validator_proposals: chunk_extra.validator_proposals(), diff --git a/tools/state-viewer/src/apply_chunk.rs b/tools/state-viewer/src/apply_chunk.rs index 64875d09b0d..b0c801f6b02 100644 --- a/tools/state-viewer/src/apply_chunk.rs +++ b/tools/state-viewer/src/apply_chunk.rs @@ -3,11 +3,12 @@ use borsh::BorshDeserialize; use near_chain::chain::collect_receipts_from_response; use near_chain::migrations::check_if_block_is_first_with_chunk_of_version; use near_chain::types::{ - ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, ApplyChunkShardContext, - RuntimeAdapter, RuntimeStorageConfig, + ApplyChunkBlockContext, ApplyChunkResult, ApplyChunkShardContext, RuntimeAdapter, + RuntimeStorageConfig, }; use near_chain::{ChainStore, ChainStoreAccess}; use near_epoch_manager::{EpochManagerAdapter, EpochManagerHandle}; +use near_primitives::apply::ApplyChunkReason; use near_primitives::hash::CryptoHash; use near_primitives::merkle::combine_hash; use near_primitives::receipt::Receipt; @@ -133,7 +134,7 @@ pub(crate) fn apply_chunk( Ok(( runtime.apply_chunk( RuntimeStorageConfig::new(prev_state_root, use_flat_storage), - ApplyChunkReason::UpdateShard, + ApplyChunkReason::UpdateTrackedShard, ApplyChunkShardContext { shard_id, last_validator_proposals: chunk_header.prev_validator_proposals(), diff --git a/tools/state-viewer/src/commands.rs b/tools/state-viewer/src/commands.rs index 4b5f6759822..257cb7e69b1 100644 --- a/tools/state-viewer/src/commands.rs +++ b/tools/state-viewer/src/commands.rs @@ -14,8 +14,8 @@ use itertools::Itertools; use near_chain::chain::collect_receipts_from_response; use near_chain::migrations::check_if_block_is_first_with_chunk_of_version; use near_chain::types::{ - ApplyChunkBlockContext, ApplyChunkReason, ApplyChunkResult, ApplyChunkShardContext, - RuntimeAdapter, RuntimeStorageConfig, + ApplyChunkBlockContext, ApplyChunkResult, ApplyChunkShardContext, RuntimeAdapter, + RuntimeStorageConfig, }; use near_chain::{ChainStore, ChainStoreAccess, ChainStoreUpdate, Error}; use near_chain_configs::GenesisChangeConfig; @@ -23,6 +23,7 @@ use near_epoch_manager::types::BlockHeaderInfo; use near_epoch_manager::EpochManagerHandle; use near_epoch_manager::{EpochManager, EpochManagerAdapter}; use near_primitives::account::id::AccountId; +use near_primitives::apply::ApplyChunkReason; use near_primitives::block::{Block, BlockHeader}; use near_primitives::hash::CryptoHash; use near_primitives::shard_layout::ShardLayout; @@ -93,7 +94,7 @@ pub(crate) fn apply_block( runtime .apply_chunk( RuntimeStorageConfig::new(*chunk_inner.prev_state_root(), use_flat_storage), - ApplyChunkReason::UpdateShard, + ApplyChunkReason::UpdateTrackedShard, ApplyChunkShardContext { shard_id, last_validator_proposals: chunk_inner.prev_validator_proposals(), @@ -116,7 +117,7 @@ pub(crate) fn apply_block( runtime .apply_chunk( RuntimeStorageConfig::new(*chunk_extra.state_root(), use_flat_storage), - ApplyChunkReason::UpdateShard, + ApplyChunkReason::UpdateTrackedShard, ApplyChunkShardContext { shard_id, last_validator_proposals: chunk_extra.validator_proposals(), From 005cde2f5247ae2d91286b1f4a412cf0dc269f22 Mon Sep 17 00:00:00 2001 From: Tayfun Elmas Date: Mon, 29 Apr 2024 10:35:11 -0700 Subject: [PATCH 04/15] Change string to ApplyChunkReason in ApplyState --- chain/chain/src/runtime/mod.rs | 4 +--- integration-tests/src/tests/runtime/state_viewer.rs | 4 ---- integration-tests/src/user/runtime_user.rs | 2 -- runtime/near-vm-runner/src/logic/context.rs | 6 ++++-- .../runtime-params-estimator/src/estimator_context.rs | 1 - runtime/runtime/src/lib.rs | 11 ++++------- runtime/runtime/src/state_viewer/mod.rs | 3 --- runtime/runtime/tests/runtime_group_tools/mod.rs | 1 - 8 files changed, 9 insertions(+), 23 deletions(-) diff --git a/chain/chain/src/runtime/mod.rs b/chain/chain/src/runtime/mod.rs index 05646ffd113..bac0c3879b8 100644 --- a/chain/chain/src/runtime/mod.rs +++ b/chain/chain/src/runtime/mod.rs @@ -363,8 +363,7 @@ impl NightshadeRuntime { ); let apply_state = ApplyState { - apply_reason: Some(apply_reason.as_str()), - shard_id: chunk.shard_id, + apply_reason: Some(apply_reason), block_height, prev_block_hash: *prev_block_hash, block_hash, @@ -1326,7 +1325,6 @@ impl node_runtime::adapter::ViewRuntimeAdapter for NightshadeRuntime { cache: Some(Box::new(self.compiled_contract_cache.handle())), }; self.trie_viewer.call_function( - shard_uid.shard_id(), state_update, view_state, contract_id, diff --git a/integration-tests/src/tests/runtime/state_viewer.rs b/integration-tests/src/tests/runtime/state_viewer.rs index 73b695288b2..c549d158cc4 100644 --- a/integration-tests/src/tests/runtime/state_viewer.rs +++ b/integration-tests/src/tests/runtime/state_viewer.rs @@ -119,7 +119,6 @@ fn test_view_call() { cache: None, }; let result = viewer.call_function( - ShardUId::single_shard().shard_id(), root, view_state, &"test.contract".parse().unwrap(), @@ -149,7 +148,6 @@ fn test_view_call_try_changing_storage() { cache: None, }; let result = viewer.call_function( - ShardUId::single_shard().shard_id(), root, view_state, &"test.contract".parse().unwrap(), @@ -183,7 +181,6 @@ fn test_view_call_with_args() { cache: None, }; let view_call_result = viewer.call_function( - ShardUId::single_shard().shard_id(), root, view_state, &"test.contract".parse().unwrap(), @@ -407,7 +404,6 @@ fn test_log_when_panic() { let mut logs = vec![]; viewer .call_function( - ShardUId::single_shard().shard_id(), root, view_state, &"test.contract".parse().unwrap(), diff --git a/integration-tests/src/user/runtime_user.rs b/integration-tests/src/user/runtime_user.rs index b88dfe0d37e..cf55ed99647 100644 --- a/integration-tests/src/user/runtime_user.rs +++ b/integration-tests/src/user/runtime_user.rs @@ -156,7 +156,6 @@ impl RuntimeUser { ApplyState { apply_reason: None, - shard_id: ShardUId::single_shard().shard_id(), block_height: 1, prev_block_hash: Default::default(), block_hash: Default::default(), @@ -305,7 +304,6 @@ impl User for RuntimeUser { result.result = self .trie_viewer .call_function( - ShardUId::single_shard().shard_id(), state_update, view_state, account_id, diff --git a/runtime/near-vm-runner/src/logic/context.rs b/runtime/near-vm-runner/src/logic/context.rs index 190f3e59e48..eb775d136d5 100644 --- a/runtime/near-vm-runner/src/logic/context.rs +++ b/runtime/near-vm-runner/src/logic/context.rs @@ -52,10 +52,12 @@ pub struct VMContext { /// How many `DataReceipt`'s should receive this execution result. This should be empty if /// this function call is a part of a batch and it is not the last action. pub output_data_receivers: Vec, - /// The shard that the VM is running on. pub shard_id: ShardId, - /// Reason for running the apply-chunk operation, where this VM runs as part of. + /// Reason for running the apply-chunk operation. + /// This refers to a particular step in block production lifecycle that apply-chunk operation runs and + /// invokes this VM as part of apply-chunk. We currently use this for metric collection to differentiate + /// VM behavior (eg. compilation, caching) during these different steps. pub apply_reason: Option, } diff --git a/runtime/runtime-params-estimator/src/estimator_context.rs b/runtime/runtime-params-estimator/src/estimator_context.rs index d0251ab2a93..411258a9eaa 100644 --- a/runtime/runtime-params-estimator/src/estimator_context.rs +++ b/runtime/runtime-params-estimator/src/estimator_context.rs @@ -148,7 +148,6 @@ impl<'c> EstimatorContext<'c> { let shard_id = ShardUId::single_shard().shard_id(); ApplyState { apply_reason: None, - shard_id: ShardUId::single_shard().shard_id(), // Put each runtime into a separate shard. block_height: 1, // Epoch length is long enough to avoid corner cases. diff --git a/runtime/runtime/src/lib.rs b/runtime/runtime/src/lib.rs index 32f47ba3d89..e2f3e0c7266 100644 --- a/runtime/runtime/src/lib.rs +++ b/runtime/runtime/src/lib.rs @@ -34,17 +34,17 @@ use near_primitives::transaction::{ SignedTransaction, TransferAction, }; use near_primitives::trie_key::TrieKey; -use near_primitives::types::ShardId; use near_primitives::types::{ validator_stake::ValidatorStake, AccountId, Balance, BlockHeight, Compute, EpochHeight, - EpochId, EpochInfoProvider, Gas, RawStateChangesWithTrieKey, StateChangeCause, StateRoot, + EpochId, EpochInfoProvider, Gas, RawStateChangesWithTrieKey, ShardId, StateChangeCause, + StateRoot, }; use near_primitives::utils::{ create_action_hash_from_receipt_id, create_receipt_id_from_receipt_id, create_receipt_id_from_transaction, }; use near_primitives::version::{ProtocolFeature, ProtocolVersion}; -use near_primitives_core::types::ShardId; +use near_primitives_core::apply::ApplyChunkReason; use near_store::trie::receipts_column_helper::{DelayedReceiptQueue, TrieQueue}; use near_store::{ get, get_account, get_postponed_receipt, get_promise_yield_receipt, get_received_data, @@ -80,11 +80,9 @@ const EXPECT_ACCOUNT_EXISTS: &str = "account exists, checked above"; #[derive(Debug)] pub struct ApplyState { - /// The shard whose state is the apply operations is running on. - pub shard_id: ShardId, /// Represents a phase of the chain lifecycle that we want to run apply for. /// This is currently represented as a static string and used as dimension in some metrics. - pub apply_reason: Option<&'static str>, + pub apply_reason: Option, /// Currently building block height. pub block_height: BlockHeight, /// Prev block hash @@ -2002,7 +2000,6 @@ mod tests { let contract_cache = FilesystemContractRuntimeCache::test().unwrap(); let apply_state = ApplyState { apply_reason: None, - shard_id: ShardUId::single_shard().shard_id(), block_height: 1, prev_block_hash: Default::default(), block_hash: Default::default(), diff --git a/runtime/runtime/src/state_viewer/mod.rs b/runtime/runtime/src/state_viewer/mod.rs index 0b3ed1226fc..12a86036612 100644 --- a/runtime/runtime/src/state_viewer/mod.rs +++ b/runtime/runtime/src/state_viewer/mod.rs @@ -15,7 +15,6 @@ use near_primitives::types::{AccountId, EpochInfoProvider, Gas}; use near_primitives::version::PROTOCOL_VERSION; use near_primitives::views::{StateItem, ViewApplyState, ViewStateResult}; use near_primitives_core::config::ViewConfig; -use near_primitives_core::types::ShardId; use near_store::{get_access_key, get_account, get_code, TrieUpdate}; use near_vm_runner::logic::ReturnData; use near_vm_runner::ContractCode; @@ -156,7 +155,6 @@ impl TrieViewer { pub fn call_function( &self, - shard_id: ShardId, mut state_update: TrieUpdate, view_state: ViewApplyState, contract_id: &AccountId, @@ -192,7 +190,6 @@ impl TrieViewer { let config = config_store.get_config(PROTOCOL_VERSION); let apply_state = ApplyState { apply_reason: None, - shard_id: shard_id, block_height: view_state.block_height, // Used for legacy reasons prev_block_hash: view_state.prev_block_hash, diff --git a/runtime/runtime/tests/runtime_group_tools/mod.rs b/runtime/runtime/tests/runtime_group_tools/mod.rs index e3596187e4a..dbc04c0804a 100644 --- a/runtime/runtime/tests/runtime_group_tools/mod.rs +++ b/runtime/runtime/tests/runtime_group_tools/mod.rs @@ -98,7 +98,6 @@ impl StandaloneRuntime { let apply_state = ApplyState { apply_reason: None, - shard_id: ShardUId::single_shard().shard_id(), block_height: 1, prev_block_hash: Default::default(), block_hash: Default::default(), From eec1b287835a4edcbe474f452256847f1b6e4b0f Mon Sep 17 00:00:00 2001 From: Tayfun Elmas Date: Mon, 29 Apr 2024 11:48:16 -0700 Subject: [PATCH 05/15] Address clippy findings. --- integration-tests/src/tests/runtime/state_viewer.rs | 1 - runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs | 2 +- runtime/near-vm-runner/src/tests.rs | 2 +- runtime/near-vm-runner/src/tests/fuzzers.rs | 2 +- runtime/near-vm-runner/src/tests/test_builder.rs | 2 +- runtime/runtime/src/actions.rs | 1 - 6 files changed, 4 insertions(+), 6 deletions(-) diff --git a/integration-tests/src/tests/runtime/state_viewer.rs b/integration-tests/src/tests/runtime/state_viewer.rs index c549d158cc4..df4ba18b088 100644 --- a/integration-tests/src/tests/runtime/state_viewer.rs +++ b/integration-tests/src/tests/runtime/state_viewer.rs @@ -3,7 +3,6 @@ use std::{collections::HashMap, io, sync::Arc}; use borsh::BorshDeserialize; use crate::runtime_utils::{get_runtime_and_trie, get_test_trie_viewer, TEST_SHARD_UID}; -use near_primitives::shard_layout::ShardUId; use near_primitives::{ account::Account, hash::hash as sha256, diff --git a/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs b/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs index 7e6a312be20..78472724f8b 100644 --- a/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs +++ b/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs @@ -81,7 +81,7 @@ fn get_context() -> VMContext { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], - shard_id: ShardUId::single_shard().shard_id(), + shard_id: 0, apply_reason: None, } } diff --git a/runtime/near-vm-runner/src/tests.rs b/runtime/near-vm-runner/src/tests.rs index 72e467beb50..2bae47028e7 100644 --- a/runtime/near-vm-runner/src/tests.rs +++ b/runtime/near-vm-runner/src/tests.rs @@ -70,7 +70,7 @@ fn create_context(input: Vec) -> VMContext { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], - shard_id: ShardUId::single_shard().shard_id(), + shard_id: 0, apply_reason: None, } } diff --git a/runtime/near-vm-runner/src/tests/fuzzers.rs b/runtime/near-vm-runner/src/tests/fuzzers.rs index 4339cc37b5f..573e7681cee 100644 --- a/runtime/near-vm-runner/src/tests/fuzzers.rs +++ b/runtime/near-vm-runner/src/tests/fuzzers.rs @@ -56,7 +56,7 @@ pub fn create_context(input: Vec) -> VMContext { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], - shard_id: ShardUId::single_shard().shard_id(), + shard_id: 0, apply_reason: None, } } diff --git a/runtime/near-vm-runner/src/tests/test_builder.rs b/runtime/near-vm-runner/src/tests/test_builder.rs index d43e9c8151a..90349b587bc 100644 --- a/runtime/near-vm-runner/src/tests/test_builder.rs +++ b/runtime/near-vm-runner/src/tests/test_builder.rs @@ -27,7 +27,7 @@ pub(crate) fn test_builder() -> TestBuilder { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], - shard_id: ShardUId::single_shard().shard_id(), + shard_id: 0, apply_reason: None, }; let mut skip = HashSet::new(); diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index f6facb1bf9f..2b54b9822be 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -1409,7 +1409,6 @@ mod tests { fn create_apply_state(block_height: BlockHeight) -> ApplyState { ApplyState { apply_reason: None, - shard_id: ShardUId::single_shard().shard_id(), block_height, prev_block_hash: CryptoHash::default(), block_hash: CryptoHash::default(), From 4347216145cc4027f92ceed0eca191bf96455696 Mon Sep 17 00:00:00 2001 From: Tayfun Elmas Date: Tue, 30 Apr 2024 13:55:20 -0700 Subject: [PATCH 06/15] Remove apply_reason from VContext and use exported Metrics structure to update metrics. --- runtime/near-vm-runner/fuzz/src/lib.rs | 3 - runtime/near-vm-runner/src/logic/context.rs | 10 +--- .../src/logic/tests/vm_logic_builder.rs | 2 - runtime/near-vm-runner/src/metrics.rs | 59 ++++++++++++++++++- .../src/near_vm_runner/metrics.rs | 19 ------ .../near-vm-runner/src/near_vm_runner/mod.rs | 1 - .../src/near_vm_runner/runner.rs | 18 ++---- runtime/near-vm-runner/src/tests.rs | 2 - runtime/near-vm-runner/src/tests/fuzzers.rs | 2 - .../near-vm-runner/src/tests/test_builder.rs | 2 - .../src/vm_estimator.rs | 2 - runtime/runtime/src/actions.rs | 4 +- 12 files changed, 63 insertions(+), 61 deletions(-) delete mode 100644 runtime/near-vm-runner/src/near_vm_runner/metrics.rs diff --git a/runtime/near-vm-runner/fuzz/src/lib.rs b/runtime/near-vm-runner/fuzz/src/lib.rs index 91d917c1757..a7eb0a8e92f 100644 --- a/runtime/near-vm-runner/fuzz/src/lib.rs +++ b/runtime/near-vm-runner/fuzz/src/lib.rs @@ -1,5 +1,4 @@ use core::fmt; -use near_primitives::shard_layout::ShardUId; use near_vm_runner::internal::wasmparser::{Export, ExternalKind, Parser, Payload, TypeDef}; use near_vm_runner::logic::VMContext; use near_vm_runner::ContractCode; @@ -49,8 +48,6 @@ pub fn create_context(input: Vec) -> VMContext { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], - shard_id: ShardUId::single_shard().shard_id(), - apply_reason: None, } } diff --git a/runtime/near-vm-runner/src/logic/context.rs b/runtime/near-vm-runner/src/logic/context.rs index eb775d136d5..869aa24554f 100644 --- a/runtime/near-vm-runner/src/logic/context.rs +++ b/runtime/near-vm-runner/src/logic/context.rs @@ -1,8 +1,7 @@ use super::types::PublicKey; -use near_primitives_core::apply::ApplyChunkReason; use near_primitives_core::config::ViewConfig; use near_primitives_core::types::{ - AccountId, Balance, BlockHeight, EpochHeight, Gas, ShardId, StorageUsage, + AccountId, Balance, BlockHeight, EpochHeight, Gas, StorageUsage, }; #[derive(Clone)] @@ -52,13 +51,6 @@ pub struct VMContext { /// How many `DataReceipt`'s should receive this execution result. This should be empty if /// this function call is a part of a batch and it is not the last action. pub output_data_receivers: Vec, - /// The shard that the VM is running on. - pub shard_id: ShardId, - /// Reason for running the apply-chunk operation. - /// This refers to a particular step in block production lifecycle that apply-chunk operation runs and - /// invokes this VM as part of apply-chunk. We currently use this for metric collection to differentiate - /// VM behavior (eg. compilation, caching) during these different steps. - pub apply_reason: Option, } impl VMContext { diff --git a/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs b/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs index 78472724f8b..b3358b1fa6b 100644 --- a/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs +++ b/runtime/near-vm-runner/src/logic/tests/vm_logic_builder.rs @@ -81,8 +81,6 @@ fn get_context() -> VMContext { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], - shard_id: 0, - apply_reason: None, } } diff --git a/runtime/near-vm-runner/src/metrics.rs b/runtime/near-vm-runner/src/metrics.rs index a8228449536..9dcfe9c30f6 100644 --- a/runtime/near-vm-runner/src/metrics.rs +++ b/runtime/near-vm-runner/src/metrics.rs @@ -1,4 +1,6 @@ -use near_o11y::metrics::{try_create_histogram_vec, HistogramVec}; +use near_o11y::metrics::{ + try_create_histogram_vec, try_create_int_counter_vec, HistogramVec, IntCounterVec, +}; use once_cell::sync::Lazy; use std::{cell::RefCell, time::Duration}; @@ -6,6 +8,7 @@ thread_local! { static METRICS: RefCell = const { RefCell::new(Metrics { near_vm_compilation_time: Duration::new(0, 0), wasmtime_compilation_time: Duration::new(0, 0), + compiled_contract_cache_hit: None, }) }; } @@ -19,10 +22,30 @@ pub static COMPILATION_TIME: Lazy = Lazy::new(|| { .unwrap() }); +pub static COMPILED_CONTRACT_CACHE_HIT: Lazy = Lazy::new(|| { + try_create_int_counter_vec( + "near_vm_compiled_contract_cache_hits_total", + "The number of times the runtime finds compiled code in cache for the given caller context and shard_id", + &["context", "shard_id"], + ) + .unwrap() +}); + +pub static COMPILED_CONTRACT_CACHE_MISS: Lazy = Lazy::new(|| { + try_create_int_counter_vec( + "near_vm_compiled_contract_cache_misses_total", + "The number of times the runtime cannot find compiled code in cache for the given caller context and shard_id", + &["context", "shard_id"], + ) + .unwrap() +}); + #[derive(Default, Copy, Clone)] pub struct Metrics { near_vm_compilation_time: Duration, wasmtime_compilation_time: Duration, + /// True iff the runtime checked the compiled contract cache and found already-compiled code. + compiled_contract_cache_hit: Option, } impl Metrics { @@ -37,7 +60,8 @@ impl Metrics { METRICS.with_borrow(|m| *m) } - pub fn report(&mut self, shard_id: &str) { + /// Report the current metrics at the end of a single VM invocation (eg. to run a function call). + pub fn report(&mut self, shard_id: &str, caller_context: &str) { if !self.near_vm_compilation_time.is_zero() { COMPILATION_TIME .with_label_values(&["near_vm", shard_id]) @@ -50,6 +74,15 @@ impl Metrics { .observe(self.wasmtime_compilation_time.as_secs_f64()); self.wasmtime_compilation_time = Duration::default(); } + match self.compiled_contract_cache_hit.take() { + Some(true) => { + COMPILED_CONTRACT_CACHE_HIT.with_label_values(&[caller_context, shard_id]).inc(); + } + Some(false) => { + COMPILED_CONTRACT_CACHE_MISS.with_label_values(&[caller_context, shard_id]).inc(); + } + None => {} + }; } } @@ -63,3 +96,25 @@ pub(crate) fn compilation_duration(kind: near_parameters::vm::VMKind, duration: VMKind::NearVm => m.near_vm_compilation_time += duration, }); } + +/// Updates metrics to record that the runtime has found an entry in compiled contract cache. +pub(crate) fn record_compiled_contract_cache_hit() { + METRICS.with_borrow_mut(|m| { + debug_assert!( + m.compiled_contract_cache_hit.is_none(), + "Compiled context cache hit/miss should be reported once." + ); + m.compiled_contract_cache_hit = Some(true); + }); +} + +/// Updates metrics to record that the runtime could not find an entry in compiled contract cache. +pub(crate) fn record_compiled_contract_cache_miss() { + METRICS.with_borrow_mut(|m| { + debug_assert!( + m.compiled_contract_cache_hit.is_none(), + "Compiled context cache hit/miss should be reported once." + ); + m.compiled_contract_cache_hit = Some(false); + }); +} diff --git a/runtime/near-vm-runner/src/near_vm_runner/metrics.rs b/runtime/near-vm-runner/src/near_vm_runner/metrics.rs deleted file mode 100644 index c9558e91f1b..00000000000 --- a/runtime/near-vm-runner/src/near_vm_runner/metrics.rs +++ /dev/null @@ -1,19 +0,0 @@ -use near_o11y::metrics::{try_create_int_counter_vec, IntCounterVec}; -use once_cell::sync::Lazy; - -pub static COMPILED_CONTRACT_CACHE_HIT: Lazy = Lazy::new(|| { - try_create_int_counter_vec( - "near_compiled_contract_cache_hit", - "The number of times the runtime finds compiled code in cache", - &["shard_id"], - ) - .unwrap() -}); -pub static COMPILED_CONTRACT_CACHE_MISS: Lazy = Lazy::new(|| { - try_create_int_counter_vec( - "near_compiled_contract_cache_miss", - "The number of times the runtime cannot find compiled code in cache", - &["shard_id"], - ) - .unwrap() -}); diff --git a/runtime/near-vm-runner/src/near_vm_runner/mod.rs b/runtime/near-vm-runner/src/near_vm_runner/mod.rs index c751534f0f7..f2c7b48b5b4 100644 --- a/runtime/near-vm-runner/src/near_vm_runner/mod.rs +++ b/runtime/near-vm-runner/src/near_vm_runner/mod.rs @@ -1,5 +1,4 @@ mod memory; -mod metrics; mod runner; pub use memory::NearVmMemory; diff --git a/runtime/near-vm-runner/src/near_vm_runner/runner.rs b/runtime/near-vm-runner/src/near_vm_runner/runner.rs index 0da24cc9f2b..cb2878ac51f 100644 --- a/runtime/near-vm-runner/src/near_vm_runner/runner.rs +++ b/runtime/near-vm-runner/src/near_vm_runner/runner.rs @@ -1,4 +1,4 @@ -use super::{metrics, NearVmMemory, VM_CONFIG}; +use super::{NearVmMemory, VM_CONFIG}; use crate::cache::CompiledContractInfo; use crate::errors::ContractPrecompilatonResult; use crate::imports::near_vm::NearVmImports; @@ -239,23 +239,12 @@ impl NearVM { let key = get_contract_cache_key(code_hash, &self.config); let cache_record = cache.get(&key).map_err(CacheError::ReadError)?; let Some(code) = cache_record else { - metrics::COMPILED_CONTRACT_CACHE_MISS - .with_label_values(&[ - &context.shard_id.to_string(), - context.apply_reason.as_ref().map_or("unknown", |r| r.as_str()), - ]) - .inc(); + crate::metrics::record_compiled_contract_cache_miss(); return Err(VMRunnerError::CacheError(CacheError::ReadError( std::io::Error::from(std::io::ErrorKind::NotFound), ))); }; - metrics::COMPILED_CONTRACT_CACHE_HIT - .with_label_values(&[ - &context.shard_id.to_string(), - context.apply_reason.as_ref().map_or("unknown", |r| r.as_str()), - ]) - .inc(); - + match &code.compiled { CompiledContract::CompileModuleError(err) => { Ok::<_, VMRunnerError>(to_any((code.wasm_bytes, Err(err.clone())))) @@ -307,6 +296,7 @@ impl NearVM { move |value| { let _span = tracing::debug_span!(target: "vm", "NearVM::load_from_mem_cache").entered(); + crate::metrics::record_compiled_contract_cache_hit(); let &(wasm_bytes, ref downcast) = value .downcast_ref::() .expect("downcast should always succeed"); diff --git a/runtime/near-vm-runner/src/tests.rs b/runtime/near-vm-runner/src/tests.rs index 2bae47028e7..bacca8c2c10 100644 --- a/runtime/near-vm-runner/src/tests.rs +++ b/runtime/near-vm-runner/src/tests.rs @@ -70,7 +70,5 @@ fn create_context(input: Vec) -> VMContext { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], - shard_id: 0, - apply_reason: None, } } diff --git a/runtime/near-vm-runner/src/tests/fuzzers.rs b/runtime/near-vm-runner/src/tests/fuzzers.rs index 573e7681cee..5d0ce4af948 100644 --- a/runtime/near-vm-runner/src/tests/fuzzers.rs +++ b/runtime/near-vm-runner/src/tests/fuzzers.rs @@ -56,8 +56,6 @@ pub fn create_context(input: Vec) -> VMContext { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], - shard_id: 0, - apply_reason: None, } } diff --git a/runtime/near-vm-runner/src/tests/test_builder.rs b/runtime/near-vm-runner/src/tests/test_builder.rs index 90349b587bc..b765f89876d 100644 --- a/runtime/near-vm-runner/src/tests/test_builder.rs +++ b/runtime/near-vm-runner/src/tests/test_builder.rs @@ -27,8 +27,6 @@ pub(crate) fn test_builder() -> TestBuilder { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], - shard_id: 0, - apply_reason: None, }; let mut skip = HashSet::new(); for kind in [VMKind::Wasmer0, VMKind::Wasmer2, VMKind::NearVm, VMKind::Wasmtime] { diff --git a/runtime/runtime-params-estimator/src/vm_estimator.rs b/runtime/runtime-params-estimator/src/vm_estimator.rs index 4ed599267d7..29c4ae12d0d 100644 --- a/runtime/runtime-params-estimator/src/vm_estimator.rs +++ b/runtime/runtime-params-estimator/src/vm_estimator.rs @@ -34,8 +34,6 @@ pub(crate) fn create_context(input: Vec) -> VMContext { random_seed: vec![0, 1, 2], view_config: None, output_data_receivers: vec![], - shard_id: ShardUId::single_shard().shard_id(), - apply_reason: None, } } diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index a96bb0dcaa2..65bb2b2a624 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -110,8 +110,6 @@ pub(crate) fn execute_function_call( random_seed, view_config: view_config.clone(), output_data_receivers, - shard_id: ShardUId::single_shard().shard_id(), - apply_reason: None, }; // Enable caching chunk mode for the function call. This allows to charge for nodes touched in a chunk only once for @@ -172,7 +170,7 @@ pub(crate) fn execute_function_call( promise_results, apply_state.cache.as_deref(), ); - metrics.report(&apply_state.shard_id.to_string()); + metrics.report(&apply_state.shard_id.to_string(), apply_state.apply_reason.to_string());); r } res => res, From 9857410c4b442920469a6279771e7f46a97c496c Mon Sep 17 00:00:00 2001 From: Tayfun Elmas Date: Tue, 30 Apr 2024 14:15:30 -0700 Subject: [PATCH 07/15] fix clippy errors and format --- .../near-vm-runner/src/near_vm_runner/runner.rs | 2 +- .../src/vm_estimator.rs | 1 - runtime/runtime/src/actions.rs | 17 ++++++++++++++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/runtime/near-vm-runner/src/near_vm_runner/runner.rs b/runtime/near-vm-runner/src/near_vm_runner/runner.rs index cb2878ac51f..f92821b173d 100644 --- a/runtime/near-vm-runner/src/near_vm_runner/runner.rs +++ b/runtime/near-vm-runner/src/near_vm_runner/runner.rs @@ -244,7 +244,7 @@ impl NearVM { std::io::Error::from(std::io::ErrorKind::NotFound), ))); }; - + match &code.compiled { CompiledContract::CompileModuleError(err) => { Ok::<_, VMRunnerError>(to_any((code.wasm_bytes, Err(err.clone())))) diff --git a/runtime/runtime-params-estimator/src/vm_estimator.rs b/runtime/runtime-params-estimator/src/vm_estimator.rs index 29c4ae12d0d..72bd4415ed6 100644 --- a/runtime/runtime-params-estimator/src/vm_estimator.rs +++ b/runtime/runtime-params-estimator/src/vm_estimator.rs @@ -3,7 +3,6 @@ use crate::gas_cost::{GasCost, LeastSquaresTolerance}; use crate::{utils::read_resource, REAL_CONTRACTS_SAMPLE}; use near_parameters::vm::VMKind; use near_parameters::RuntimeConfigStore; -use near_primitives::shard_layout::ShardUId; use near_primitives::version::PROTOCOL_VERSION; use near_vm_runner::internal::VMKindExt; use near_vm_runner::logic::VMContext; diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index 65bb2b2a624..cd0b7eaba19 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -42,7 +42,6 @@ use near_vm_runner::precompile_contract; use near_vm_runner::ContractCode; use near_wallet_contract::{wallet_contract, wallet_contract_magic_bytes}; -use near_primitives::shard_layout::ShardUId; use std::sync::Arc; /// Returns `ContractCode` (if exists) for the given `account` or returns `StorageError`. @@ -131,7 +130,13 @@ pub(crate) fn execute_function_call( promise_results, apply_state.cache.as_deref(), ); - metrics.report(&apply_state.shard_id.to_string()); + metrics.report( + &apply_state.shard_id.to_string(), + &apply_state + .apply_reason + .as_ref() + .map_or_else(|| String::from("unknown"), |r| r.to_string()), + ); let result = match result_from_cache { Err(VMRunnerError::CacheError(CacheError::ReadError(err))) if err.kind() == std::io::ErrorKind::NotFound => @@ -170,7 +175,13 @@ pub(crate) fn execute_function_call( promise_results, apply_state.cache.as_deref(), ); - metrics.report(&apply_state.shard_id.to_string(), apply_state.apply_reason.to_string());); + metrics.report( + &apply_state.shard_id.to_string(), + &apply_state + .apply_reason + .as_ref() + .map_or_else(|| String::from("unknown"), |r| r.to_string()), + ); r } res => res, From 15d66a962d36bb624d66db8fad7d635f553309ba Mon Sep 17 00:00:00 2001 From: Tayfun Elmas Date: Tue, 30 Apr 2024 14:22:10 -0700 Subject: [PATCH 08/15] Add one more cache hit record. --- runtime/near-vm-runner/src/near_vm_runner/runner.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/near-vm-runner/src/near_vm_runner/runner.rs b/runtime/near-vm-runner/src/near_vm_runner/runner.rs index f92821b173d..b07cc07ee65 100644 --- a/runtime/near-vm-runner/src/near_vm_runner/runner.rs +++ b/runtime/near-vm-runner/src/near_vm_runner/runner.rs @@ -244,6 +244,7 @@ impl NearVM { std::io::Error::from(std::io::ErrorKind::NotFound), ))); }; + crate::metrics::record_compiled_contract_cache_hit(); match &code.compiled { CompiledContract::CompileModuleError(err) => { From b4dfbf1f1c5849e557cbd74cb9cabe9278754907 Mon Sep 17 00:00:00 2001 From: Tayfun Elmas Date: Tue, 30 Apr 2024 14:36:09 -0700 Subject: [PATCH 09/15] Merge hit and miss functions and also move metrics.record to record only once. --- runtime/near-vm-runner/src/metrics.rs | 20 +++++-------------- .../src/near_vm_runner/runner.rs | 6 +++--- runtime/runtime/src/actions.rs | 18 +++++++++-------- 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/runtime/near-vm-runner/src/metrics.rs b/runtime/near-vm-runner/src/metrics.rs index 9dcfe9c30f6..c995d44a390 100644 --- a/runtime/near-vm-runner/src/metrics.rs +++ b/runtime/near-vm-runner/src/metrics.rs @@ -97,24 +97,14 @@ pub(crate) fn compilation_duration(kind: near_parameters::vm::VMKind, duration: }); } -/// Updates metrics to record that the runtime has found an entry in compiled contract cache. -pub(crate) fn record_compiled_contract_cache_hit() { +/// Updates metrics to record a compiled-contract cache lookup that finds +/// an entry in the cache (is_hit=true) or not (is_hit=false). +pub(crate) fn record_compiled_contract_cache_lookup(is_hit: bool) { METRICS.with_borrow_mut(|m| { debug_assert!( m.compiled_contract_cache_hit.is_none(), - "Compiled context cache hit/miss should be reported once." + "Compiled contract cache lookup should be reported once." ); - m.compiled_contract_cache_hit = Some(true); - }); -} - -/// Updates metrics to record that the runtime could not find an entry in compiled contract cache. -pub(crate) fn record_compiled_contract_cache_miss() { - METRICS.with_borrow_mut(|m| { - debug_assert!( - m.compiled_contract_cache_hit.is_none(), - "Compiled context cache hit/miss should be reported once." - ); - m.compiled_contract_cache_hit = Some(false); + m.compiled_contract_cache_hit = Some(is_hit); }); } diff --git a/runtime/near-vm-runner/src/near_vm_runner/runner.rs b/runtime/near-vm-runner/src/near_vm_runner/runner.rs index b07cc07ee65..582e7e58e79 100644 --- a/runtime/near-vm-runner/src/near_vm_runner/runner.rs +++ b/runtime/near-vm-runner/src/near_vm_runner/runner.rs @@ -239,12 +239,12 @@ impl NearVM { let key = get_contract_cache_key(code_hash, &self.config); let cache_record = cache.get(&key).map_err(CacheError::ReadError)?; let Some(code) = cache_record else { - crate::metrics::record_compiled_contract_cache_miss(); + crate::metrics::record_compiled_contract_cache_lookup(false); return Err(VMRunnerError::CacheError(CacheError::ReadError( std::io::Error::from(std::io::ErrorKind::NotFound), ))); }; - crate::metrics::record_compiled_contract_cache_hit(); + crate::metrics::record_compiled_contract_cache_lookup(true); match &code.compiled { CompiledContract::CompileModuleError(err) => { @@ -297,7 +297,7 @@ impl NearVM { move |value| { let _span = tracing::debug_span!(target: "vm", "NearVM::load_from_mem_cache").entered(); - crate::metrics::record_compiled_contract_cache_hit(); + crate::metrics::record_compiled_contract_cache_lookup(true); let &(wasm_bytes, ref downcast) = value .downcast_ref::() .expect("downcast should always succeed"); diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index cd0b7eaba19..1a69abab4e6 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -130,13 +130,6 @@ pub(crate) fn execute_function_call( promise_results, apply_state.cache.as_deref(), ); - metrics.report( - &apply_state.shard_id.to_string(), - &apply_state - .apply_reason - .as_ref() - .map_or_else(|| String::from("unknown"), |r| r.to_string()), - ); let result = match result_from_cache { Err(VMRunnerError::CacheError(CacheError::ReadError(err))) if err.kind() == std::io::ErrorKind::NotFound => @@ -184,7 +177,16 @@ pub(crate) fn execute_function_call( ); r } - res => res, + res => { + metrics.report( + &apply_state.shard_id.to_string(), + &apply_state + .apply_reason + .as_ref() + .map_or_else(|| String::from("unknown"), |r| r.to_string()), + ); + res + } }; if checked_feature!("stable", ChunkNodesCache, protocol_version) { From 7beb96ddead5b723601bc703ad30d5dc520c0927 Mon Sep 17 00:00:00 2001 From: Tayfun Elmas Date: Wed, 1 May 2024 11:25:24 -0700 Subject: [PATCH 10/15] Address comments v1 --- runtime/near-vm-runner/src/metrics.rs | 55 +++++++++++++++------------ 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/runtime/near-vm-runner/src/metrics.rs b/runtime/near-vm-runner/src/metrics.rs index c995d44a390..0d95467e0af 100644 --- a/runtime/near-vm-runner/src/metrics.rs +++ b/runtime/near-vm-runner/src/metrics.rs @@ -8,7 +8,8 @@ thread_local! { static METRICS: RefCell = const { RefCell::new(Metrics { near_vm_compilation_time: Duration::new(0, 0), wasmtime_compilation_time: Duration::new(0, 0), - compiled_contract_cache_hit: None, + compiled_contract_cache_lookups: 0, + compiled_contract_cache_hits: 0, }) }; } @@ -22,19 +23,19 @@ pub static COMPILATION_TIME: Lazy = Lazy::new(|| { .unwrap() }); -pub static COMPILED_CONTRACT_CACHE_HIT: Lazy = Lazy::new(|| { +pub static COMPILED_CONTRACT_CACHE_LOOKUPS_TOTAL: Lazy = Lazy::new(|| { try_create_int_counter_vec( - "near_vm_compiled_contract_cache_hits_total", - "The number of times the runtime finds compiled code in cache for the given caller context and shard_id", + "near_vm_compiled_contract_cache_lookups_total", + "The number of times the runtime looks up for an entry in the compiled-contract cache for the given caller context and shard_id", &["context", "shard_id"], ) .unwrap() }); -pub static COMPILED_CONTRACT_CACHE_MISS: Lazy = Lazy::new(|| { +pub static COMPILED_CONTRACT_CACHE_HITS_TOTAL: Lazy = Lazy::new(|| { try_create_int_counter_vec( - "near_vm_compiled_contract_cache_misses_total", - "The number of times the runtime cannot find compiled code in cache for the given caller context and shard_id", + "near_vm_compiled_contract_cache_hits_total", + "The number of times the runtime finds an entry in the compiled-contract cache for the given caller context and shard_id", &["context", "shard_id"], ) .unwrap() @@ -44,8 +45,10 @@ pub static COMPILED_CONTRACT_CACHE_MISS: Lazy = Lazy::new(|| { pub struct Metrics { near_vm_compilation_time: Duration, wasmtime_compilation_time: Duration, - /// True iff the runtime checked the compiled contract cache and found already-compiled code. - compiled_contract_cache_hit: Option, + /// Number of lookups from the compiled contract cache. + compiled_contract_cache_lookups: u64, + /// Number of times the lookup from the compiled contract cache finds a match. + compiled_contract_cache_hits: u64, } impl Metrics { @@ -74,15 +77,18 @@ impl Metrics { .observe(self.wasmtime_compilation_time.as_secs_f64()); self.wasmtime_compilation_time = Duration::default(); } - match self.compiled_contract_cache_hit.take() { - Some(true) => { - COMPILED_CONTRACT_CACHE_HIT.with_label_values(&[caller_context, shard_id]).inc(); - } - Some(false) => { - COMPILED_CONTRACT_CACHE_MISS.with_label_values(&[caller_context, shard_id]).inc(); - } - None => {} - }; + if self.compiled_contract_cache_lookups > 0 { + COMPILED_CONTRACT_CACHE_LOOKUPS_TOTAL + .with_label_values(&[caller_context, shard_id]) + .inc_by(self.compiled_contract_cache_lookups); + self.compiled_contract_cache_lookups = 0; + } + if self.compiled_contract_cache_hits > 0 { + COMPILED_CONTRACT_CACHE_HITS_TOTAL + .with_label_values(&[caller_context, shard_id]) + .inc_by(self.compiled_contract_cache_lookups); + self.compiled_contract_cache_hits = 0; + } } } @@ -97,14 +103,13 @@ pub(crate) fn compilation_duration(kind: near_parameters::vm::VMKind, duration: }); } -/// Updates metrics to record a compiled-contract cache lookup that finds -/// an entry in the cache (is_hit=true) or not (is_hit=false). +/// Updates metrics to record a compiled-contract cache lookup, +/// where is_hit=true indicates that we found an entry in the cache. pub(crate) fn record_compiled_contract_cache_lookup(is_hit: bool) { METRICS.with_borrow_mut(|m| { - debug_assert!( - m.compiled_contract_cache_hit.is_none(), - "Compiled contract cache lookup should be reported once." - ); - m.compiled_contract_cache_hit = Some(is_hit); + m.compiled_contract_cache_lookups += 1; + if is_hit { + m.compiled_contract_cache_hits += 1; + } }); } From d975a9602b94d12a42f3f7dad8d504f2bc6991cb Mon Sep 17 00:00:00 2001 From: Tayfun Elmas Date: Wed, 1 May 2024 11:52:21 -0700 Subject: [PATCH 11/15] Make reset and report operations static --- runtime/near-vm-runner/src/lib.rs | 2 +- runtime/near-vm-runner/src/metrics.rs | 81 ++++++++++++--------------- runtime/near-vm-runner/src/runner.rs | 8 +-- runtime/runtime/src/actions.rs | 33 +++++------ 4 files changed, 54 insertions(+), 70 deletions(-) diff --git a/runtime/near-vm-runner/src/lib.rs b/runtime/near-vm-runner/src/lib.rs index 93138fceee1..0fa8b064d7c 100644 --- a/runtime/near-vm-runner/src/lib.rs +++ b/runtime/near-vm-runner/src/lib.rs @@ -34,7 +34,7 @@ pub use cache::{ NoContractRuntimeCache, }; pub use code::ContractCode; -pub use metrics::Metrics; +pub use metrics::{reset_metrics, report_metrics}; pub use profile::ProfileDataV3; pub use runner::{run, VM}; diff --git a/runtime/near-vm-runner/src/metrics.rs b/runtime/near-vm-runner/src/metrics.rs index 0d95467e0af..20a38f6e576 100644 --- a/runtime/near-vm-runner/src/metrics.rs +++ b/runtime/near-vm-runner/src/metrics.rs @@ -13,7 +13,7 @@ thread_local! { }) }; } -pub static COMPILATION_TIME: Lazy = Lazy::new(|| { +static COMPILATION_TIME: Lazy = Lazy::new(|| { try_create_histogram_vec( "near_vm_runner_compilation_seconds", "Histogram of how long it takes to compile things", @@ -23,7 +23,7 @@ pub static COMPILATION_TIME: Lazy = Lazy::new(|| { .unwrap() }); -pub static COMPILED_CONTRACT_CACHE_LOOKUPS_TOTAL: Lazy = Lazy::new(|| { +static COMPILED_CONTRACT_CACHE_LOOKUPS_TOTAL: Lazy = Lazy::new(|| { try_create_int_counter_vec( "near_vm_compiled_contract_cache_lookups_total", "The number of times the runtime looks up for an entry in the compiled-contract cache for the given caller context and shard_id", @@ -32,7 +32,7 @@ pub static COMPILED_CONTRACT_CACHE_LOOKUPS_TOTAL: Lazy = Lazy::ne .unwrap() }); -pub static COMPILED_CONTRACT_CACHE_HITS_TOTAL: Lazy = Lazy::new(|| { +static COMPILED_CONTRACT_CACHE_HITS_TOTAL: Lazy = Lazy::new(|| { try_create_int_counter_vec( "near_vm_compiled_contract_cache_hits_total", "The number of times the runtime finds an entry in the compiled-contract cache for the given caller context and shard_id", @@ -42,7 +42,7 @@ pub static COMPILED_CONTRACT_CACHE_HITS_TOTAL: Lazy = Lazy::new(| }); #[derive(Default, Copy, Clone)] -pub struct Metrics { +struct Metrics { near_vm_compilation_time: Duration, wasmtime_compilation_time: Duration, /// Number of lookups from the compiled contract cache. @@ -51,47 +51,6 @@ pub struct Metrics { compiled_contract_cache_hits: u64, } -impl Metrics { - pub fn reset() { - METRICS.with_borrow_mut(|m| *m = Self::default()); - } - - /// Get the current metrics. - /// - /// Note that this is a thread-local operation. - pub fn get() -> Metrics { - METRICS.with_borrow(|m| *m) - } - - /// Report the current metrics at the end of a single VM invocation (eg. to run a function call). - pub fn report(&mut self, shard_id: &str, caller_context: &str) { - if !self.near_vm_compilation_time.is_zero() { - COMPILATION_TIME - .with_label_values(&["near_vm", shard_id]) - .observe(self.near_vm_compilation_time.as_secs_f64()); - self.near_vm_compilation_time = Duration::default(); - } - if !self.wasmtime_compilation_time.is_zero() { - COMPILATION_TIME - .with_label_values(&["wasmtime", shard_id]) - .observe(self.wasmtime_compilation_time.as_secs_f64()); - self.wasmtime_compilation_time = Duration::default(); - } - if self.compiled_contract_cache_lookups > 0 { - COMPILED_CONTRACT_CACHE_LOOKUPS_TOTAL - .with_label_values(&[caller_context, shard_id]) - .inc_by(self.compiled_contract_cache_lookups); - self.compiled_contract_cache_lookups = 0; - } - if self.compiled_contract_cache_hits > 0 { - COMPILED_CONTRACT_CACHE_HITS_TOTAL - .with_label_values(&[caller_context, shard_id]) - .inc_by(self.compiled_contract_cache_lookups); - self.compiled_contract_cache_hits = 0; - } - } -} - #[cfg(any(feature = "near_vm", feature = "wasmtime_vm"))] pub(crate) fn compilation_duration(kind: near_parameters::vm::VMKind, duration: Duration) { use near_parameters::vm::VMKind; @@ -113,3 +72,35 @@ pub(crate) fn record_compiled_contract_cache_lookup(is_hit: bool) { } }); } + +pub fn reset_metrics() { + METRICS.with_borrow_mut(|m| *m = Metrics::default()); +} + +/// Reports the current metrics at the end of a single VM invocation (eg. to run a function call). +pub fn report_metrics(shard_id: &str, caller_context: &str) { + METRICS.with_borrow_mut(|m| { + if !m.near_vm_compilation_time.is_zero() { + COMPILATION_TIME + .with_label_values(&["near_vm", shard_id]) + .observe(m.near_vm_compilation_time.as_secs_f64()); + } + if !m.wasmtime_compilation_time.is_zero() { + COMPILATION_TIME + .with_label_values(&["wasmtime", shard_id]) + .observe(m.wasmtime_compilation_time.as_secs_f64()); + } + if m.compiled_contract_cache_lookups > 0 { + COMPILED_CONTRACT_CACHE_LOOKUPS_TOTAL + .with_label_values(&[caller_context, shard_id]) + .inc_by(m.compiled_contract_cache_lookups); + } + if m.compiled_contract_cache_hits > 0 { + COMPILED_CONTRACT_CACHE_HITS_TOTAL + .with_label_values(&[caller_context, shard_id]) + .inc_by(m.compiled_contract_cache_lookups); + } + + *m = Metrics::default(); + }); +} diff --git a/runtime/near-vm-runner/src/runner.rs b/runtime/near-vm-runner/src/runner.rs index bdfdff2aebd..c71013faad8 100644 --- a/runtime/near-vm-runner/src/runner.rs +++ b/runtime/near-vm-runner/src/runner.rs @@ -58,14 +58,12 @@ pub fn run( fees_config: &RuntimeFeesConfig, promise_results: &[PromiseResult], cache: Option<&dyn ContractRuntimeCache>, -) -> (VMResult, crate::Metrics) { +) -> VMResult { let span = tracing::Span::current(); let vm_kind = wasm_config.vm_kind; let runtime = vm_kind .runtime(wasm_config.clone()) .unwrap_or_else(|| panic!("the {vm_kind:?} runtime has not been enabled at compile time")); - crate::Metrics::reset(); - let outcome = runtime.run( account.code_hash(), code, @@ -78,12 +76,12 @@ pub fn run( ); let outcome = match outcome { Ok(o) => o, - e @ Err(_) => return (e, crate::Metrics::get()), + e @ Err(_) => return e, }; span.record("burnt_gas", outcome.burnt_gas); span.record("compute_usage", outcome.compute_usage); - (Ok(outcome), crate::Metrics::get()) + Ok(outcome) } pub trait VM { diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index 1a69abab4e6..a497e9ee77f 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -119,7 +119,10 @@ pub(crate) fn execute_function_call( if checked_feature!("stable", ChunkNodesCache, protocol_version) { runtime_ext.set_trie_cache_mode(TrieCacheMode::CachingChunk); } - let (result_from_cache, mut metrics) = near_vm_runner::run( + + near_vm_runner::reset_metrics(); + + let result_from_cache = near_vm_runner::run( account, None, &function_call.method_name, @@ -157,7 +160,7 @@ pub(crate) fn execute_function_call( if checked_feature!("stable", ChunkNodesCache, protocol_version) { runtime_ext.set_trie_cache_mode(TrieCacheMode::CachingChunk); } - let (r, mut metrics) = near_vm_runner::run( + let r = near_vm_runner::run( account, Some(&code), &function_call.method_name, @@ -168,27 +171,19 @@ pub(crate) fn execute_function_call( promise_results, apply_state.cache.as_deref(), ); - metrics.report( - &apply_state.shard_id.to_string(), - &apply_state - .apply_reason - .as_ref() - .map_or_else(|| String::from("unknown"), |r| r.to_string()), - ); r } - res => { - metrics.report( - &apply_state.shard_id.to_string(), - &apply_state - .apply_reason - .as_ref() - .map_or_else(|| String::from("unknown"), |r| r.to_string()), - ); - res - } + res => res, }; + near_vm_runner::report_metrics( + &apply_state.shard_id.to_string(), + &apply_state + .apply_reason + .as_ref() + .map_or_else(|| String::from("unknown"), |r| r.to_string()), + ); + if checked_feature!("stable", ChunkNodesCache, protocol_version) { runtime_ext.set_trie_cache_mode(TrieCacheMode::CachingShard); } From 292b613b2599292e32a74b4c16e4f7c8a9a51892 Mon Sep 17 00:00:00 2001 From: Tayfun Elmas Date: Wed, 1 May 2024 12:54:35 -0700 Subject: [PATCH 12/15] Set the metric correctly to consider memory and disk cache --- runtime/near-vm-runner/src/lib.rs | 2 +- runtime/near-vm-runner/src/near_vm_runner/runner.rs | 8 ++++++-- runtime/runtime/src/actions.rs | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/runtime/near-vm-runner/src/lib.rs b/runtime/near-vm-runner/src/lib.rs index 0fa8b064d7c..2f98014f300 100644 --- a/runtime/near-vm-runner/src/lib.rs +++ b/runtime/near-vm-runner/src/lib.rs @@ -34,7 +34,7 @@ pub use cache::{ NoContractRuntimeCache, }; pub use code::ContractCode; -pub use metrics::{reset_metrics, report_metrics}; +pub use metrics::{report_metrics, reset_metrics}; pub use profile::ProfileDataV3; pub use runner::{run, VM}; diff --git a/runtime/near-vm-runner/src/near_vm_runner/runner.rs b/runtime/near-vm-runner/src/near_vm_runner/runner.rs index 582e7e58e79..774bb11b2ca 100644 --- a/runtime/near-vm-runner/src/near_vm_runner/runner.rs +++ b/runtime/near-vm-runner/src/near_vm_runner/runner.rs @@ -225,6 +225,9 @@ impl NearVM { // (wasm code size, compilation result) type MemoryCacheType = (u64, Result); let to_any = |v: MemoryCacheType| -> Box { Box::new(v) }; + // To identify a cache hit from either in-memory and on-disk cache correctly, we first assume that we have a cache hit here, + // and then we set it to false when we fail to find any entry and decide to compile (by calling compile_and_cache below). + let mut is_cache_hit = true; let (wasm_bytes, artifact_result) = cache.memory_cache().try_lookup( code_hash, || match code { @@ -239,12 +242,10 @@ impl NearVM { let key = get_contract_cache_key(code_hash, &self.config); let cache_record = cache.get(&key).map_err(CacheError::ReadError)?; let Some(code) = cache_record else { - crate::metrics::record_compiled_contract_cache_lookup(false); return Err(VMRunnerError::CacheError(CacheError::ReadError( std::io::Error::from(std::io::ErrorKind::NotFound), ))); }; - crate::metrics::record_compiled_contract_cache_lookup(true); match &code.compiled { CompiledContract::CompileModuleError(err) => { @@ -281,6 +282,7 @@ impl NearVM { Some(code) => { let _span = tracing::debug_span!(target: "vm", "NearVM::build_from_source").entered(); + is_cache_hit = false; Ok(to_any(( code.code().len() as u64, match self.compile_and_cache(code, cache)? { @@ -306,6 +308,8 @@ impl NearVM { }, )?; + crate::metrics::record_compiled_contract_cache_lookup(is_cache_hit); + let mut memory = NearVmMemory::new( self.config.limit_config.initial_memory_pages, self.config.limit_config.max_memory_pages, diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index a497e9ee77f..b5fd33d62a4 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -121,7 +121,7 @@ pub(crate) fn execute_function_call( } near_vm_runner::reset_metrics(); - + let result_from_cache = near_vm_runner::run( account, None, From 565dd0c98bbccdcc75d9cf7f942d438a61c40ff0 Mon Sep 17 00:00:00 2001 From: Tayfun Elmas Date: Wed, 1 May 2024 13:00:29 -0700 Subject: [PATCH 13/15] Remove extra call to record_compiled_contract_cache_lookup --- runtime/near-vm-runner/src/near_vm_runner/runner.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/runtime/near-vm-runner/src/near_vm_runner/runner.rs b/runtime/near-vm-runner/src/near_vm_runner/runner.rs index 774bb11b2ca..70cec03d57e 100644 --- a/runtime/near-vm-runner/src/near_vm_runner/runner.rs +++ b/runtime/near-vm-runner/src/near_vm_runner/runner.rs @@ -299,7 +299,6 @@ impl NearVM { move |value| { let _span = tracing::debug_span!(target: "vm", "NearVM::load_from_mem_cache").entered(); - crate::metrics::record_compiled_contract_cache_lookup(true); let &(wasm_bytes, ref downcast) = value .downcast_ref::() .expect("downcast should always succeed"); From 7d6070603a4e2621858a6acabba1c3ad328f278a Mon Sep 17 00:00:00 2001 From: tayfunelmas Date: Mon, 6 May 2024 14:13:03 -0700 Subject: [PATCH 14/15] Add instrumentation to enable record_compiled_contract_cache_lookup for near_vm only. --- runtime/near-vm-runner/src/metrics.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/near-vm-runner/src/metrics.rs b/runtime/near-vm-runner/src/metrics.rs index 20a38f6e576..12af37c149b 100644 --- a/runtime/near-vm-runner/src/metrics.rs +++ b/runtime/near-vm-runner/src/metrics.rs @@ -64,6 +64,7 @@ pub(crate) fn compilation_duration(kind: near_parameters::vm::VMKind, duration: /// Updates metrics to record a compiled-contract cache lookup, /// where is_hit=true indicates that we found an entry in the cache. +#[cfg(feature = "near_vm")] pub(crate) fn record_compiled_contract_cache_lookup(is_hit: bool) { METRICS.with_borrow_mut(|m| { m.compiled_contract_cache_lookups += 1; From b129a73d95763c7a129a4cb28fe7638aa7b7647f Mon Sep 17 00:00:00 2001 From: tayfunelmas Date: Mon, 6 May 2024 14:30:25 -0700 Subject: [PATCH 15/15] Also add x86_64 annotation to skip MacOS tests (the codepath is not enabled for MacOS and we get function not used error). --- runtime/near-vm-runner/src/metrics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/near-vm-runner/src/metrics.rs b/runtime/near-vm-runner/src/metrics.rs index 12af37c149b..3ae812356d7 100644 --- a/runtime/near-vm-runner/src/metrics.rs +++ b/runtime/near-vm-runner/src/metrics.rs @@ -64,7 +64,7 @@ pub(crate) fn compilation_duration(kind: near_parameters::vm::VMKind, duration: /// Updates metrics to record a compiled-contract cache lookup, /// where is_hit=true indicates that we found an entry in the cache. -#[cfg(feature = "near_vm")] +#[cfg(all(feature = "near_vm", target_arch = "x86_64"))] pub(crate) fn record_compiled_contract_cache_lookup(is_hit: bool) { METRICS.with_borrow_mut(|m| { m.compiled_contract_cache_lookups += 1;