mirror of
https://github.com/0glabs/0g-storage-node.git
synced 2025-04-04 15:35:18 +00:00
add detailed metrics in slow operations
This commit is contained in:
parent
d0945e430a
commit
05381ab347
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -226,6 +226,7 @@ dependencies = [
|
|||||||
"itertools 0.13.0",
|
"itertools 0.13.0",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"lru 0.12.5",
|
"lru 0.12.5",
|
||||||
|
"metrics",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"serde",
|
"serde",
|
||||||
"tiny-keccak",
|
"tiny-keccak",
|
||||||
|
@ -13,5 +13,8 @@ serde = { version = "1.0.137", features = ["derive"] }
|
|||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
tracing = "0.1.36"
|
tracing = "0.1.36"
|
||||||
once_cell = "1.19.0"
|
once_cell = "1.19.0"
|
||||||
|
|
||||||
|
metrics = { workspace = true }
|
||||||
|
|
||||||
itertools = "0.13.0"
|
itertools = "0.13.0"
|
||||||
lru = "0.12.5"
|
lru = "0.12.5"
|
@ -1,4 +1,5 @@
|
|||||||
mod merkle_tree;
|
mod merkle_tree;
|
||||||
|
mod metrics;
|
||||||
mod node_manager;
|
mod node_manager;
|
||||||
mod proof;
|
mod proof;
|
||||||
mod sha3;
|
mod sha3;
|
||||||
@ -10,6 +11,7 @@ use std::collections::{BTreeMap, HashMap};
|
|||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::Instant;
|
||||||
use tracing::{trace, warn};
|
use tracing::{trace, warn};
|
||||||
|
|
||||||
use crate::merkle_tree::MerkleTreeWrite;
|
use crate::merkle_tree::MerkleTreeWrite;
|
||||||
@ -145,6 +147,7 @@ impl<E: HashElement, A: Algorithm<E>> AppendMerkleTree<E, A> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn append(&mut self, new_leaf: E) {
|
pub fn append(&mut self, new_leaf: E) {
|
||||||
|
let start_time = Instant::now();
|
||||||
if new_leaf == E::null() {
|
if new_leaf == E::null() {
|
||||||
// appending null is not allowed.
|
// appending null is not allowed.
|
||||||
return;
|
return;
|
||||||
@ -152,10 +155,13 @@ impl<E: HashElement, A: Algorithm<E>> AppendMerkleTree<E, A> {
|
|||||||
self.node_manager.start_transaction();
|
self.node_manager.start_transaction();
|
||||||
self.node_manager.push_node(0, new_leaf);
|
self.node_manager.push_node(0, new_leaf);
|
||||||
self.recompute_after_append_leaves(self.leaves() - 1);
|
self.recompute_after_append_leaves(self.leaves() - 1);
|
||||||
|
|
||||||
self.node_manager.commit();
|
self.node_manager.commit();
|
||||||
|
metrics::APPEND.update_since(start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append_list(&mut self, leaf_list: Vec<E>) {
|
pub fn append_list(&mut self, leaf_list: Vec<E>) {
|
||||||
|
let start_time = Instant::now();
|
||||||
if leaf_list.contains(&E::null()) {
|
if leaf_list.contains(&E::null()) {
|
||||||
// appending null is not allowed.
|
// appending null is not allowed.
|
||||||
return;
|
return;
|
||||||
@ -165,6 +171,7 @@ impl<E: HashElement, A: Algorithm<E>> AppendMerkleTree<E, A> {
|
|||||||
self.node_manager.append_nodes(0, &leaf_list);
|
self.node_manager.append_nodes(0, &leaf_list);
|
||||||
self.recompute_after_append_leaves(start_index);
|
self.recompute_after_append_leaves(start_index);
|
||||||
self.node_manager.commit();
|
self.node_manager.commit();
|
||||||
|
metrics::APPEND_LIST.update_since(start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Append a leaf list by providing their intermediate node hash.
|
/// Append a leaf list by providing their intermediate node hash.
|
||||||
@ -173,6 +180,7 @@ impl<E: HashElement, A: Algorithm<E>> AppendMerkleTree<E, A> {
|
|||||||
/// Other nodes in the subtree will be set to `null` nodes.
|
/// Other nodes in the subtree will be set to `null` nodes.
|
||||||
/// TODO: Optimize to avoid storing the `null` nodes?
|
/// TODO: Optimize to avoid storing the `null` nodes?
|
||||||
pub fn append_subtree(&mut self, subtree_depth: usize, subtree_root: E) -> Result<()> {
|
pub fn append_subtree(&mut self, subtree_depth: usize, subtree_root: E) -> Result<()> {
|
||||||
|
let start_time = Instant::now();
|
||||||
if subtree_root == E::null() {
|
if subtree_root == E::null() {
|
||||||
// appending null is not allowed.
|
// appending null is not allowed.
|
||||||
bail!("subtree_root is null");
|
bail!("subtree_root is null");
|
||||||
@ -182,10 +190,13 @@ impl<E: HashElement, A: Algorithm<E>> AppendMerkleTree<E, A> {
|
|||||||
self.append_subtree_inner(subtree_depth, subtree_root)?;
|
self.append_subtree_inner(subtree_depth, subtree_root)?;
|
||||||
self.recompute_after_append_subtree(start_index, subtree_depth - 1);
|
self.recompute_after_append_subtree(start_index, subtree_depth - 1);
|
||||||
self.node_manager.commit();
|
self.node_manager.commit();
|
||||||
|
metrics::APPEND_SUBTREE.update_since(start_time);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append_subtree_list(&mut self, subtree_list: Vec<(usize, E)>) -> Result<()> {
|
pub fn append_subtree_list(&mut self, subtree_list: Vec<(usize, E)>) -> Result<()> {
|
||||||
|
let start_time = Instant::now();
|
||||||
if subtree_list.iter().any(|(_, root)| root == &E::null()) {
|
if subtree_list.iter().any(|(_, root)| root == &E::null()) {
|
||||||
// appending null is not allowed.
|
// appending null is not allowed.
|
||||||
bail!("subtree_list contains null");
|
bail!("subtree_list contains null");
|
||||||
@ -197,12 +208,15 @@ impl<E: HashElement, A: Algorithm<E>> AppendMerkleTree<E, A> {
|
|||||||
self.recompute_after_append_subtree(start_index, subtree_depth - 1);
|
self.recompute_after_append_subtree(start_index, subtree_depth - 1);
|
||||||
}
|
}
|
||||||
self.node_manager.commit();
|
self.node_manager.commit();
|
||||||
|
metrics::APPEND_SUBTREE_LIST.update_since(start_time);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change the value of the last leaf and return the new merkle root.
|
/// Change the value of the last leaf and return the new merkle root.
|
||||||
/// This is needed if our merkle-tree in memory only keeps intermediate nodes instead of real leaves.
|
/// This is needed if our merkle-tree in memory only keeps intermediate nodes instead of real leaves.
|
||||||
pub fn update_last(&mut self, updated_leaf: E) {
|
pub fn update_last(&mut self, updated_leaf: E) {
|
||||||
|
let start_time = Instant::now();
|
||||||
if updated_leaf == E::null() {
|
if updated_leaf == E::null() {
|
||||||
// updating to null is not allowed.
|
// updating to null is not allowed.
|
||||||
return;
|
return;
|
||||||
@ -216,6 +230,7 @@ impl<E: HashElement, A: Algorithm<E>> AppendMerkleTree<E, A> {
|
|||||||
}
|
}
|
||||||
self.recompute_after_append_leaves(self.leaves() - 1);
|
self.recompute_after_append_leaves(self.leaves() - 1);
|
||||||
self.node_manager.commit();
|
self.node_manager.commit();
|
||||||
|
metrics::UPDATE_LAST.update_since(start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fill an unknown `null` leaf with its real value.
|
/// Fill an unknown `null` leaf with its real value.
|
||||||
|
11
common/append_merkle/src/metrics.rs
Normal file
11
common/append_merkle/src/metrics.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use metrics::{register_timer, Timer};
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
pub static ref APPEND: Arc<dyn Timer> = register_timer("append_merkle_append");
|
||||||
|
pub static ref APPEND_LIST: Arc<dyn Timer> = register_timer("append_merkle_append_list");
|
||||||
|
pub static ref APPEND_SUBTREE: Arc<dyn Timer> = register_timer("append_merkle_append_subtree");
|
||||||
|
pub static ref APPEND_SUBTREE_LIST: Arc<dyn Timer> = register_timer("append_merkle_append_subtree_list");
|
||||||
|
pub static ref UPDATE_LAST: Arc<dyn Timer> = register_timer("append_merkle_update_last");
|
||||||
|
}
|
@ -208,6 +208,7 @@ impl FlowWrite for FlowStore {
|
|||||||
/// Return the roots of completed chunks. The order is guaranteed to be increasing
|
/// Return the roots of completed chunks. The order is guaranteed to be increasing
|
||||||
/// by chunk index.
|
/// by chunk index.
|
||||||
fn append_entries(&self, data: ChunkArray) -> Result<Vec<(u64, DataRoot)>> {
|
fn append_entries(&self, data: ChunkArray) -> Result<Vec<(u64, DataRoot)>> {
|
||||||
|
let start_time = Instant::now();
|
||||||
let mut to_seal_set = self.seal_manager.to_seal_set.write();
|
let mut to_seal_set = self.seal_manager.to_seal_set.write();
|
||||||
trace!("append_entries: {} {}", data.start_index, data.data.len());
|
trace!("append_entries: {} {}", data.start_index, data.data.len());
|
||||||
if data.data.len() % BYTES_PER_SECTOR != 0 {
|
if data.data.len() % BYTES_PER_SECTOR != 0 {
|
||||||
@ -250,6 +251,8 @@ impl FlowWrite for FlowStore {
|
|||||||
|
|
||||||
batch_list.push((chunk_index, batch));
|
batch_list.push((chunk_index, batch));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
metrics::APPEND_ENTRIES.update_since(start_time);
|
||||||
self.data_db.put_entry_batch_list(batch_list)
|
self.data_db.put_entry_batch_list(batch_list)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,6 +362,7 @@ impl FlowDBStore {
|
|||||||
&self,
|
&self,
|
||||||
batch_list: Vec<(u64, EntryBatch)>,
|
batch_list: Vec<(u64, EntryBatch)>,
|
||||||
) -> Result<Vec<(u64, DataRoot)>> {
|
) -> Result<Vec<(u64, DataRoot)>> {
|
||||||
|
let start_time = Instant::now();
|
||||||
let mut completed_batches = Vec::new();
|
let mut completed_batches = Vec::new();
|
||||||
let mut tx = self.kvdb.transaction();
|
let mut tx = self.kvdb.transaction();
|
||||||
for (batch_index, batch) in batch_list {
|
for (batch_index, batch) in batch_list {
|
||||||
@ -373,6 +377,7 @@ impl FlowDBStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.kvdb.write(tx)?;
|
self.kvdb.write(tx)?;
|
||||||
|
metrics::PUT_ENTRY_BATCH_LIST.update_since(start_time);
|
||||||
Ok(completed_batches)
|
Ok(completed_batches)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
use super::tx_store::BlockHashAndSubmissionIndex;
|
|
||||||
use super::{FlowSeal, MineLoadChunk, SealAnswer, SealTask};
|
|
||||||
use crate::config::ShardConfig;
|
use crate::config::ShardConfig;
|
||||||
use crate::log_store::flow_store::{batch_iter_sharded, FlowConfig, FlowDBStore, FlowStore};
|
use crate::log_store::flow_store::{batch_iter_sharded, FlowConfig, FlowDBStore, FlowStore};
|
||||||
use crate::log_store::tx_store::TransactionStore;
|
use crate::log_store::tx_store::TransactionStore;
|
||||||
@ -1242,6 +1240,7 @@ pub fn sub_merkle_tree(leaf_data: &[u8]) -> Result<FileMerkleTree> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn data_to_merkle_leaves(leaf_data: &[u8]) -> Result<Vec<H256>> {
|
pub fn data_to_merkle_leaves(leaf_data: &[u8]) -> Result<Vec<H256>> {
|
||||||
|
let start_time = Instant::now();
|
||||||
if leaf_data.len() % ENTRY_SIZE != 0 {
|
if leaf_data.len() % ENTRY_SIZE != 0 {
|
||||||
bail!("merkle_tree: mismatched data size");
|
bail!("merkle_tree: mismatched data size");
|
||||||
}
|
}
|
||||||
@ -1257,6 +1256,8 @@ pub fn data_to_merkle_leaves(leaf_data: &[u8]) -> Result<Vec<H256>> {
|
|||||||
.map(Sha3Algorithm::leaf)
|
.map(Sha3Algorithm::leaf)
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
metrics::DATA_TO_MERKLE_LEAVES.update_since(start_time);
|
||||||
Ok(r)
|
Ok(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@ lazy_static::lazy_static! {
|
|||||||
pub static ref APPEND_SUBTREE_LIST: Arc<dyn Timer> =
|
pub static ref APPEND_SUBTREE_LIST: Arc<dyn Timer> =
|
||||||
register_timer("log_store_log_manager_append_subtree_list");
|
register_timer("log_store_log_manager_append_subtree_list");
|
||||||
|
|
||||||
|
pub static ref DATA_TO_MERKLE_LEAVES: Arc<dyn Timer> =
|
||||||
|
register_timer("log_store_log_manager_data_to_merkle_leaves");
|
||||||
|
|
||||||
pub static ref COPY_TX_AND_FINALIZE: Arc<dyn Timer> =
|
pub static ref COPY_TX_AND_FINALIZE: Arc<dyn Timer> =
|
||||||
register_timer("log_store_log_manager_copy_tx_and_finalize");
|
register_timer("log_store_log_manager_copy_tx_and_finalize");
|
||||||
|
|
||||||
@ -19,7 +22,12 @@ lazy_static::lazy_static! {
|
|||||||
pub static ref PUT_BATCH_ROOT_LIST: Arc<dyn Timer> = register_timer("log_store_flow_store_put_batch_root_list");
|
pub static ref PUT_BATCH_ROOT_LIST: Arc<dyn Timer> = register_timer("log_store_flow_store_put_batch_root_list");
|
||||||
|
|
||||||
pub static ref INSERT_SUBTREE_LIST: Arc<dyn Timer> =
|
pub static ref INSERT_SUBTREE_LIST: Arc<dyn Timer> =
|
||||||
register_timer("log_store_log_manager_insert_subtree_list");
|
register_timer("log_store_flow_store_insert_subtree_list");
|
||||||
|
|
||||||
pub static ref PUT_MPT_NODE: Arc<dyn Timer> = register_timer("log_store_log_manager_put_mpt_node");
|
pub static ref PUT_MPT_NODE: Arc<dyn Timer> = register_timer("log_store_flow_store_put_mpt_node");
|
||||||
|
|
||||||
|
pub static ref PUT_ENTRY_BATCH_LIST: Arc<dyn Timer> =
|
||||||
|
register_timer("log_store_flow_store_put_entry_batch_list");
|
||||||
|
|
||||||
|
pub static ref APPEND_ENTRIES: Arc<dyn Timer> = register_timer("log_store_flow_store_append_entries");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user