feat(engine): add state root task timeout with sequential fallback (#22004)

Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Georgios Konstantopoulos
2026-02-11 15:45:45 -05:00
committed by GitHub
parent 0b7cd60668
commit 5bccdc4a5d
6 changed files with 182 additions and 6 deletions

View File

@@ -5,7 +5,7 @@ use reth_engine_primitives::{
TreeConfig, DEFAULT_MULTIPROOF_TASK_CHUNK_SIZE, DEFAULT_SPARSE_TRIE_MAX_STORAGE_TRIES,
DEFAULT_SPARSE_TRIE_PRUNE_DEPTH,
};
use std::sync::OnceLock;
use std::{sync::OnceLock, time::Duration};
use crate::node_config::{
DEFAULT_CROSS_BLOCK_CACHE_SIZE_MB, DEFAULT_MEMORY_BLOCK_BUFFER_TARGET,
@@ -43,6 +43,7 @@ pub struct DefaultEngineValues {
disable_trie_cache: bool,
sparse_trie_prune_depth: usize,
sparse_trie_max_storage_tries: usize,
state_root_task_timeout: Option<String>,
}
impl DefaultEngineValues {
@@ -196,6 +197,12 @@ impl DefaultEngineValues {
self.sparse_trie_max_storage_tries = v;
self
}
/// Set the default state root task timeout
pub fn with_state_root_task_timeout(mut self, v: Option<String>) -> Self {
self.state_root_task_timeout = v;
self
}
}
impl Default for DefaultEngineValues {
@@ -224,6 +231,7 @@ impl Default for DefaultEngineValues {
disable_trie_cache: false,
sparse_trie_prune_depth: DEFAULT_SPARSE_TRIE_PRUNE_DEPTH,
sparse_trie_max_storage_tries: DEFAULT_SPARSE_TRIE_MAX_STORAGE_TRIES,
state_root_task_timeout: Some("1s".to_string()),
}
}
}
@@ -363,6 +371,21 @@ pub struct EngineArgs {
/// Maximum number of storage tries to retain after sparse trie pruning.
#[arg(long = "engine.sparse-trie-max-storage-tries", default_value_t = DefaultEngineValues::get_global().sparse_trie_max_storage_tries)]
pub sparse_trie_max_storage_tries: usize,
/// Configure the timeout for the state root task before spawning a sequential fallback.
/// If the state root task takes longer than this, a sequential computation starts in
/// parallel and whichever finishes first is used.
///
/// --engine.state-root-task-timeout 1s
/// --engine.state-root-task-timeout 400ms
///
/// Set to 0s to disable.
#[arg(
long = "engine.state-root-task-timeout",
value_parser = humantime::parse_duration,
default_value = DefaultEngineValues::get_global().state_root_task_timeout.as_deref().unwrap_or("1s"),
)]
pub state_root_task_timeout: Option<Duration>,
}
#[allow(deprecated)]
@@ -392,6 +415,7 @@ impl Default for EngineArgs {
disable_trie_cache,
sparse_trie_prune_depth,
sparse_trie_max_storage_tries,
state_root_task_timeout,
} = DefaultEngineValues::get_global().clone();
Self {
persistence_threshold,
@@ -421,6 +445,9 @@ impl Default for EngineArgs {
disable_trie_cache,
sparse_trie_prune_depth,
sparse_trie_max_storage_tries,
state_root_task_timeout: state_root_task_timeout
.as_deref()
.map(|s| humantime::parse_duration(s).expect("valid default duration")),
}
}
}
@@ -453,6 +480,7 @@ impl EngineArgs {
.with_disable_trie_cache(self.disable_trie_cache)
.with_sparse_trie_prune_depth(self.sparse_trie_prune_depth)
.with_sparse_trie_max_storage_tries(self.sparse_trie_max_storage_tries)
.with_state_root_task_timeout(self.state_root_task_timeout.filter(|d| !d.is_zero()))
}
}
@@ -506,6 +534,7 @@ mod tests {
disable_trie_cache: true,
sparse_trie_prune_depth: 10,
sparse_trie_max_storage_tries: 100,
state_root_task_timeout: Some(Duration::from_secs(2)),
};
let parsed_args = CommandParser::<EngineArgs>::parse_from([
@@ -541,6 +570,8 @@ mod tests {
"10",
"--engine.sparse-trie-max-storage-tries",
"100",
"--engine.state-root-task-timeout",
"2s",
])
.args;