diff --git a/crates/engine/primitives/src/config.rs b/crates/engine/primitives/src/config.rs index fbe79920d2..9e2c8210f0 100644 --- a/crates/engine/primitives/src/config.rs +++ b/crates/engine/primitives/src/config.rs @@ -6,6 +6,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 = 0; +/// Default maximum concurrency for on-demand proof tasks (blinded nodes) +pub const DEFAULT_MAX_PROOF_TASK_CONCURRENCY: u64 = 256; + /// Minimum number of workers we allow configuring explicitly. pub const MIN_WORKER_COUNT: usize = 32; @@ -99,6 +102,8 @@ pub struct TreeConfig { cross_block_cache_size: u64, /// Whether the host has enough parallelism to run state root task. has_enough_parallelism: bool, + /// Maximum number of concurrent proof tasks + max_proof_task_concurrency: u64, /// Whether multiproof task should chunk proof targets. multiproof_chunking_enabled: bool, /// Multiproof task chunk size for proof targets. @@ -148,6 +153,7 @@ impl Default for TreeConfig { state_provider_metrics: false, cross_block_cache_size: DEFAULT_CROSS_BLOCK_CACHE_SIZE, has_enough_parallelism: has_enough_parallelism(), + max_proof_task_concurrency: DEFAULT_MAX_PROOF_TASK_CONCURRENCY, multiproof_chunking_enabled: true, multiproof_chunk_size: DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE, reserved_cpu_cores: DEFAULT_RESERVED_CPU_CORES, @@ -178,6 +184,7 @@ impl TreeConfig { state_provider_metrics: bool, cross_block_cache_size: u64, has_enough_parallelism: bool, + max_proof_task_concurrency: u64, multiproof_chunking_enabled: bool, multiproof_chunk_size: usize, reserved_cpu_cores: usize, @@ -189,6 +196,7 @@ impl TreeConfig { storage_worker_count: usize, account_worker_count: usize, ) -> Self { + assert!(max_proof_task_concurrency > 0, "max_proof_task_concurrency must be at least 1"); Self { persistence_threshold, memory_block_buffer_target, @@ -202,6 +210,7 @@ impl TreeConfig { state_provider_metrics, cross_block_cache_size, has_enough_parallelism, + max_proof_task_concurrency, multiproof_chunking_enabled, multiproof_chunk_size, reserved_cpu_cores, @@ -240,6 +249,11 @@ impl TreeConfig { self.max_execute_block_batch_size } + /// Return the maximum proof task concurrency. + pub const fn max_proof_task_concurrency(&self) -> u64 { + self.max_proof_task_concurrency + } + /// Return whether the multiproof task chunking is enabled. pub const fn multiproof_chunking_enabled(&self) -> bool { self.multiproof_chunking_enabled @@ -409,6 +423,16 @@ impl TreeConfig { self } + /// Setter for maximum number of concurrent proof tasks. + pub const fn with_max_proof_task_concurrency( + mut self, + max_proof_task_concurrency: u64, + ) -> Self { + assert!(max_proof_task_concurrency > 0, "max_proof_task_concurrency must be at least 1"); + self.max_proof_task_concurrency = max_proof_task_concurrency; + self + } + /// Setter for whether multiproof task should chunk proof targets. pub const fn with_multiproof_chunking_enabled( mut self, diff --git a/crates/engine/tree/src/tree/payload_processor/mod.rs b/crates/engine/tree/src/tree/payload_processor/mod.rs index 74ef660402..e3090d6075 100644 --- a/crates/engine/tree/src/tree/payload_processor/mod.rs +++ b/crates/engine/tree/src/tree/payload_processor/mod.rs @@ -200,6 +200,7 @@ where ); let storage_worker_count = config.storage_worker_count(); let account_worker_count = config.account_worker_count(); + let max_proof_task_concurrency = config.max_proof_task_concurrency() as usize; let proof_handle = ProofWorkerHandle::new( self.executor.handle().clone(), consistent_view, @@ -208,15 +209,15 @@ where account_worker_count, ); - // Limit concurrent multiproof tasks to match the account worker pool size. - // Each multiproof task spawns a tokio task that queues to one account worker, - // which then fans out to storage workers as needed. + // We set it to half of the proof task concurrency, because often for each multiproof we + // spawn one Tokio task for the account proof, and one Tokio task for the storage proof. + let max_multi_proof_task_concurrency = max_proof_task_concurrency / 2; let multi_proof_task = MultiProofTask::new( state_root_config, self.executor.clone(), proof_handle.clone(), to_sparse_trie, - account_worker_count, + max_multi_proof_task_concurrency, config.multiproof_chunking_enabled().then_some(config.multiproof_chunk_size()), ); diff --git a/crates/node/core/src/args/engine.rs b/crates/node/core/src/args/engine.rs index 8a77eaa780..6b678b5789 100644 --- a/crates/node/core/src/args/engine.rs +++ b/crates/node/core/src/args/engine.rs @@ -4,8 +4,8 @@ use clap::Args; use reth_engine_primitives::{TreeConfig, DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE}; use crate::node_config::{ - DEFAULT_CROSS_BLOCK_CACHE_SIZE_MB, DEFAULT_MEMORY_BLOCK_BUFFER_TARGET, - DEFAULT_PERSISTENCE_THRESHOLD, DEFAULT_RESERVED_CPU_CORES, + DEFAULT_CROSS_BLOCK_CACHE_SIZE_MB, DEFAULT_MAX_PROOF_TASK_CONCURRENCY, + DEFAULT_MEMORY_BLOCK_BUFFER_TARGET, DEFAULT_PERSISTENCE_THRESHOLD, DEFAULT_RESERVED_CPU_CORES, }; /// Parameters for configuring the engine driver. @@ -63,6 +63,10 @@ pub struct EngineArgs { #[arg(long = "engine.accept-execution-requests-hash")] pub accept_execution_requests_hash: bool, + /// Configure the maximum number of concurrent proof tasks + #[arg(long = "engine.max-proof-task-concurrency", default_value_t = DEFAULT_MAX_PROOF_TASK_CONCURRENCY)] + pub max_proof_task_concurrency: u64, + /// Whether multiproof task should chunk proof targets. #[arg(long = "engine.multiproof-chunking", default_value = "true")] pub multiproof_chunking_enabled: bool, @@ -131,6 +135,7 @@ impl Default for EngineArgs { state_provider_metrics: false, cross_block_cache_size: DEFAULT_CROSS_BLOCK_CACHE_SIZE_MB, accept_execution_requests_hash: false, + max_proof_task_concurrency: DEFAULT_MAX_PROOF_TASK_CONCURRENCY, multiproof_chunking_enabled: true, multiproof_chunk_size: DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE, reserved_cpu_cores: DEFAULT_RESERVED_CPU_CORES, @@ -157,6 +162,7 @@ impl EngineArgs { .with_state_provider_metrics(self.state_provider_metrics) .with_always_compare_trie_updates(self.state_root_task_compare_updates) .with_cross_block_cache_size(self.cross_block_cache_size * 1024 * 1024) + .with_max_proof_task_concurrency(self.max_proof_task_concurrency) .with_multiproof_chunking_enabled(self.multiproof_chunking_enabled) .with_multiproof_chunk_size(self.multiproof_chunk_size) .with_reserved_cpu_cores(self.reserved_cpu_cores) diff --git a/crates/node/core/src/node_config.rs b/crates/node/core/src/node_config.rs index 19b51bce03..94dbecb649 100644 --- a/crates/node/core/src/node_config.rs +++ b/crates/node/core/src/node_config.rs @@ -34,7 +34,8 @@ use tracing::*; use crate::args::{EraArgs, MetricArgs}; pub use reth_engine_primitives::{ - DEFAULT_MEMORY_BLOCK_BUFFER_TARGET, DEFAULT_PERSISTENCE_THRESHOLD, DEFAULT_RESERVED_CPU_CORES, + DEFAULT_MAX_PROOF_TASK_CONCURRENCY, DEFAULT_MEMORY_BLOCK_BUFFER_TARGET, + DEFAULT_PERSISTENCE_THRESHOLD, DEFAULT_RESERVED_CPU_CORES, }; /// Default size of cross-block cache in megabytes. diff --git a/docs/cli/help.rs b/docs/cli/help.rs index 0474d00e72..05e61eef74 100755 --- a/docs/cli/help.rs +++ b/docs/cli/help.rs @@ -269,6 +269,11 @@ fn preprocess_help(s: &str) -> Cow<'_, str> { r"(rpc.max-tracing-requests \n.*\n.*\n.*\n.*\n.*)\[default: \d+\]", r"$1[default: ]", ), + // Handle engine.max-proof-task-concurrency dynamic default + ( + r"(engine\.max-proof-task-concurrency.*)\[default: \d+\]", + r"$1[default: ]", + ), // Handle engine.reserved-cpu-cores dynamic default ( r"(engine\.reserved-cpu-cores.*)\[default: \d+\]", diff --git a/docs/vocs/docs/pages/cli/reth/node.mdx b/docs/vocs/docs/pages/cli/reth/node.mdx index ef3274001d..9d6a162798 100644 --- a/docs/vocs/docs/pages/cli/reth/node.mdx +++ b/docs/vocs/docs/pages/cli/reth/node.mdx @@ -835,6 +835,11 @@ Engine: --engine.accept-execution-requests-hash Enables accepting requests hash instead of an array of requests in `engine_newPayloadV4` + --engine.max-proof-task-concurrency + Configure the maximum number of concurrent proof tasks + + [default: 256] + --engine.multiproof-chunking Whether multiproof task should chunk proof targets