From 4aa13e25c1f5e27bbf89f37b1133b021e97a6fbd Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Fri, 18 Aug 2023 22:01:54 +0200 Subject: [PATCH] perf: tweak optimizations again --- Cargo.toml | 18 ++++++++++++------ crates/cli/src/utils/cmd.rs | 4 ++-- crates/evm/src/fuzz/invariant/error.rs | 9 +++------ crates/evm/src/fuzz/invariant/executor.rs | 8 ++++---- crates/evm/src/trace/decoder.rs | 14 +++++++++++--- crates/forge/src/runner.rs | 7 +++---- 6 files changed, 35 insertions(+), 25 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 71828bf6c14a7..d799d70f4b66e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,14 +19,22 @@ debug = 0 # Speed up tests and dev build [profile.dev.package] +# solc +ethers-solc.opt-level = 3 +solang-parser.opt-level = 3 +serde_json.opt-level = 3 + # evm revm.opt-level = 3 revm-primitives.opt-level = 3 revm-interpreter.opt-level = 3 revm-precompile.opt-level = 3 tiny-keccak.opt-level = 3 +sha2.opt-level = 3 +sha3.opt-level = 3 +keccak.opt-level = 3 ruint.opt-level = 3 -primitive-types.opt-level = 3 +hashbrown.opt-level = 3 # keystores scrypt.opt-level = 3 @@ -48,7 +56,6 @@ codegen-units = 1 # Package overrides foundry-evm.opt-level = 3 -ethers-solc.opt-level = 1 foundry-abi.opt-level = 1 mdbook.opt-level = 1 protobuf.opt-level = 1 @@ -93,12 +100,11 @@ wasm-bindgen-backend.opt-level = 0 # Local "release" mode, more optimized than dev but much faster to compile than release [profile.local] -inherits = "release" +inherits = "dev" opt-level = 1 -lto = "none" +strip = true +panic = "abort" codegen-units = 16 -# Empty, clears `profile.release.package` -package = {} [workspace.dependencies] anvil = { path = "crates/anvil" } diff --git a/crates/cli/src/utils/cmd.rs b/crates/cli/src/utils/cmd.rs index 44a5dbc6f4b92..e41790a27fcf9 100644 --- a/crates/cli/src/utils/cmd.rs +++ b/crates/cli/src/utils/cmd.rs @@ -393,7 +393,7 @@ pub async fn handle_traces( let (sources, bytecode) = etherscan_identifier.get_compiled_contracts().await?; run_debugger(result, decoder, bytecode, sources)?; } else { - print_traces(&mut result, decoder, verbose).await?; + print_traces(&mut result, &decoder, verbose).await?; } Ok(()) @@ -401,7 +401,7 @@ pub async fn handle_traces( pub async fn print_traces( result: &mut TraceResult, - decoder: CallTraceDecoder, + decoder: &CallTraceDecoder, verbose: bool, ) -> Result<()> { if result.traces.is_empty() { diff --git a/crates/evm/src/fuzz/invariant/error.rs b/crates/evm/src/fuzz/invariant/error.rs index c09e52e85ab3c..2f1be0c510a03 100644 --- a/crates/evm/src/fuzz/invariant/error.rs +++ b/crates/evm/src/fuzz/invariant/error.rs @@ -166,15 +166,12 @@ impl InvariantFuzzError { anchor: usize, removed_calls: &[usize], ) -> Result, ()> { - let calls = calls.iter().enumerate().filter_map(|(index, element)| { + let mut new_sequence = Vec::with_capacity(calls.len()); + for (index, details) in calls.iter().enumerate() { if anchor > index || removed_calls.contains(&index) { - return None + continue } - Some(element) - }); - let mut new_sequence = vec![]; - for details in calls { new_sequence.push(details); let (sender, (addr, bytes)) = details; diff --git a/crates/evm/src/fuzz/invariant/executor.rs b/crates/evm/src/fuzz/invariant/executor.rs index acbffe60347f9..3907884d02338 100644 --- a/crates/evm/src/fuzz/invariant/executor.rs +++ b/crates/evm/src/fuzz/invariant/executor.rs @@ -98,9 +98,9 @@ impl<'a> InvariantExecutor<'a> { /// Returns a list of all the consumed gas and calldata of every invariant fuzz case pub fn invariant_fuzz( &mut self, - invariant_contract: InvariantContract, + invariant_contract: &InvariantContract, ) -> eyre::Result { - let (fuzz_state, targeted_contracts, strat) = self.prepare_fuzzing(&invariant_contract)?; + let (fuzz_state, targeted_contracts, strat) = self.prepare_fuzzing(invariant_contract)?; // Stores the consumed gas and calldata of every successful fuzz call. let fuzz_cases: RefCell> = RefCell::new(Default::default()); @@ -113,7 +113,7 @@ impl<'a> InvariantExecutor<'a> { let last_call_results = RefCell::new( assert_invariants( - &invariant_contract, + invariant_contract, &blank_executor.borrow(), &[], &mut failures.borrow_mut(), @@ -199,7 +199,7 @@ impl<'a> InvariantExecutor<'a> { }); let RichInvariantResults { success: can_continue, call_results } = can_continue( - &invariant_contract, + invariant_contract, call_result, &executor, &inputs, diff --git a/crates/evm/src/trace/decoder.rs b/crates/evm/src/trace/decoder.rs index f8e8ae651a1c3..c2a51c6dad77b 100644 --- a/crates/evm/src/trace/decoder.rs +++ b/crates/evm/src/trace/decoder.rs @@ -15,6 +15,7 @@ use ethers::{ }; use foundry_common::{abi::get_indexed_event, SELECTOR_LEN}; use hashbrown::HashSet; +use once_cell::sync::OnceCell; use std::collections::{BTreeMap, HashMap}; /// Build a new [CallTraceDecoder]. @@ -25,7 +26,7 @@ pub struct CallTraceDecoderBuilder { impl CallTraceDecoderBuilder { pub fn new() -> Self { - Self { decoder: CallTraceDecoder::new() } + Self { decoder: CallTraceDecoder::new().clone() } } /// Add known labels to the decoder. @@ -65,7 +66,7 @@ impl CallTraceDecoderBuilder { /// /// Note that a call trace decoder is required for each new set of traces, since addresses in /// different sets might overlap. -#[derive(Default, Debug)] +#[derive(Clone, Default, Debug)] pub struct CallTraceDecoder { /// Information for decoding precompile calls. pub precompiles: HashMap, @@ -115,7 +116,14 @@ impl CallTraceDecoder { /// /// The call trace decoder always knows how to decode calls to the cheatcode address, as well /// as DSTest-style logs. - pub fn new() -> Self { + pub fn new() -> &'static Self { + // If you want to take arguments in this function, assign them to the fields of the cloned + // lazy instead of removing it + static INIT: OnceCell = OnceCell::new(); + INIT.get_or_init(Self::init) + } + + fn init() -> Self { Self { // TODO: These are the Ethereum precompiles. We should add a way to support precompiles // for other networks, too. diff --git a/crates/forge/src/runner.rs b/crates/forge/src/runner.rs index b500309d4bc06..c489429696a80 100644 --- a/crates/forge/src/runner.rs +++ b/crates/forge/src/runner.rs @@ -451,15 +451,14 @@ impl<'a> ContractRunner<'a> { InvariantContract { address, invariant_functions: functions, abi: self.contract }; let Ok(InvariantFuzzTestResult { invariants, cases, reverts, last_run_inputs }) = - evm.invariant_fuzz(invariant_contract.clone()) + evm.invariant_fuzz(&invariant_contract) else { return vec![] }; invariants .into_values() - .map(|test_error| { - let (test_error, invariant) = test_error; + .map(|(test_error, invariant)| { let mut counterexample = None; let mut logs = logs.clone(); let mut traces = traces.clone(); @@ -495,7 +494,7 @@ impl<'a> ContractRunner<'a> { // If invariants ran successfully, replay the last run to collect logs and // traces. replay_run( - &invariant_contract.clone(), + &invariant_contract, self.executor.clone(), known_contracts, identified_contracts.clone(),