Skip to content

Commit c81d23c

Browse files
committed
Introduce ThreadBlockBuildingContext, removing old CachedReads.
The idea behind ThreadBlockBuildingContext is to have a place that is owned by a particular thread (for example, max profit ordering builder) that can be used as a scratchpad for caching without doing global caching shared between all threads. Currently we have only one place for caches BlockBuildingContext. It is global and shared between all builders, top of block simulation, and finalization thread. This approach solves many problems with caching. For example, we use it for eth-sparse-mpt root hash caching. But sometimes we would like to have a cache that is local to the current thread to avoid the overhead of mutex and multiple threads. I've seen the need for caches like this multiple times. This commit adds support for local caches like this. The first thing that is moved to this new setup of 2 caches is cached reads. We had a lot of trouble with passing CachedReads struct around and it introduced itself into traits where it does not belong such as BlockBuildingHelper or backtesting code. Here we move CachedReads to this uniform setup and it simplifies cached reads state handling.
1 parent b2a7013 commit c81d23c

26 files changed

+585
-343
lines changed

Diff for: crates/rbuilder/src/backtest/build_block/backtest_build_block.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,13 @@ where
117117
builder_name: builder_name.clone(),
118118
sim_orders: &sim_orders,
119119
provider: provider_factory.clone(),
120-
cached_reads: None,
121120
};
122121
let build_res = config.build_backtest_block(builder_name, input);
123122
if let Err(err) = &build_res {
124123
println!("Error building block: {:?}", err);
125124
return None;
126125
}
127-
let (block, _) = build_res.ok()?;
126+
let block = build_res.ok()?;
128127
println!(
129128
"Built block {} with builder: {:?}",
130129
ctx.block(),

Diff for: crates/rbuilder/src/backtest/execute.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use crate::{
1212
};
1313
use alloy_eips::BlockNumHash;
1414
use alloy_primitives::{Address, U256};
15-
use reth::revm::cached::CachedReads;
1615
use reth_chainspec::ChainSpec;
1716
use serde::{Deserialize, Serialize};
1817
use std::{cell::RefCell, rc::Rc, sync::Arc};
@@ -180,19 +179,15 @@ where
180179
let simulated_total_gas = sim_orders.iter().map(|o| o.sim_value.gas_used).sum();
181180
let mut builder_outputs = Vec::new();
182181

183-
let mut cached_reads = Some(CachedReads::default());
184182
for building_algorithm_name in builders_names {
185183
let input = BacktestSimulateBlockInput {
186184
ctx: ctx.clone(),
187185
builder_name: building_algorithm_name.clone(),
188186
sim_orders: &sim_orders,
189187
provider: provider.clone(),
190-
cached_reads,
191188
};
192189

193-
let (block, new_cached_reads) =
194-
config.build_backtest_block(&building_algorithm_name, input)?;
195-
cached_reads = Some(new_cached_reads);
190+
let block = config.build_backtest_block(&building_algorithm_name, input)?;
196191
builder_outputs.push(BacktestBuilderOutput {
197192
orders_included: block.trace.included_orders.len(),
198193
builder_name: building_algorithm_name,

Diff for: crates/rbuilder/src/backtest/restore_landed_orders/resim_landed_block.rs

+17-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
building::{
33
evm_inspector::SlotKey, tracers::AccumulatorSimulationTracer, BlockBuildingContext,
4-
BlockState, PartialBlock, PartialBlockFork,
4+
BlockState, PartialBlock, PartialBlockFork, ThreadBlockBuildingContext,
55
},
66
provider::StateProviderFactory,
77
utils::{extract_onchain_block_txs, find_suggested_fee_recipient, signed_uint_delta},
@@ -55,27 +55,38 @@ where
5555
Arc::from(provider.root_hasher(parent_num_hash)?),
5656
);
5757

58+
let mut local_ctx = ThreadBlockBuildingContext::default();
59+
5860
let state_provider = provider.history_by_block_hash(ctx.attributes.parent)?;
5961
let mut partial_block = PartialBlock::new(true);
6062
let mut state = BlockState::new(state_provider);
6163

6264
partial_block
63-
.pre_block_call(&ctx, &mut state)
65+
.pre_block_call(&ctx, &mut local_ctx, &mut state)
6466
.with_context(|| "Failed to pre_block_call")?;
6567

6668
let mut cumulative_gas_used = 0;
6769
let mut cumulative_blob_gas_used = 0;
6870
let mut written_slots: HashMap<SlotKey, Vec<B256>> = HashMap::default();
6971

7072
for (idx, tx) in txs.into_iter().enumerate() {
71-
let coinbase_balance_before = state.balance(coinbase)?;
73+
let coinbase_balance_before = state.balance(
74+
coinbase,
75+
&ctx.shared_cached_reads,
76+
&mut local_ctx.cached_reads,
77+
)?;
7278
let mut accumulator_tracer = AccumulatorSimulationTracer::default();
7379
let result = {
74-
let mut fork = PartialBlockFork::new(&mut state).with_tracer(&mut accumulator_tracer);
75-
fork.commit_tx(&tx, &ctx, cumulative_gas_used, 0, cumulative_blob_gas_used)?
80+
let mut fork = PartialBlockFork::new(&mut state, &ctx, &mut local_ctx)
81+
.with_tracer(&mut accumulator_tracer);
82+
fork.commit_tx(&tx, cumulative_gas_used, 0, cumulative_blob_gas_used)?
7683
.with_context(|| format!("Failed to commit tx: {} {:?}", idx, tx.hash()))?
7784
};
78-
let coinbase_balance_after = state.balance(coinbase)?;
85+
let coinbase_balance_after = state.balance(
86+
coinbase,
87+
&ctx.shared_cached_reads,
88+
&mut local_ctx.cached_reads,
89+
)?;
7990
let coinbase_profit = signed_uint_delta(coinbase_balance_after, coinbase_balance_before);
8091

8192
cumulative_gas_used += result.gas_used;

Diff for: crates/rbuilder/src/bin/debug-bench-machine.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ use clap::Parser;
66
use eyre::Context;
77
use itertools::Itertools;
88
use rbuilder::{
9-
building::{BlockBuildingContext, BlockState, PartialBlock, PartialBlockFork},
9+
building::{
10+
BlockBuildingContext, BlockState, PartialBlock, PartialBlockFork,
11+
ThreadBlockBuildingContext,
12+
},
1013
live_builder::{base_config::load_config_toml_and_env, cli::LiveBuilderConfig, config::Config},
1114
provider::StateProviderFactory,
1215
utils::{extract_onchain_block_txs, find_suggested_fee_recipient, http_provider},
1316
};
14-
use reth::revm::cached::CachedReads;
1517
use reth_provider::StateProvider;
1618
use std::{path::PathBuf, sync::Arc, time::Instant};
1719
use tracing::{debug, info};
@@ -82,25 +84,24 @@ async fn main() -> eyre::Result<()> {
8284

8385
let mut build_times_ms = Vec::new();
8486
let mut finalize_time_ms = Vec::new();
85-
let mut cached_reads = Some(CachedReads::default());
8687
for _ in 0..cli.iters {
8788
let ctx = ctx.clone();
8889
let txs = txs.clone();
8990
let state_provider = state_provider.clone();
90-
let (new_cached_reads, build_time, finalize_time) =
91+
let (build_time, finalize_time) =
9192
tokio::task::spawn_blocking(move || -> eyre::Result<_> {
9293
let partial_block = PartialBlock::new(true);
93-
let mut state = BlockState::new_arc(state_provider)
94-
.with_cached_reads(cached_reads.unwrap_or_default());
94+
let mut state = BlockState::new_arc(state_provider);
95+
let mut local_ctx = ThreadBlockBuildingContext::default();
9596

9697
let build_time = Instant::now();
9798

9899
let mut cumulative_gas_used = 0;
99100
let mut cumulative_blob_gas_used = 0;
100101
for (idx, tx) in txs.into_iter().enumerate() {
101102
let result = {
102-
let mut fork = PartialBlockFork::new(&mut state);
103-
fork.commit_tx(&tx, &ctx, cumulative_gas_used, 0, cumulative_blob_gas_used)?
103+
let mut fork = PartialBlockFork::new(&mut state, &ctx, &mut local_ctx);
104+
fork.commit_tx(&tx, cumulative_gas_used, 0, cumulative_blob_gas_used)?
104105
.with_context(|| {
105106
format!("Failed to commit tx: {} {:?}", idx, tx.hash())
106107
})?
@@ -112,19 +113,18 @@ async fn main() -> eyre::Result<()> {
112113
let build_time = build_time.elapsed();
113114

114115
let finalize_time = Instant::now();
115-
let finalized_block = partial_block.finalize(&mut state, &ctx)?;
116+
let finalized_block = partial_block.finalize(&mut state, &ctx, &mut local_ctx)?;
116117
let finalize_time = finalize_time.elapsed();
117118

118119
debug!(
119120
"Calculated root hash: {:?}",
120121
finalized_block.sealed_block.state_root
121122
);
122123

123-
Ok((finalized_block.cached_reads, build_time, finalize_time))
124+
Ok((build_time, finalize_time))
124125
})
125126
.await??;
126127

127-
cached_reads = Some(new_cached_reads);
128128
build_times_ms.push(build_time.as_millis());
129129
finalize_time_ms.push(finalize_time.as_millis());
130130
}

Diff for: crates/rbuilder/src/bin/dummy-builder.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rbuilder::{
1616
BlockBuildingAlgorithm, BlockBuildingAlgorithmInput, OrderConsumer,
1717
UnfinishedBlockBuildingSink, UnfinishedBlockBuildingSinkFactory,
1818
},
19-
BlockBuildingContext, SimulatedOrderStore,
19+
BlockBuildingContext, SimulatedOrderStore, ThreadBlockBuildingContext,
2020
},
2121
live_builder::{
2222
base_config::{
@@ -206,22 +206,23 @@ impl DummyBuildingAlgorithm {
206206
where
207207
P: StateProviderFactory + Clone + 'static,
208208
{
209+
let mut local_ctx = ThreadBlockBuildingContext::default();
209210
let block_state = provider
210211
.history_by_block_hash(ctx.attributes.parent)?
211212
.into();
212213

213214
let mut block_building_helper = BlockBuildingHelperFromProvider::new(
214215
block_state,
215216
ctx.clone(),
216-
None,
217+
&mut local_ctx,
217218
BUILDER_NAME.to_string(),
218219
false,
219220
CancellationToken::new(),
220221
)?;
221222

222223
for order in orders {
223224
// don't care about the result
224-
let _ = block_building_helper.commit_order(&order, &|_| Ok(()))?;
225+
let _ = block_building_helper.commit_order(&mut local_ctx, &order, &|_| Ok(()))?;
225226
}
226227
Ok(Box::new(block_building_helper))
227228
}

0 commit comments

Comments
 (0)