diff --git a/Cargo.lock b/Cargo.lock index 2f21233de..f83bf97c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4418,6 +4418,7 @@ dependencies = [ "nom", "nonempty", "num-traits", + "once_cell", "paste", "phf", "phf_codegen", diff --git a/Cargo.toml b/Cargo.toml index 6daaf3fca..bd05c0587 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ rand = "=0.8.5" strum = "=0.25.0" thiserror = "=1.0.56" url = "=2.5.0" +once_cell = "1.19.0" # async tokio = { version = "=1.36.0", features = ["rt-multi-thread", "macros", "signal"] } diff --git a/src/eth/storage/rocks/rocks_permanent.rs b/src/eth/storage/rocks/rocks_permanent.rs index 04af3539e..c1ef812c4 100644 --- a/src/eth/storage/rocks/rocks_permanent.rs +++ b/src/eth/storage/rocks/rocks_permanent.rs @@ -1,10 +1,14 @@ use std::sync::atomic::AtomicU64; +use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; use std::sync::Arc; +use std::sync::Mutex; +use std::time::Instant; use anyhow::Context; use async_trait::async_trait; use futures::future::join_all; +use once_cell::sync::Lazy; use super::rocks_state::RocksStorageState; use crate::eth::primitives::Account; @@ -27,6 +31,12 @@ use crate::eth::storage::rocks::rocks_state::AccountInfo; use crate::eth::storage::PermanentStorage; use crate::eth::storage::StorageError; +/// used for multiple purposes, such as TPS counting and backup management +const TRANSACTION_LOOP_THRESHOLD: usize = 210_000; + +static TRANSACTIONS_COUNT: AtomicUsize = AtomicUsize::new(0); +static START_TIME: Lazy> = Lazy::new(|| Mutex::new(Instant::now())); + #[derive(Debug)] pub struct RocksPermanentStorage { state: RocksStorageState, @@ -184,6 +194,29 @@ impl PermanentStorage for RocksPermanentStorage { .context("failed to update state with execution changes")?, ); + // TPS Calculation and Printing + futures.push(tokio::task::spawn_blocking(move || { + let previous_count = TRANSACTIONS_COUNT.load(Ordering::Relaxed); + let current_count = TRANSACTIONS_COUNT.fetch_add(block.transactions.len(), Ordering::Relaxed); + let elapsed_time = START_TIME.lock().unwrap().elapsed().as_secs_f64(); + let multiple_to_print = TRANSACTION_LOOP_THRESHOLD / 8; + + // for every multiple of transactions, print the TPS + if previous_count % multiple_to_print > current_count % multiple_to_print { + let total_transactions = TRANSACTIONS_COUNT.load(Ordering::Relaxed); + let tps = total_transactions as f64 / elapsed_time; + //TODO replace this with metrics or do a cfg feature to enable/disable + println!("Transactions per second: {:.2} @ block {}", tps, block.number()); + } + + // for every multiple of TRANSACTION_LOOP_THRESHOLD transactions, reset the counter + if previous_count % TRANSACTION_LOOP_THRESHOLD > current_count % TRANSACTION_LOOP_THRESHOLD { + TRANSACTIONS_COUNT.store(0, Ordering::Relaxed); + let mut start_time = START_TIME.lock().unwrap(); + *start_time = Instant::now(); + } + })); + join_all(futures).await; Ok(()) }