combined fixed-cache execution cache and cached provider fixes

This commit is contained in:
Alexey Shekhirin
2026-01-05 21:56:15 +00:00
11 changed files with 453 additions and 585 deletions

113
Cargo.lock generated
View File

@@ -493,7 +493,7 @@ dependencies = [
"async-stream", "async-stream",
"async-trait", "async-trait",
"auto_impl", "auto_impl",
"dashmap 6.1.0", "dashmap",
"either", "either",
"futures", "futures",
"futures-utils-wasm", "futures-utils-wasm",
@@ -1779,7 +1779,7 @@ dependencies = [
"bytemuck", "bytemuck",
"cfg-if", "cfg-if",
"cow-utils", "cow-utils",
"dashmap 6.1.0", "dashmap",
"dynify", "dynify",
"fast-float2", "fast-float2",
"float16", "float16",
@@ -1973,12 +1973,6 @@ version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d"
[[package]]
name = "bytecount"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e"
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
version = "1.24.0" version = "1.24.0"
@@ -2058,19 +2052,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "cargo_metadata"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa"
dependencies = [
"camino",
"cargo-platform",
"semver 1.0.27",
"serde",
"serde_json",
]
[[package]] [[package]]
name = "cargo_metadata" name = "cargo_metadata"
version = "0.19.2" version = "0.19.2"
@@ -2920,19 +2901,6 @@ dependencies = [
"syn 2.0.113", "syn 2.0.113",
] ]
[[package]]
name = "dashmap"
version = "5.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
dependencies = [
"cfg-if",
"hashbrown 0.14.5",
"lock_api",
"once_cell",
"parking_lot_core",
]
[[package]] [[package]]
name = "dashmap" name = "dashmap"
version = "6.1.0" version = "6.1.0"
@@ -3491,15 +3459,6 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "error-chain"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
dependencies = [
"version_check",
]
[[package]] [[package]]
name = "ethereum_hashing" name = "ethereum_hashing"
version = "0.7.0" version = "0.7.0"
@@ -4078,6 +4037,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba59b6c98ba422a13f17ee1305c995cb5742bba7997f5b4d9af61b2ff0ffb213" checksum = "ba59b6c98ba422a13f17ee1305c995cb5742bba7997f5b4d9af61b2ff0ffb213"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"typeid",
] ]
[[package]] [[package]]
@@ -5932,21 +5892,6 @@ dependencies = [
"unicase", "unicase",
] ]
[[package]]
name = "mini-moka"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c325dfab65f261f386debee8b0969da215b3fa0037e74c8a1234db7ba986d803"
dependencies = [
"crossbeam-channel",
"crossbeam-utils",
"dashmap 5.5.3",
"skeptic",
"smallvec",
"tagptr",
"triomphe",
]
[[package]] [[package]]
name = "minimal-lexical" name = "minimal-lexical"
version = "0.2.1" version = "0.2.1"
@@ -7088,17 +7033,6 @@ dependencies = [
"syn 2.0.113", "syn 2.0.113",
] ]
[[package]]
name = "pulldown-cmark"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
dependencies = [
"bitflags 2.10.0",
"memchr",
"unicase",
]
[[package]] [[package]]
name = "quanta" name = "quanta"
version = "0.12.6" version = "0.12.6"
@@ -8366,13 +8300,13 @@ dependencies = [
"assert_matches", "assert_matches",
"codspeed-criterion-compat", "codspeed-criterion-compat",
"crossbeam-channel", "crossbeam-channel",
"dashmap 6.1.0", "dashmap",
"derive_more", "derive_more",
"eyre", "eyre",
"fixed-cache",
"futures", "futures",
"metrics", "metrics",
"metrics-util", "metrics-util",
"mini-moka",
"moka", "moka",
"parking_lot", "parking_lot",
"proptest", "proptest",
@@ -9010,7 +8944,7 @@ dependencies = [
"bitflags 2.10.0", "bitflags 2.10.0",
"byteorder", "byteorder",
"codspeed-criterion-compat", "codspeed-criterion-compat",
"dashmap 6.1.0", "dashmap",
"derive_more", "derive_more",
"parking_lot", "parking_lot",
"rand 0.9.2", "rand 0.9.2",
@@ -10109,7 +10043,7 @@ dependencies = [
"alloy-primitives", "alloy-primitives",
"alloy-rpc-types-engine", "alloy-rpc-types-engine",
"assert_matches", "assert_matches",
"dashmap 6.1.0", "dashmap",
"eyre", "eyre",
"itertools 0.14.0", "itertools 0.14.0",
"metrics", "metrics",
@@ -11124,7 +11058,7 @@ dependencies = [
"alloy-rlp", "alloy-rlp",
"codspeed-criterion-compat", "codspeed-criterion-compat",
"crossbeam-channel", "crossbeam-channel",
"dashmap 6.1.0", "dashmap",
"derive_more", "derive_more",
"itertools 0.14.0", "itertools 0.14.0",
"metrics", "metrics",
@@ -12270,21 +12204,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
[[package]]
name = "skeptic"
version = "0.13.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8"
dependencies = [
"bytecount",
"cargo_metadata 0.14.2",
"error-chain",
"glob",
"pulldown-cmark",
"tempfile",
"walkdir",
]
[[package]] [[package]]
name = "sketches-ddsketch" name = "sketches-ddsketch"
version = "0.3.0" version = "0.3.0"
@@ -12633,7 +12552,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d25f2f0ee315b130411a98570dd128dfe344bfaa0a28bf33d38f4a1fe85f39b" checksum = "4d25f2f0ee315b130411a98570dd128dfe344bfaa0a28bf33d38f4a1fe85f39b"
dependencies = [ dependencies = [
"bincode 2.0.1", "bincode 2.0.1",
"cargo_metadata 0.19.2", "cargo_metadata",
"serde", "serde",
] ]
@@ -13323,12 +13242,6 @@ dependencies = [
"rlp", "rlp",
] ]
[[package]]
name = "triomphe"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39"
[[package]] [[package]]
name = "try-lock" name = "try-lock"
version = "0.2.5" version = "0.2.5"
@@ -13354,6 +13267,12 @@ dependencies = [
"utf-8", "utf-8",
] ]
[[package]]
name = "typeid"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.19.0" version = "1.19.0"
@@ -13537,7 +13456,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b2bf58be11fc9414104c6d3a2e464163db5ef74b12296bda593cac37b6e4777" checksum = "6b2bf58be11fc9414104c6d3a2e464163db5ef74b12296bda593cac37b6e4777"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cargo_metadata 0.19.2", "cargo_metadata",
"derive_builder", "derive_builder",
"regex", "regex",
"rustversion", "rustversion",

View File

@@ -587,7 +587,7 @@ tracing-appender = "0.2"
url = { version = "2.3", default-features = false } url = { version = "2.3", default-features = false }
zstd = "0.13" zstd = "0.13"
byteorder = "1" byteorder = "1"
mini-moka = "0.10" fixed-cache = { version = "0.1.3", features = ["stats"] }
moka = "0.12" moka = "0.12"
tar-no-std = { version = "0.3.2", default-features = false } tar-no-std = { version = "0.3.2", default-features = false }
miniz_oxide = { version = "0.8.4", default-features = false } miniz_oxide = { version = "0.8.4", default-features = false }

View File

@@ -1467,8 +1467,7 @@ mod tests {
assert_eq!(parents[0].block().recovered_block().number, 2); assert_eq!(parents[0].block().recovered_block().number, 2);
assert_eq!(parents[1].block().recovered_block().number, 1); assert_eq!(parents[1].block().recovered_block().number, 1);
let parents: Vec<_> = chain[0].parent_state_chain().collect(); assert_eq!(chain[0].parent_state_chain().count(), 0);
assert_eq!(parents.len(), 0);
} }
#[test] #[test]

View File

@@ -45,7 +45,7 @@ pub const DEFAULT_PREWARM_MAX_CONCURRENCY: usize = 16;
const DEFAULT_BLOCK_BUFFER_LIMIT: u32 = EPOCH_SLOTS as u32 * 2; const DEFAULT_BLOCK_BUFFER_LIMIT: u32 = EPOCH_SLOTS as u32 * 2;
const DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH: u32 = 256; const DEFAULT_MAX_INVALID_HEADER_CACHE_LENGTH: u32 = 256;
const DEFAULT_MAX_EXECUTE_BLOCK_BATCH_SIZE: usize = 4; const DEFAULT_MAX_EXECUTE_BLOCK_BATCH_SIZE: usize = 4;
const DEFAULT_CROSS_BLOCK_CACHE_SIZE: u64 = 4 * 1024 * 1024 * 1024; const DEFAULT_CROSS_BLOCK_CACHE_SIZE: usize = 4 * 1024 * 1024 * 1024;
/// Determines if the host has enough parallelism to run the payload processor. /// Determines if the host has enough parallelism to run the payload processor.
/// ///
@@ -100,7 +100,7 @@ pub struct TreeConfig {
/// Whether to enable state provider metrics. /// Whether to enable state provider metrics.
state_provider_metrics: bool, state_provider_metrics: bool,
/// Cross-block cache size in bytes. /// Cross-block cache size in bytes.
cross_block_cache_size: u64, cross_block_cache_size: usize,
/// Whether the host has enough parallelism to run state root task. /// Whether the host has enough parallelism to run state root task.
has_enough_parallelism: bool, has_enough_parallelism: bool,
/// Whether multiproof task should chunk proof targets. /// Whether multiproof task should chunk proof targets.
@@ -182,7 +182,7 @@ impl TreeConfig {
disable_prewarming: bool, disable_prewarming: bool,
disable_parallel_sparse_trie: bool, disable_parallel_sparse_trie: bool,
state_provider_metrics: bool, state_provider_metrics: bool,
cross_block_cache_size: u64, cross_block_cache_size: usize,
has_enough_parallelism: bool, has_enough_parallelism: bool,
multiproof_chunking_enabled: bool, multiproof_chunking_enabled: bool,
multiproof_chunk_size: usize, multiproof_chunk_size: usize,
@@ -295,7 +295,7 @@ impl TreeConfig {
} }
/// Returns the cross-block cache size. /// Returns the cross-block cache size.
pub const fn cross_block_cache_size(&self) -> u64 { pub const fn cross_block_cache_size(&self) -> usize {
self.cross_block_cache_size self.cross_block_cache_size
} }
@@ -398,7 +398,7 @@ impl TreeConfig {
} }
/// Setter for cross block cache size. /// Setter for cross block cache size.
pub const fn with_cross_block_cache_size(mut self, cross_block_cache_size: u64) -> Self { pub const fn with_cross_block_cache_size(mut self, cross_block_cache_size: usize) -> Self {
self.cross_block_cache_size = cross_block_cache_size; self.cross_block_cache_size = cross_block_cache_size;
self self
} }

View File

@@ -52,7 +52,7 @@ revm-primitives.workspace = true
futures.workspace = true futures.workspace = true
thiserror.workspace = true thiserror.workspace = true
tokio = { workspace = true, features = ["rt", "rt-multi-thread", "sync", "macros"] } tokio = { workspace = true, features = ["rt", "rt-multi-thread", "sync", "macros"] }
mini-moka = { workspace = true, features = ["sync"] } fixed-cache.workspace = true
moka = { workspace = true, features = ["sync"] } moka = { workspace = true, features = ["sync"] }
smallvec.workspace = true smallvec.workspace = true

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@ use super::precompile_cache::PrecompileCacheMap;
use crate::tree::{ use crate::tree::{
cached_state::{ cached_state::{
CachedStateMetrics, CachedStateProvider, ExecutionCache as StateExecutionCache, CachedStateMetrics, CachedStateProvider, ExecutionCache as StateExecutionCache,
ExecutionCacheBuilder, SavedCache, FixedCacheMetrics, SavedCache,
}, },
payload_processor::{ payload_processor::{
prewarm::{PrewarmCacheTask, PrewarmContext, PrewarmMode, PrewarmTaskEvent}, prewarm::{PrewarmCacheTask, PrewarmContext, PrewarmMode, PrewarmTaskEvent},
@@ -116,7 +116,7 @@ where
/// Metrics for trie operations /// Metrics for trie operations
trie_metrics: MultiProofTaskMetrics, trie_metrics: MultiProofTaskMetrics,
/// Cross-block cache size in bytes. /// Cross-block cache size in bytes.
cross_block_cache_size: u64, cross_block_cache_size: usize,
/// Whether transactions should not be executed on prewarming task. /// Whether transactions should not be executed on prewarming task.
disable_transaction_prewarming: bool, disable_transaction_prewarming: bool,
/// Whether state cache should be disable /// Whether state cache should be disable
@@ -301,7 +301,7 @@ where
// Build a state provider for the multiproof task // Build a state provider for the multiproof task
let provider = provider_builder.build().expect("failed to build provider"); let provider = provider_builder.build().expect("failed to build provider");
let provider = if let Some(saved_cache) = saved_cache { let provider = if let Some(saved_cache) = saved_cache {
let (cache, metrics) = saved_cache.split(); let (cache, metrics, _) = saved_cache.split();
Box::new(CachedStateProvider::new(provider, cache, metrics)) Box::new(CachedStateProvider::new(provider, cache, metrics))
as Box<dyn StateProvider> as Box<dyn StateProvider>
} else { } else {
@@ -477,8 +477,13 @@ where
cache cache
} else { } else {
debug!("creating new execution cache on cache miss"); debug!("creating new execution cache on cache miss");
let cache = ExecutionCacheBuilder::default().build_caches(self.cross_block_cache_size); let cache = crate::tree::cached_state::ExecutionCache::new(self.cross_block_cache_size);
SavedCache::new(parent_hash, cache, CachedStateMetrics::zeroed()) SavedCache::new(
parent_hash,
cache,
CachedStateMetrics::zeroed(),
FixedCacheMetrics::zeroed(),
)
} }
} }
@@ -569,18 +574,22 @@ where
} }
// Take existing cache (if any) or create fresh caches // Take existing cache (if any) or create fresh caches
let (caches, cache_metrics) = match cached.take() { let (caches, cache_metrics, fixed_cache_metrics) = match cached.take() {
Some(existing) => { Some(existing) => existing.split(),
existing.split()
}
None => ( None => (
ExecutionCacheBuilder::default().build_caches(self.cross_block_cache_size), crate::tree::cached_state::ExecutionCache::new(self.cross_block_cache_size),
CachedStateMetrics::zeroed(), CachedStateMetrics::zeroed(),
FixedCacheMetrics::zeroed(),
), ),
}; };
// Insert the block's bundle state into cache // Insert the block's bundle state into cache
let new_cache = SavedCache::new(block_with_parent.block.hash, caches, cache_metrics); let new_cache = SavedCache::new(
block_with_parent.block.hash,
caches,
cache_metrics,
fixed_cache_metrics,
);
if new_cache.cache().insert_state(bundle_state).is_err() { if new_cache.cache().insert_state(bundle_state).is_err() {
*cached = None; *cached = None;
debug!(target: "engine::caching", "cleared execution cache on update error"); debug!(target: "engine::caching", "cleared execution cache on update error");
@@ -841,7 +850,7 @@ where
mod tests { mod tests {
use super::ExecutionCache; use super::ExecutionCache;
use crate::tree::{ use crate::tree::{
cached_state::{CachedStateMetrics, ExecutionCacheBuilder, SavedCache}, cached_state::{CachedStateMetrics, FixedCacheMetrics, SavedCache},
payload_processor::{ payload_processor::{
evm_state_to_hashed_post_state, executor::WorkloadExecutor, PayloadProcessor, evm_state_to_hashed_post_state, executor::WorkloadExecutor, PayloadProcessor,
}, },
@@ -870,8 +879,13 @@ mod tests {
use std::sync::Arc; use std::sync::Arc;
fn make_saved_cache(hash: B256) -> SavedCache { fn make_saved_cache(hash: B256) -> SavedCache {
let execution_cache = ExecutionCacheBuilder::default().build_caches(1_000); let execution_cache = crate::tree::cached_state::ExecutionCache::new(1_000);
SavedCache::new(hash, execution_cache, CachedStateMetrics::zeroed()) SavedCache::new(
hash,
execution_cache,
CachedStateMetrics::zeroed(),
FixedCacheMetrics::zeroed(),
)
} }
#[test] #[test]

View File

@@ -1499,7 +1499,7 @@ fn estimate_evm_state_targets(state: &EvmState) -> usize {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::tree::cached_state::{CachedStateProvider, ExecutionCacheBuilder}; use crate::tree::cached_state::CachedStateProvider;
use alloy_eip7928::{AccountChanges, BalanceChange}; use alloy_eip7928::{AccountChanges, BalanceChange};
use alloy_primitives::{map::B256Set, Address}; use alloy_primitives::{map::B256Set, Address};
use reth_provider::{ use reth_provider::{
@@ -1552,7 +1552,7 @@ mod tests {
{ {
let db_provider = factory.database_provider_ro().unwrap(); let db_provider = factory.database_provider_ro().unwrap();
let state_provider: StateProviderBox = Box::new(LatestStateProvider::new(db_provider)); let state_provider: StateProviderBox = Box::new(LatestStateProvider::new(db_provider));
let cache = ExecutionCacheBuilder::default().build_caches(1000); let cache = crate::tree::cached_state::ExecutionCache::new(1000);
CachedStateProvider::new(state_provider, cache, Default::default()) CachedStateProvider::new(state_provider, cache, Default::default())
} }

View File

@@ -272,8 +272,8 @@ where
execution_cache.update_with_guard(|cached| { execution_cache.update_with_guard(|cached| {
// consumes the `SavedCache` held by the prewarming task, which releases its usage // consumes the `SavedCache` held by the prewarming task, which releases its usage
// guard // guard
let (caches, cache_metrics) = saved_cache.split(); let (caches, cache_metrics, fixed_cache_metrics) = saved_cache.split();
let new_cache = SavedCache::new(hash, caches, cache_metrics); let new_cache = SavedCache::new(hash, caches, cache_metrics, fixed_cache_metrics);
// Insert state into cache while holding the lock // Insert state into cache while holding the lock
// Access the BundleState through the shared ExecutionOutcome // Access the BundleState through the shared ExecutionOutcome

View File

@@ -24,7 +24,7 @@ pub struct DefaultEngineValues {
prewarming_disabled: bool, prewarming_disabled: bool,
parallel_sparse_trie_disabled: bool, parallel_sparse_trie_disabled: bool,
state_provider_metrics: bool, state_provider_metrics: bool,
cross_block_cache_size: u64, cross_block_cache_size: usize,
state_root_task_compare_updates: bool, state_root_task_compare_updates: bool,
accept_execution_requests_hash: bool, accept_execution_requests_hash: bool,
multiproof_chunking_enabled: bool, multiproof_chunking_enabled: bool,
@@ -92,7 +92,7 @@ impl DefaultEngineValues {
} }
/// Set the default cross-block cache size in MB /// Set the default cross-block cache size in MB
pub const fn with_cross_block_cache_size(mut self, v: u64) -> Self { pub const fn with_cross_block_cache_size(mut self, v: usize) -> Self {
self.cross_block_cache_size = v; self.cross_block_cache_size = v;
self self
} }
@@ -246,7 +246,7 @@ pub struct EngineArgs {
/// Configure the size of cross-block cache in megabytes /// Configure the size of cross-block cache in megabytes
#[arg(long = "engine.cross-block-cache-size", default_value_t = DefaultEngineValues::get_global().cross_block_cache_size)] #[arg(long = "engine.cross-block-cache-size", default_value_t = DefaultEngineValues::get_global().cross_block_cache_size)]
pub cross_block_cache_size: u64, pub cross_block_cache_size: usize,
/// Enable comparing trie updates from the state root task to the trie updates from the regular /// Enable comparing trie updates from the state root task to the trie updates from the regular
/// state root calculation. /// state root calculation.

View File

@@ -38,7 +38,7 @@ pub use reth_engine_primitives::{
}; };
/// Default size of cross-block cache in megabytes. /// Default size of cross-block cache in megabytes.
pub const DEFAULT_CROSS_BLOCK_CACHE_SIZE_MB: u64 = 4 * 1024; pub const DEFAULT_CROSS_BLOCK_CACHE_SIZE_MB: usize = 4 * 1024;
/// This includes all necessary configuration to launch the node. /// This includes all necessary configuration to launch the node.
/// The individual configuration options can be overwritten before launching the node. /// The individual configuration options can be overwritten before launching the node.