diff --git a/book/cli/reth/node.md b/book/cli/reth/node.md index 6d8a5d33a110..0d59c72d55ca 100644 --- a/book/cli/reth/node.md +++ b/book/cli/reth/node.md @@ -708,6 +708,11 @@ Engine: --engine.caching-and-prewarming Enable cross-block caching and parallel prewarming + --engine.cross-block-cache-size + Configure the size of cross-block cache in megabytes + + [default: 4096] + --engine.state-root-task-compare-updates Enable comparing trie updates from the state root task to the trie updates from the regular state root calculation diff --git a/crates/engine/tree/src/tree/cached_state.rs b/crates/engine/tree/src/tree/cached_state.rs index 1ab1ff4768f3..6e524e4ec8f1 100644 --- a/crates/engine/tree/src/tree/cached_state.rs +++ b/crates/engine/tree/src/tree/cached_state.rs @@ -377,29 +377,27 @@ impl ProviderCaches { /// A builder for [`ProviderCaches`]. #[derive(Debug)] pub(crate) struct ProviderCacheBuilder { - /// Code cache size - code_cache_size: u64, + /// Code cache entries + code_cache_entries: u64, - /// Storage cache size - storage_cache_size: u64, + /// Storage cache entries + storage_cache_entries: u64, - /// Account cache size - account_cache_size: u64, + /// Account cache entries + account_cache_entries: u64, } impl ProviderCacheBuilder { /// Build a [`ProviderCaches`] struct, so that provider caches can be easily cloned. - pub(crate) fn build_caches(self) -> ProviderCaches { - // TODO: the total cache size could be a CLI configuration parameter. - const TOTAL_CACHE_SIZE: u64 = 4 * 1024 * 1024 * 1024; // 4GB - let storage_cache_size = (TOTAL_CACHE_SIZE * 8888) / 10000; // 88.88% of total - let account_cache_size = (TOTAL_CACHE_SIZE * 556) / 10000; // 5.56% of total - let code_cache_size = (TOTAL_CACHE_SIZE * 556) / 10000; // 5.56% of total + pub(crate) fn build_caches(self, total_cache_size: u64) -> ProviderCaches { + let storage_cache_size = (total_cache_size * 8888) / 10000; // 88.88% of total + let account_cache_size = (total_cache_size * 556) / 10000; // 5.56% of total + let code_cache_size = (total_cache_size * 556) / 10000; // 5.56% of total const EXPIRY_TIME: Duration = Duration::from_secs(7200); // 2 hours const TIME_TO_IDLE: Duration = Duration::from_secs(3600); // 1 hour - let storage_cache = CacheBuilder::new(self.storage_cache_size) + let storage_cache = CacheBuilder::new(self.storage_cache_entries) .weigher(|_key: &Address, value: &AccountStorageCache| -> u32 { // values based on results from measure_storage_cache_overhead test let base_weight = 39_000; @@ -411,7 +409,7 @@ impl ProviderCacheBuilder { .time_to_idle(TIME_TO_IDLE) .build_with_hasher(DefaultHashBuilder::default()); - let account_cache = CacheBuilder::new(self.account_cache_size) + let account_cache = CacheBuilder::new(self.account_cache_entries) .weigher(|_key: &Address, value: &Option| -> u32 { match value { Some(account) => { @@ -437,7 +435,7 @@ impl ProviderCacheBuilder { .time_to_idle(TIME_TO_IDLE) .build_with_hasher(DefaultHashBuilder::default()); - let code_cache = CacheBuilder::new(self.code_cache_size) + let code_cache = CacheBuilder::new(self.code_cache_entries) .weigher(|_key: &B256, value: &Option| -> u32 { match value { Some(bytecode) => { @@ -466,9 +464,9 @@ impl Default for ProviderCacheBuilder { // Storage cache: up to 10M accounts but limited to 8GB // Account cache: up to 10M accounts but limited to 0.5GB Self { - code_cache_size: 10_000_000, - storage_cache_size: 10_000_000, - account_cache_size: 10_000_000, + code_cache_entries: 10_000_000, + storage_cache_entries: 10_000_000, + account_cache_entries: 10_000_000, } } } diff --git a/crates/engine/tree/src/tree/config.rs b/crates/engine/tree/src/tree/config.rs index 59e7b87dbb25..6bc4bb105ff4 100644 --- a/crates/engine/tree/src/tree/config.rs +++ b/crates/engine/tree/src/tree/config.rs @@ -20,6 +20,8 @@ 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; + /// The configuration of the engine tree. #[derive(Debug)] pub struct TreeConfig { @@ -48,6 +50,8 @@ pub struct TreeConfig { always_compare_trie_updates: bool, /// Whether to use cross-block caching and parallel prewarming use_caching_and_prewarming: bool, + /// Cross-block cache size in bytes. + cross_block_cache_size: u64, } impl Default for TreeConfig { @@ -61,6 +65,7 @@ impl Default for TreeConfig { use_state_root_task: false, always_compare_trie_updates: false, use_caching_and_prewarming: false, + cross_block_cache_size: DEFAULT_CROSS_BLOCK_CACHE_SIZE, } } } @@ -77,6 +82,7 @@ impl TreeConfig { use_state_root_task: bool, always_compare_trie_updates: bool, use_caching_and_prewarming: bool, + cross_block_cache_size: u64, ) -> Self { Self { persistence_threshold, @@ -87,6 +93,7 @@ impl TreeConfig { use_state_root_task, always_compare_trie_updates, use_caching_and_prewarming, + cross_block_cache_size, } } @@ -131,6 +138,11 @@ impl TreeConfig { self.always_compare_trie_updates } + /// Return the cross-block cache size. + pub const fn cross_block_cache_size(&self) -> u64 { + self.cross_block_cache_size + } + /// Setter for persistence threshold. pub const fn with_persistence_threshold(mut self, persistence_threshold: u64) -> Self { self.persistence_threshold = persistence_threshold; @@ -191,4 +203,10 @@ impl TreeConfig { self.always_compare_trie_updates = always_compare_trie_updates; self } + + /// Setter for cross block cache size. + pub const fn with_cross_block_cache_size(mut self, cross_block_cache_size: u64) -> Self { + self.cross_block_cache_size = cross_block_cache_size; + self + } } diff --git a/crates/engine/tree/src/tree/mod.rs b/crates/engine/tree/src/tree/mod.rs index 5971342f61db..d94ea8e5e5ff 100644 --- a/crates/engine/tree/src/tree/mod.rs +++ b/crates/engine/tree/src/tree/mod.rs @@ -2464,12 +2464,16 @@ where (None, None, None, Box::new(NoopHook::default()) as Box) }; - let (caches, cache_metrics) = - if let Some(cache) = self.take_latest_cache(block.parent_hash()) { - cache.split() - } else { - (ProviderCacheBuilder::default().build_caches(), CachedStateMetrics::zeroed()) - }; + let (caches, cache_metrics) = if let Some(cache) = + self.take_latest_cache(block.parent_hash()) + { + cache.split() + } else { + ( + ProviderCacheBuilder::default().build_caches(self.config.cross_block_cache_size()), + CachedStateMetrics::zeroed(), + ) + }; // Use cached state provider before executing, used in execution after prewarming threads // complete diff --git a/crates/node/builder/src/builder/mod.rs b/crates/node/builder/src/builder/mod.rs index 10d3f47f9c22..65b2790fb545 100644 --- a/crates/node/builder/src/builder/mod.rs +++ b/crates/node/builder/src/builder/mod.rs @@ -566,8 +566,9 @@ where .with_memory_block_buffer_target(builder.config.engine.memory_block_buffer_target) .with_state_root_task(builder.config.engine.state_root_task_enabled) .with_caching_and_prewarming(builder.config.engine.caching_and_prewarming_enabled) - .with_always_compare_trie_updates( - builder.config.engine.state_root_task_compare_updates, + .with_always_compare_trie_updates(builder.config.engine.state_root_task_compare_updates) + .with_cross_block_cache_size( + builder.config.engine.cross_block_cache_size * 1024 * 1024, ); let launcher = diff --git a/crates/node/core/src/args/engine.rs b/crates/node/core/src/args/engine.rs index 8de89b3a6fb8..8debea19975b 100644 --- a/crates/node/core/src/args/engine.rs +++ b/crates/node/core/src/args/engine.rs @@ -2,7 +2,10 @@ use clap::Args; -use crate::node_config::{DEFAULT_MEMORY_BLOCK_BUFFER_TARGET, DEFAULT_PERSISTENCE_THRESHOLD}; +use crate::node_config::{ + DEFAULT_CROSS_BLOCK_CACHE_SIZE_MB, DEFAULT_MEMORY_BLOCK_BUFFER_TARGET, + DEFAULT_PERSISTENCE_THRESHOLD, +}; /// Parameters for configuring the engine driver. #[derive(Debug, Clone, Args, PartialEq, Eq)] @@ -24,6 +27,10 @@ pub struct EngineArgs { #[arg(long = "engine.caching-and-prewarming")] pub caching_and_prewarming_enabled: bool, + /// Configure the size of cross-block cache in megabytes + #[arg(long = "engine.cross-block-cache-size", default_value_t = DEFAULT_CROSS_BLOCK_CACHE_SIZE_MB)] + pub cross_block_cache_size: u64, + /// Enable comparing trie updates from the state root task to the trie updates from the regular /// state root calculation. #[arg(long = "engine.state-root-task-compare-updates")] @@ -38,6 +45,7 @@ impl Default for EngineArgs { state_root_task_enabled: false, state_root_task_compare_updates: false, caching_and_prewarming_enabled: false, + cross_block_cache_size: DEFAULT_CROSS_BLOCK_CACHE_SIZE_MB, } } } diff --git a/crates/node/core/src/node_config.rs b/crates/node/core/src/node_config.rs index eb8aa2378b87..fef518c60785 100644 --- a/crates/node/core/src/node_config.rs +++ b/crates/node/core/src/node_config.rs @@ -37,6 +37,9 @@ pub const DEFAULT_PERSISTENCE_THRESHOLD: u64 = 2; /// How close to the canonical head we persist blocks. pub const DEFAULT_MEMORY_BLOCK_BUFFER_TARGET: u64 = 2; +/// Default size of cross-block cache in megabytes. +pub const DEFAULT_CROSS_BLOCK_CACHE_SIZE_MB: u64 = 4 * 1024; + /// This includes all necessary configuration to launch the node. /// The individual configuration options can be overwritten before launching the node. ///