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-trait",
"auto_impl",
"dashmap 6.1.0",
"dashmap",
"either",
"futures",
"futures-utils-wasm",
@@ -1779,7 +1779,7 @@ dependencies = [
"bytemuck",
"cfg-if",
"cow-utils",
"dashmap 6.1.0",
"dashmap",
"dynify",
"fast-float2",
"float16",
@@ -1973,12 +1973,6 @@ version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d"
[[package]]
name = "bytecount"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e"
[[package]]
name = "bytemuck"
version = "1.24.0"
@@ -2058,19 +2052,6 @@ dependencies = [
"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]]
name = "cargo_metadata"
version = "0.19.2"
@@ -2920,19 +2901,6 @@ dependencies = [
"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]]
name = "dashmap"
version = "6.1.0"
@@ -3491,15 +3459,6 @@ dependencies = [
"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]]
name = "ethereum_hashing"
version = "0.7.0"
@@ -4078,6 +4037,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba59b6c98ba422a13f17ee1305c995cb5742bba7997f5b4d9af61b2ff0ffb213"
dependencies = [
"equivalent",
"typeid",
]
[[package]]
@@ -5932,21 +5892,6 @@ dependencies = [
"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]]
name = "minimal-lexical"
version = "0.2.1"
@@ -7088,17 +7033,6 @@ dependencies = [
"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]]
name = "quanta"
version = "0.12.6"
@@ -8366,13 +8300,13 @@ dependencies = [
"assert_matches",
"codspeed-criterion-compat",
"crossbeam-channel",
"dashmap 6.1.0",
"dashmap",
"derive_more",
"eyre",
"fixed-cache",
"futures",
"metrics",
"metrics-util",
"mini-moka",
"moka",
"parking_lot",
"proptest",
@@ -9010,7 +8944,7 @@ dependencies = [
"bitflags 2.10.0",
"byteorder",
"codspeed-criterion-compat",
"dashmap 6.1.0",
"dashmap",
"derive_more",
"parking_lot",
"rand 0.9.2",
@@ -10109,7 +10043,7 @@ dependencies = [
"alloy-primitives",
"alloy-rpc-types-engine",
"assert_matches",
"dashmap 6.1.0",
"dashmap",
"eyre",
"itertools 0.14.0",
"metrics",
@@ -11124,7 +11058,7 @@ dependencies = [
"alloy-rlp",
"codspeed-criterion-compat",
"crossbeam-channel",
"dashmap 6.1.0",
"dashmap",
"derive_more",
"itertools 0.14.0",
"metrics",
@@ -12270,21 +12204,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "sketches-ddsketch"
version = "0.3.0"
@@ -12633,7 +12552,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d25f2f0ee315b130411a98570dd128dfe344bfaa0a28bf33d38f4a1fe85f39b"
dependencies = [
"bincode 2.0.1",
"cargo_metadata 0.19.2",
"cargo_metadata",
"serde",
]
@@ -13323,12 +13242,6 @@ dependencies = [
"rlp",
]
[[package]]
name = "triomphe"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39"
[[package]]
name = "try-lock"
version = "0.2.5"
@@ -13354,6 +13267,12 @@ dependencies = [
"utf-8",
]
[[package]]
name = "typeid"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
[[package]]
name = "typenum"
version = "1.19.0"
@@ -13537,7 +13456,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b2bf58be11fc9414104c6d3a2e464163db5ef74b12296bda593cac37b6e4777"
dependencies = [
"anyhow",
"cargo_metadata 0.19.2",
"cargo_metadata",
"derive_builder",
"regex",
"rustversion",

View File

@@ -587,7 +587,7 @@ tracing-appender = "0.2"
url = { version = "2.3", default-features = false }
zstd = "0.13"
byteorder = "1"
mini-moka = "0.10"
fixed-cache = { version = "0.1.3", features = ["stats"] }
moka = "0.12"
tar-no-std = { version = "0.3.2", 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[1].block().recovered_block().number, 1);
let parents: Vec<_> = chain[0].parent_state_chain().collect();
assert_eq!(parents.len(), 0);
assert_eq!(chain[0].parent_state_chain().count(), 0);
}
#[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_MAX_INVALID_HEADER_CACHE_LENGTH: u32 = 256;
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.
///
@@ -100,7 +100,7 @@ pub struct TreeConfig {
/// Whether to enable state provider metrics.
state_provider_metrics: bool,
/// 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.
has_enough_parallelism: bool,
/// Whether multiproof task should chunk proof targets.
@@ -182,7 +182,7 @@ impl TreeConfig {
disable_prewarming: bool,
disable_parallel_sparse_trie: bool,
state_provider_metrics: bool,
cross_block_cache_size: u64,
cross_block_cache_size: usize,
has_enough_parallelism: bool,
multiproof_chunking_enabled: bool,
multiproof_chunk_size: usize,
@@ -295,7 +295,7 @@ impl TreeConfig {
}
/// 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
}
@@ -398,7 +398,7 @@ impl TreeConfig {
}
/// 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
}

View File

@@ -52,7 +52,7 @@ revm-primitives.workspace = true
futures.workspace = true
thiserror.workspace = true
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"] }
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::{
cached_state::{
CachedStateMetrics, CachedStateProvider, ExecutionCache as StateExecutionCache,
ExecutionCacheBuilder, SavedCache,
FixedCacheMetrics, SavedCache,
},
payload_processor::{
prewarm::{PrewarmCacheTask, PrewarmContext, PrewarmMode, PrewarmTaskEvent},
@@ -116,7 +116,7 @@ where
/// Metrics for trie operations
trie_metrics: MultiProofTaskMetrics,
/// 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.
disable_transaction_prewarming: bool,
/// Whether state cache should be disable
@@ -301,7 +301,7 @@ where
// Build a state provider for the multiproof task
let provider = provider_builder.build().expect("failed to build provider");
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))
as Box<dyn StateProvider>
} else {
@@ -477,8 +477,13 @@ where
cache
} else {
debug!("creating new execution cache on cache miss");
let cache = ExecutionCacheBuilder::default().build_caches(self.cross_block_cache_size);
SavedCache::new(parent_hash, cache, CachedStateMetrics::zeroed())
let cache = crate::tree::cached_state::ExecutionCache::new(self.cross_block_cache_size);
SavedCache::new(
parent_hash,
cache,
CachedStateMetrics::zeroed(),
FixedCacheMetrics::zeroed(),
)
}
}
@@ -569,18 +574,22 @@ where
}
// Take existing cache (if any) or create fresh caches
let (caches, cache_metrics) = match cached.take() {
Some(existing) => {
existing.split()
}
let (caches, cache_metrics, fixed_cache_metrics) = match cached.take() {
Some(existing) => existing.split(),
None => (
ExecutionCacheBuilder::default().build_caches(self.cross_block_cache_size),
crate::tree::cached_state::ExecutionCache::new(self.cross_block_cache_size),
CachedStateMetrics::zeroed(),
FixedCacheMetrics::zeroed(),
),
};
// 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() {
*cached = None;
debug!(target: "engine::caching", "cleared execution cache on update error");
@@ -841,7 +850,7 @@ where
mod tests {
use super::ExecutionCache;
use crate::tree::{
cached_state::{CachedStateMetrics, ExecutionCacheBuilder, SavedCache},
cached_state::{CachedStateMetrics, FixedCacheMetrics, SavedCache},
payload_processor::{
evm_state_to_hashed_post_state, executor::WorkloadExecutor, PayloadProcessor,
},
@@ -870,8 +879,13 @@ mod tests {
use std::sync::Arc;
fn make_saved_cache(hash: B256) -> SavedCache {
let execution_cache = ExecutionCacheBuilder::default().build_caches(1_000);
SavedCache::new(hash, execution_cache, CachedStateMetrics::zeroed())
let execution_cache = crate::tree::cached_state::ExecutionCache::new(1_000);
SavedCache::new(
hash,
execution_cache,
CachedStateMetrics::zeroed(),
FixedCacheMetrics::zeroed(),
)
}
#[test]

View File

@@ -1499,7 +1499,7 @@ fn estimate_evm_state_targets(state: &EvmState) -> usize {
#[cfg(test)]
mod tests {
use super::*;
use crate::tree::cached_state::{CachedStateProvider, ExecutionCacheBuilder};
use crate::tree::cached_state::CachedStateProvider;
use alloy_eip7928::{AccountChanges, BalanceChange};
use alloy_primitives::{map::B256Set, Address};
use reth_provider::{
@@ -1552,7 +1552,7 @@ mod tests {
{
let db_provider = factory.database_provider_ro().unwrap();
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())
}

View File

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

View File

@@ -24,7 +24,7 @@ pub struct DefaultEngineValues {
prewarming_disabled: bool,
parallel_sparse_trie_disabled: bool,
state_provider_metrics: bool,
cross_block_cache_size: u64,
cross_block_cache_size: usize,
state_root_task_compare_updates: bool,
accept_execution_requests_hash: bool,
multiproof_chunking_enabled: bool,
@@ -92,7 +92,7 @@ impl DefaultEngineValues {
}
/// 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
}
@@ -246,7 +246,7 @@ pub struct EngineArgs {
/// 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)]
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
/// state root calculation.

View File

@@ -38,7 +38,7 @@ pub use reth_engine_primitives::{
};
/// 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.
/// The individual configuration options can be overwritten before launching the node.