Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 4 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions book/cli/reth/node.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

[default: 4294967296]

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

Expand Down
34 changes: 16 additions & 18 deletions crates/engine/tree/src/tree/cached_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) => {
Expand All @@ -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) => {
Expand Down Expand Up @@ -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,
}
}
}
Expand Down
18 changes: 18 additions & 0 deletions crates/engine/tree/src/tree/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
cross_block_cache_size: u64,
}

impl Default for TreeConfig {
Expand All @@ -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,
}
}
}
Expand All @@ -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,
Expand All @@ -87,6 +93,7 @@ impl TreeConfig {
use_state_root_task,
always_compare_trie_updates,
use_caching_and_prewarming,
cross_block_cache_size,
}
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
}
}
16 changes: 10 additions & 6 deletions crates/engine/tree/src/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2464,12 +2464,16 @@ 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()) {
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
Expand Down
5 changes: 2 additions & 3 deletions crates/node/builder/src/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,9 +566,8 @@ 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);

let launcher =
EngineNodeLauncher::new(task_executor, builder.config.datadir(), engine_tree_config);
Expand Down
10 changes: 9 additions & 1 deletion crates/node/core/src/args/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, DEFAULT_MEMORY_BLOCK_BUFFER_TARGET,
DEFAULT_PERSISTENCE_THRESHOLD,
};

/// Parameters for configuring the engine driver.
#[derive(Debug, Clone, Args, PartialEq, Eq)]
Expand All @@ -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
#[arg(long = "engine.cross-block-cache-size", default_value_t = DEFAULT_CROSS_BLOCK_CACHE_SIZE)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should mention the unit,

for other caches we expect that the input is MB because handling bytes is a bit useless:

for example:

/// Set the maximum RPC request payload size for both HTTP and WS in megabytes.
#[arg(long = "rpc.max-request-size", alias = "rpc-max-request-size", default_value_t = RPC_DEFAULT_MAX_REQUEST_SIZE_MB.into())]
pub rpc_max_request_size: MaxU32,

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense, done here 0918a5b PTAL

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")]
Expand All @@ -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,
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions crates/node/core/src/node_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
pub const DEFAULT_CROSS_BLOCK_CACHE_SIZE: u64 = 4 * 1024 * 1024 * 1024;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is in bytes?

can we mention this?


/// This includes all necessary configuration to launch the node.
/// The individual configuration options can be overwritten before launching the node.
///
Expand Down
Loading