perf: Reuse CachedPrecompileMetrics across block executions (#16944)

This commit is contained in:
Brian Picciano
2025-06-19 15:52:05 +02:00
committed by GitHub
parent 6aa73f1480
commit 4be2226235
3 changed files with 36 additions and 10 deletions

View File

@@ -18,7 +18,7 @@ use error::{InsertBlockError, InsertBlockErrorKind, InsertBlockFatalError};
use instrumented_state::InstrumentedStateProvider;
use payload_processor::sparse_trie::StateRootComputeOutcome;
use persistence_state::CurrentPersistenceAction;
use precompile_cache::{CachedPrecompile, PrecompileCacheMap};
use precompile_cache::{CachedPrecompile, CachedPrecompileMetrics, PrecompileCacheMap};
use reth_chain_state::{
CanonicalInMemoryState, ExecutedBlock, ExecutedBlockWithTrieUpdates, ExecutedTrieUpdates,
MemoryOverlayStateProvider, NewCanonicalChain,
@@ -276,6 +276,9 @@ where
evm_config: C,
/// Precompile cache map.
precompile_cache_map: PrecompileCacheMap<SpecFor<C>>,
/// Metrics for precompile cache, saved between block executions so we don't re-allocate for
/// every block.
precompile_cache_metrics: CachedPrecompileMetrics,
}
impl<N, P: Debug, T: PayloadTypes + Debug, V: Debug, C> std::fmt::Debug
@@ -370,6 +373,7 @@ where
payload_processor,
evm_config,
precompile_cache_map,
precompile_cache_metrics: Default::default(),
}
}
@@ -2443,6 +2447,7 @@ where
precompile,
self.precompile_cache_map.cache_for_address(*address),
*self.evm_config.evm_env(block.header()).spec_id(),
Some(self.precompile_cache_metrics.clone()),
)
});
}

View File

@@ -275,6 +275,7 @@ where
precompile,
precompile_cache_map.cache_for_address(*address),
spec_id,
None, // CachedPrecompileMetrics
)
});
}

View File

@@ -123,7 +123,7 @@ where
/// The precompile.
precompile: DynPrecompile,
/// Cache metrics.
metrics: CachedPrecompileMetrics,
metrics: Option<CachedPrecompileMetrics>,
/// Spec id associated to the EVM from which this cached precompile was created.
spec_id: S,
}
@@ -133,30 +133,48 @@ where
S: Eq + Hash + std::fmt::Debug + Send + Sync + Clone + 'static,
{
/// `CachedPrecompile` constructor.
pub(crate) fn new(precompile: DynPrecompile, cache: PrecompileCache<S>, spec_id: S) -> Self {
Self { precompile, cache, spec_id, metrics: Default::default() }
pub(crate) const fn new(
precompile: DynPrecompile,
cache: PrecompileCache<S>,
spec_id: S,
metrics: Option<CachedPrecompileMetrics>,
) -> Self {
Self { precompile, cache, spec_id, metrics }
}
pub(crate) fn wrap(
precompile: DynPrecompile,
cache: PrecompileCache<S>,
spec_id: S,
metrics: Option<CachedPrecompileMetrics>,
) -> DynPrecompile {
let wrapped = Self::new(precompile, cache, spec_id);
let wrapped = Self::new(precompile, cache, spec_id, metrics);
move |data: &[u8], gas_limit: u64| -> PrecompileResult { wrapped.call(data, gas_limit) }
.into()
}
fn increment_by_one_precompile_cache_hits(&self) {
self.metrics.precompile_cache_hits.increment(1);
if let Some(metrics) = &self.metrics {
metrics.precompile_cache_hits.increment(1);
}
}
fn increment_by_one_precompile_cache_misses(&self) {
self.metrics.precompile_cache_misses.increment(1);
if let Some(metrics) = &self.metrics {
metrics.precompile_cache_misses.increment(1);
}
}
fn set_precompile_cache_size_metric(&self, to: f64) {
if let Some(metrics) = &self.metrics {
metrics.precompile_cache_size.set(to);
}
}
fn increment_by_one_precompile_errors(&self) {
self.metrics.precompile_errors.increment(1);
if let Some(metrics) = &self.metrics {
metrics.precompile_errors.increment(1);
}
}
}
@@ -180,7 +198,7 @@ where
Ok(output) => {
let key = CacheKey::new(self.spec_id.clone(), Bytes::copy_from_slice(data));
let size = self.cache.insert(key, CacheEntry(output.clone()));
self.metrics.precompile_cache_size.set(size as f64);
self.set_precompile_cache_size_metric(size as f64);
self.increment_by_one_precompile_cache_misses();
}
_ => {
@@ -241,7 +259,7 @@ mod tests {
.into();
let cache =
CachedPrecompile::new(dyn_precompile, PrecompileCache::default(), SpecId::PRAGUE);
CachedPrecompile::new(dyn_precompile, PrecompileCache::default(), SpecId::PRAGUE, None);
let output = PrecompileOutput {
gas_used: 50,
@@ -298,11 +316,13 @@ mod tests {
precompile1,
cache_map.cache_for_address(address1),
SpecId::PRAGUE,
None,
);
let wrapped_precompile2 = CachedPrecompile::wrap(
precompile2,
cache_map.cache_for_address(address2),
SpecId::PRAGUE,
None,
);
// first invocation of precompile1 (cache miss)