From bee89c0b766985313ab39c8d9307a22259c0eef4 Mon Sep 17 00:00:00 2001 From: James Date: Fri, 19 Dec 2025 09:40:02 -0500 Subject: [PATCH] refactor: reduce allocations in the sim task --- crates/rbuilder/src/building/sim.rs | 29 ++++++++++--------- .../src/live_builder/simulation/sim_worker.rs | 6 ++-- .../live_builder/simulation/simulation_job.rs | 3 +- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/crates/rbuilder/src/building/sim.rs b/crates/rbuilder/src/building/sim.rs index b0eccaf7f..93bdcdee5 100644 --- a/crates/rbuilder/src/building/sim.rs +++ b/crates/rbuilder/src/building/sim.rs @@ -20,12 +20,13 @@ use rbuilder_primitives::{Order, OrderId, SimulatedOrder}; use reth_errors::ProviderError; use reth_provider::StateProvider; use std::{ + borrow::Cow, cmp::{max, min, Ordering}, collections::hash_map::Entry, sync::Arc, time::{Duration, Instant}, }; -use tracing::{error, trace}; +use tracing::{error, instrument, trace}; #[derive(Debug)] #[allow(clippy::large_enum_variant)] @@ -41,7 +42,7 @@ pub struct OrderSimResultWithGas { pub gas_used: u64, } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct NonceKey { pub address: Address, pub nonce: u64, @@ -226,11 +227,12 @@ impl SimTree { result: SimulatedResult, ) -> Result<(), ProviderError> { self.sims.insert(result.id, result.clone()); + let mut orders_ready = Vec::new(); if result.nonces_after.len() == 1 { - let updated_nonce = result.nonces_after.first().unwrap().clone(); + let updated_nonce = result.nonces_after.first().unwrap(); - match self.sims_that_update_one_nonce.entry(updated_nonce.clone()) { + match self.sims_that_update_one_nonce.entry(*updated_nonce) { Entry::Occupied(mut entry) => { let current_sim_profit = { let sim_id = entry.get_mut(); @@ -255,7 +257,7 @@ impl SimTree { Entry::Vacant(entry) => { entry.insert(result.id); - if let Some(pending_orders) = self.pending_nonces.remove(&updated_nonce) { + if let Some(pending_orders) = self.pending_nonces.remove(updated_nonce) { for order in pending_orders { match self.pending_orders.entry(order) { Entry::Occupied(mut entry) => { @@ -364,8 +366,8 @@ where let start_time = Instant::now(); let mut block_state = BlockState::new_arc(state_for_sim); let sim_result = simulate_order( - sim_task.parents.clone(), - sim_task.order.clone(), + &sim_task.parents, + Cow::Borrowed(&sim_task.order), ctx, &mut local_ctx, &mut block_state, @@ -412,9 +414,10 @@ where } /// Prepares context (fork + tracer) and calls simulate_order_using_fork +#[instrument(skip_all, level = "debug", fields(order = ?order.id()))] pub fn simulate_order( - parent_orders: Vec, - order: Order, + parent_orders: &[Order], + order: Cow<'_, Order>, ctx: &BlockBuildingContext, local_ctx: &mut ThreadBlockBuildingContext, state: &mut BlockState, @@ -434,8 +437,8 @@ pub fn simulate_order( /// Simulates order (including parent (those needed to reach proper nonces) orders) using a precreated fork pub fn simulate_order_using_fork( - parent_orders: Vec, - order: Order, + parent_orders: &[Order], + order: Cow<'_, Order>, fork: &mut PartialBlockFork<'_, '_, '_, '_, Tracer, NullPartialBlockForkExecutionTracer>, mempool_tx_detector: &MempoolTxsDetector, ) -> Result { @@ -446,7 +449,7 @@ pub fn simulate_order_using_fork( // not change from batching. let combined_refunds = std::collections::HashMap::default(); for parent in parent_orders { - let result = fork.commit_order(&parent, space_state, true, &combined_refunds)?; + let result = fork.commit_order(parent, space_state, true, &combined_refunds)?; match result { Ok(res) => { space_state.use_space(res.space_used); @@ -472,7 +475,7 @@ pub fn simulate_order_using_fork( let new_nonces = res.nonces_updated.into_iter().collect::>(); Ok(OrderSimResult::Success( Arc::new(SimulatedOrder { - order, + order: order.into_owned(), sim_value, used_state_trace: res.used_state_trace, }), diff --git a/crates/rbuilder/src/live_builder/simulation/sim_worker.rs b/crates/rbuilder/src/live_builder/simulation/sim_worker.rs index 838ad3c6c..bd322986d 100644 --- a/crates/rbuilder/src/live_builder/simulation/sim_worker.rs +++ b/crates/rbuilder/src/live_builder/simulation/sim_worker.rs @@ -9,6 +9,7 @@ use crate::{ }; use parking_lot::Mutex; use std::{ + borrow::Cow, sync::Arc, thread::sleep, time::{Duration, Instant}, @@ -57,6 +58,7 @@ pub fn run_sim_worker

( continue 'main; } }; + while let Ok(task) = current_sim_context.requests.recv() { let sim_thread_wait_time = last_sim_finished.elapsed(); let sim_start = Instant::now(); @@ -65,8 +67,8 @@ pub fn run_sim_worker

( let start_time = Instant::now(); let mut block_state = BlockState::new_arc(state_provider.clone()); let sim_result = simulate_order( - task.parents.clone(), - task.order, + &task.parents, + Cow::Owned(task.order), ¤t_sim_context.block_ctx, &mut local_ctx, &mut block_state, diff --git a/crates/rbuilder/src/live_builder/simulation/simulation_job.rs b/crates/rbuilder/src/live_builder/simulation/simulation_job.rs index 2fc950272..005364227 100644 --- a/crates/rbuilder/src/live_builder/simulation/simulation_job.rs +++ b/crates/rbuilder/src/live_builder/simulation/simulation_job.rs @@ -115,7 +115,8 @@ impl SimulationJob { let mut new_sim_results = Vec::new(); loop { self.send_new_tasks_for_simulation(); - // tokio::select appears to be fair so no channel will be polled more than the other + // tokio::select is fair according to its documentation + // https://docs.rs/tokio/latest/tokio/macro.select.html#fairness tokio::select! { n = self.new_order_sub.recv_many(&mut new_commands, 1024) => { if n != 0 {