feat: add cross-block cache size cli arg (#14305)

This commit is contained in:
Federico Gimenez
2025-02-10 20:31:40 +01:00
committed by GitHub
parent 731b771fa2
commit d9e660bd56
7 changed files with 64 additions and 27 deletions

View File

@ -708,6 +708,11 @@ Engine:
--engine.caching-and-prewarming
Enable cross-block caching and parallel prewarming
--engine.cross-block-cache-size <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

View File

@ -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<Account>| -> 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<Bytecode>| -> 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,
}
}
}

View File

@ -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
}
}

View File

@ -2460,11 +2460,15 @@ where
(None, None, None, Box::new(NoopHook::default()) as Box<dyn OnStateHook>)
};
let (caches, cache_metrics) =
if let Some(cache) = self.take_latest_cache(block.parent_hash()) {
let (caches, cache_metrics) = if let Some(cache) =
self.take_latest_cache(block.parent_hash())
{
cache.split()
} else {
(ProviderCacheBuilder::default().build_caches(), CachedStateMetrics::zeroed())
(
ProviderCacheBuilder::default().build_caches(self.config.cross_block_cache_size()),
CachedStateMetrics::zeroed(),
)
};
// Use cached state provider before executing, used in execution after prewarming threads

View File

@ -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 =

View File

@ -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,
}
}
}

View File

@ -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.
///