reth_trie/trie_cursor/
metrics.rs1use super::{TrieCursor, TrieStorageCursor};
2use crate::{BranchNodeCompact, Nibbles};
3use alloy_primitives::B256;
4use reth_primitives_traits::FastInstant as Instant;
5use reth_storage_errors::db::DatabaseError;
6use std::time::Duration;
7use tracing::trace_span;
8
9#[cfg(feature = "metrics")]
10use crate::TrieType;
11#[cfg(feature = "metrics")]
12use reth_metrics::metrics::{self, Histogram};
13
14#[cfg(feature = "metrics")]
18#[derive(Clone, Debug)]
19pub struct TrieCursorMetrics {
20 overall_duration: Histogram,
22 next_histogram: Histogram,
24 seek_histogram: Histogram,
26 seek_exact_histogram: Histogram,
28}
29
30#[cfg(feature = "metrics")]
31impl TrieCursorMetrics {
32 pub fn new(trie_type: TrieType) -> Self {
34 let trie_type_str = trie_type.as_str();
35
36 Self {
37 overall_duration: metrics::histogram!(
38 "trie.cursor.overall_duration",
39 "type" => trie_type_str
40 ),
41 next_histogram: metrics::histogram!(
42 "trie.cursor.operations",
43 "type" => trie_type_str,
44 "operation" => "next"
45 ),
46 seek_histogram: metrics::histogram!(
47 "trie.cursor.operations",
48 "type" => trie_type_str,
49 "operation" => "seek"
50 ),
51 seek_exact_histogram: metrics::histogram!(
52 "trie.cursor.operations",
53 "type" => trie_type_str,
54 "operation" => "seek_exact"
55 ),
56 }
57 }
58
59 pub fn record(&mut self, cache: &mut TrieCursorMetricsCache) {
64 self.next_histogram.record(cache.next_count as f64);
65 self.seek_histogram.record(cache.seek_count as f64);
66 self.seek_exact_histogram.record(cache.seek_exact_count as f64);
67 self.overall_duration.record(cache.total_duration.as_secs_f64());
68 cache.reset();
69 }
70}
71
72#[derive(Debug, Copy, Clone)]
74pub struct TrieCursorMetricsCache {
75 pub next_count: usize,
77 pub seek_count: usize,
79 pub seek_exact_count: usize,
81 pub total_duration: Duration,
83}
84
85impl Default for TrieCursorMetricsCache {
86 fn default() -> Self {
87 Self { next_count: 0, seek_count: 0, seek_exact_count: 0, total_duration: Duration::ZERO }
88 }
89}
90
91impl TrieCursorMetricsCache {
92 pub const fn reset(&mut self) {
94 self.next_count = 0;
95 self.seek_count = 0;
96 self.seek_exact_count = 0;
97 self.total_duration = Duration::ZERO;
98 }
99
100 pub fn extend(&mut self, other: &Self) {
104 self.next_count += other.next_count;
105 self.seek_count += other.seek_count;
106 self.seek_exact_count += other.seek_exact_count;
107 self.total_duration += other.total_duration;
108 }
109
110 pub fn record_span(&self, name: &'static str) {
112 let _span = trace_span!(
113 target: "trie::trie_cursor",
114 "Trie cursor metrics",
115 name,
116 next_count = self.next_count,
117 seek_count = self.seek_count,
118 seek_exact_count = self.seek_exact_count,
119 total_duration = self.total_duration.as_secs_f64(),
120 )
121 .entered();
122 }
123}
124
125#[derive(Debug)]
132pub struct InstrumentedTrieCursor<'metrics, C> {
133 cursor: C,
135 metrics: &'metrics mut TrieCursorMetricsCache,
137}
138
139impl<'metrics, C> InstrumentedTrieCursor<'metrics, C> {
140 pub const fn new(cursor: C, metrics: &'metrics mut TrieCursorMetricsCache) -> Self {
142 Self { cursor, metrics }
143 }
144}
145
146impl<'metrics, C: TrieCursor> TrieCursor for InstrumentedTrieCursor<'metrics, C> {
147 fn seek_exact(
148 &mut self,
149 key: Nibbles,
150 ) -> Result<Option<(Nibbles, BranchNodeCompact)>, DatabaseError> {
151 let start = Instant::now();
152 self.metrics.seek_exact_count += 1;
153 let result = self.cursor.seek_exact(key);
154 self.metrics.total_duration += start.elapsed();
155 result
156 }
157
158 fn seek(
159 &mut self,
160 key: Nibbles,
161 ) -> Result<Option<(Nibbles, BranchNodeCompact)>, DatabaseError> {
162 let start = Instant::now();
163 self.metrics.seek_count += 1;
164 let result = self.cursor.seek(key);
165 self.metrics.total_duration += start.elapsed();
166 result
167 }
168
169 fn next(&mut self) -> Result<Option<(Nibbles, BranchNodeCompact)>, DatabaseError> {
170 let start = Instant::now();
171 self.metrics.next_count += 1;
172 let result = self.cursor.next();
173 self.metrics.total_duration += start.elapsed();
174 result
175 }
176
177 fn current(&mut self) -> Result<Option<Nibbles>, DatabaseError> {
178 self.cursor.current()
179 }
180
181 fn reset(&mut self) {
182 self.cursor.reset()
183 }
184}
185
186impl<'metrics, C: TrieStorageCursor> TrieStorageCursor for InstrumentedTrieCursor<'metrics, C> {
187 fn set_hashed_address(&mut self, hashed_address: B256) {
188 self.cursor.set_hashed_address(hashed_address)
189 }
190}