From dc93d059f0b0321cd0b6fc063f136751ef8c0a0d Mon Sep 17 00:00:00 2001 From: Jan Ciolek Date: Fri, 26 Apr 2024 14:03:57 +0000 Subject: [PATCH] Add metrics to measure size of ChunkStateWitness fields Add metrics to measure the size of: * main_state_transition * new_transactions * new_transactions_validation_state * source_receipt_proofs --- chain/client/src/metrics.rs | 112 ++++++++++++++++++ .../stateless_validation/shadow_validate.rs | 11 +- .../state_witness_actions.rs | 7 +- 3 files changed, 118 insertions(+), 12 deletions(-) diff --git a/chain/client/src/metrics.rs b/chain/client/src/metrics.rs index 13ef59aecdf..b55a01d9dc4 100644 --- a/chain/client/src/metrics.rs +++ b/chain/client/src/metrics.rs @@ -4,6 +4,7 @@ use near_o11y::metrics::{ try_create_int_counter_vec, try_create_int_gauge, try_create_int_gauge_vec, Counter, Gauge, Histogram, HistogramVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, }; +use near_primitives::stateless_validation::ChunkStateWitness; use once_cell::sync::Lazy; pub(crate) static BLOCK_PRODUCED_TOTAL: Lazy = Lazy::new(|| { @@ -613,6 +614,117 @@ pub(crate) static CHUNK_STATE_WITNESS_DECODE_TIME: Lazy = Lazy::ne .unwrap() }); +pub(crate) static CHUNK_STATE_WITNESS_MAIN_STATE_TRANSISTION_SIZE: Lazy = Lazy::new( + || { + try_create_histogram_vec( + "near_chunk_state_witness_main_state_transition_size", + "Size of ChunkStateWitness::main_state_transition (storage proof needed to execute receipts)", + &["shard_id"], + Some(buckets_for_witness_field_size()), + ) + .unwrap() + }, +); + +pub(crate) static CHUNK_STATE_WITNESS_NEW_TRANSACTIONS_SIZE: Lazy = Lazy::new(|| { + try_create_histogram_vec( + "near_chunk_state_witness_new_transactions_size", + "Size of ChunkStateWitness::new_transactions (new proposed transactions)", + &["shard_id"], + Some(buckets_for_witness_field_size()), + ) + .unwrap() +}); + +pub(crate) static CHUNK_STATE_WITNESS_NEW_TRANSACTIONS_STATE_SIZE: Lazy = Lazy::new( + || { + try_create_histogram_vec( + "near_chunk_state_witness_new_transactions_state_size", + "Size of ChunkStateWitness::new_transactions_validation_state (storage proof to validate new proposed transactions)", + &["shard_id"], + Some(buckets_for_witness_field_size()), + ) + .unwrap() + }, +); + +pub(crate) static CHUNK_STATE_WITNESS_SOURCE_RECEIPT_PROOFS_SIZE: Lazy = + Lazy::new(|| { + try_create_histogram_vec( + "near_chunk_state_witness_source_receipt_proofs_size", + "Size of ChunkStateWitness::source_receipt_proofs (incoming receipts proofs)", + &["shard_id"], + Some(buckets_for_witness_field_size()), + ) + .unwrap() + }); + +pub(crate) fn record_witness_size_metrics( + decoded_size: usize, + encoded_size: usize, + witness: &ChunkStateWitness, +) { + if let Err(err) = record_witness_size_metrics_fallible(decoded_size, encoded_size, witness) { + tracing::warn!(target:"client", "Failed to record witness size metrics!, error: {}", err); + } +} + +fn record_witness_size_metrics_fallible( + decoded_size: usize, + encoded_size: usize, + witness: &ChunkStateWitness, +) -> Result<(), std::io::Error> { + let shard_id = witness.chunk_header.shard_id().to_string(); + CHUNK_STATE_WITNESS_RAW_SIZE + .with_label_values(&[shard_id.as_str()]) + .observe(decoded_size as f64); + CHUNK_STATE_WITNESS_TOTAL_SIZE + .with_label_values(&[&shard_id.as_str()]) + .observe(encoded_size as f64); + CHUNK_STATE_WITNESS_MAIN_STATE_TRANSISTION_SIZE + .with_label_values(&[shard_id.as_str()]) + .observe(borsh::to_vec(&witness.main_state_transition)?.len() as f64); + CHUNK_STATE_WITNESS_NEW_TRANSACTIONS_SIZE + .with_label_values(&[&shard_id.as_str()]) + .observe(borsh::to_vec(&witness.new_transactions)?.len() as f64); + CHUNK_STATE_WITNESS_NEW_TRANSACTIONS_STATE_SIZE + .with_label_values(&[&shard_id.as_str()]) + .observe(borsh::to_vec(&witness.new_transactions_validation_state)?.len() as f64); + CHUNK_STATE_WITNESS_SOURCE_RECEIPT_PROOFS_SIZE + .with_label_values(&[&shard_id.as_str()]) + .observe(borsh::to_vec(&witness.source_receipt_proofs)?.len() as f64); + Ok(()) +} + +/// Buckets from 0 to 10MB +/// Meant for measuring size of a single field inside ChunkSizeWitness. +fn buckets_for_witness_field_size() -> Vec { + vec![ + 10_000., + 20_000., + 50_000., + 100_000., + 200_000., + 300_000., + 500_000., + 750_000., + 1000_000., + 1500_000., + 2000_000., + 2500_000., + 3000_000., + 3500_000., + 4000_000., + 4500_000., + 5000_000., + 6000_000., + 7000_000., + 8000_000., + 9000_000., + 10_000_000., + ] +} + pub(crate) static ORPHAN_CHUNK_STATE_WITNESSES_TOTAL_COUNT: Lazy = Lazy::new(|| { try_create_int_counter_vec( "near_orphan_chunk_state_witness_total_count", diff --git a/chain/client/src/stateless_validation/shadow_validate.rs b/chain/client/src/stateless_validation/shadow_validate.rs index 5b214e9b3d5..7ebaf0269dc 100644 --- a/chain/client/src/stateless_validation/shadow_validate.rs +++ b/chain/client/src/stateless_validation/shadow_validate.rs @@ -89,12 +89,11 @@ impl Client { .start_timer(); let (encoded_witness, raw_witness_size) = EncodedChunkStateWitness::encode(&witness)?; encode_timer.observe_duration(); - metrics::CHUNK_STATE_WITNESS_TOTAL_SIZE - .with_label_values(&[shard_id_label.as_str()]) - .observe(encoded_witness.size_bytes() as f64); - metrics::CHUNK_STATE_WITNESS_RAW_SIZE - .with_label_values(&[shard_id_label.as_str()]) - .observe(raw_witness_size as f64); + metrics::record_witness_size_metrics( + raw_witness_size, + encoded_witness.size_bytes(), + &witness, + ); let decode_timer = metrics::CHUNK_STATE_WITNESS_DECODE_TIME .with_label_values(&[shard_id_label.as_str()]) .start_timer(); diff --git a/chain/client/src/stateless_validation/state_witness_actions.rs b/chain/client/src/stateless_validation/state_witness_actions.rs index 78b715e3d89..b17a386c037 100644 --- a/chain/client/src/stateless_validation/state_witness_actions.rs +++ b/chain/client/src/stateless_validation/state_witness_actions.rs @@ -243,11 +243,6 @@ fn compress_witness(witness: &ChunkStateWitness) -> Result