perf(db): pre-populate metric handles hashmap on env init (#6573)

This commit is contained in:
Seva Zhidkov
2024-02-13 01:59:52 +00:00
committed by GitHub
parent d4cf706ed2
commit 0e166f0f32
3 changed files with 27 additions and 19 deletions

1
Cargo.lock generated
View File

@ -5946,7 +5946,6 @@ dependencies = [
"assert_matches", "assert_matches",
"bytes", "bytes",
"criterion", "criterion",
"dashmap",
"derive_more", "derive_more",
"eyre", "eyre",
"iai", "iai",

View File

@ -38,7 +38,6 @@ parking_lot.workspace = true
derive_more.workspace = true derive_more.workspace = true
eyre.workspace = true eyre.workspace = true
paste = "1.0" paste = "1.0"
dashmap = "5.5.3"
rustc-hash = "1.1.0" rustc-hash = "1.1.0"
# arbitrary utils # arbitrary utils

View File

@ -1,14 +1,14 @@
use crate::Tables; use crate::Tables;
use dashmap::DashMap;
use metrics::{Gauge, Histogram}; use metrics::{Gauge, Histogram};
use reth_libmdbx::CommitLatency; use reth_libmdbx::CommitLatency;
use reth_metrics::{metrics::Counter, Metrics}; use reth_metrics::{metrics::Counter, Metrics};
use rustc_hash::FxHasher; use rustc_hash::FxHasher;
use std::{ use std::{
collections::HashMap,
hash::BuildHasherDefault, hash::BuildHasherDefault,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use strum::EnumCount; use strum::{EnumCount, EnumIter, IntoEnumIterator};
const LARGE_VALUE_THRESHOLD_BYTES: usize = 4096; const LARGE_VALUE_THRESHOLD_BYTES: usize = 4096;
@ -17,20 +17,33 @@ const LARGE_VALUE_THRESHOLD_BYTES: usize = 4096;
#[derive(Debug)] #[derive(Debug)]
pub struct DatabaseEnvMetrics { pub struct DatabaseEnvMetrics {
/// Caches OperationMetrics handles for each table and operation tuple. /// Caches OperationMetrics handles for each table and operation tuple.
operations: DashMap<(Tables, Operation), OperationMetrics, BuildHasherDefault<FxHasher>>, operations: HashMap<(Tables, Operation), OperationMetrics, BuildHasherDefault<FxHasher>>,
} }
impl DatabaseEnvMetrics { impl DatabaseEnvMetrics {
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
Self { // Pre-populate the map with all possible table and operation combinations
operations: DashMap::with_capacity_and_hasher( // to avoid runtime locks on the map when recording metrics.
Tables::COUNT * Operation::COUNT, let mut operations = HashMap::with_capacity_and_hasher(
BuildHasherDefault::<FxHasher>::default(), Tables::COUNT * Operation::COUNT,
), BuildHasherDefault::<FxHasher>::default(),
);
for table in Tables::ALL {
for operation in Operation::iter() {
operations.insert(
(*table, operation),
OperationMetrics::new_with_labels(&[
(Labels::Table.as_str(), table.name()),
(Labels::Operation.as_str(), operation.as_str()),
]),
);
}
} }
Self { operations }
} }
/// Record a metric for database operation executed in `f`. Panics if the table name is unknown. /// Record a metric for database operation executed in `f`.
/// Panics if a metric recorder is not found for the given table and operation.
pub(crate) fn record_operation<R>( pub(crate) fn record_operation<R>(
&self, &self,
table: Tables, table: Tables,
@ -38,13 +51,10 @@ impl DatabaseEnvMetrics {
value_size: Option<usize>, value_size: Option<usize>,
f: impl FnOnce() -> R, f: impl FnOnce() -> R,
) -> R { ) -> R {
let handle = self.operations.entry((table, operation)).or_insert_with(|| { self.operations
OperationMetrics::new_with_labels(&[ .get(&(table, operation))
(Labels::Table.as_str(), table.name()), .expect("operation & table metric handle not found")
(Labels::Operation.as_str(), operation.as_str()), .record(value_size, f)
])
});
handle.record(value_size, f)
} }
} }
@ -94,7 +104,7 @@ impl TransactionOutcome {
} }
/// Types of operations conducted on the database: get, put, delete, and various cursor operations. /// Types of operations conducted on the database: get, put, delete, and various cursor operations.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, EnumCount)] #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, EnumCount, EnumIter)]
pub(crate) enum Operation { pub(crate) enum Operation {
/// Database get operation. /// Database get operation.
Get, Get,