diff --git a/Cargo.lock b/Cargo.lock index b607e161c6..4fd9fcab22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2875,6 +2875,7 @@ dependencies = [ "ciborium", "clap", "criterion-plot", + "futures", "is-terminal", "itertools 0.10.5", "num-traits 0.2.19", @@ -2887,6 +2888,7 @@ dependencies = [ "serde_derive", "serde_json", "tinytemplate", + "tokio", "walkdir", ] diff --git a/crates/starknet_gateway/Cargo.toml b/crates/starknet_gateway/Cargo.toml index e94b288aaf..4abc9ef5e9 100644 --- a/crates/starknet_gateway/Cargo.toml +++ b/crates/starknet_gateway/Cargo.toml @@ -39,7 +39,7 @@ validator.workspace = true [dev-dependencies] assert_matches.workspace = true cairo-lang-sierra-to-casm.workspace = true -criterion.workspace = true +criterion = { workspace = true, features = ["async_tokio"] } mockall.workspace = true mockito.workspace = true num-bigint.workspace = true @@ -55,3 +55,4 @@ tracing-test.workspace = true harness = false name = "gateway_bench" path = "bench/gateway_bench.rs" +required-features = ["testing"] diff --git a/crates/starknet_gateway/bench/gateway_bench.rs b/crates/starknet_gateway/bench/gateway_bench.rs index a28f74db34..908b46ef3d 100644 --- a/crates/starknet_gateway/bench/gateway_bench.rs +++ b/crates/starknet_gateway/bench/gateway_bench.rs @@ -9,7 +9,8 @@ //! //! Run the benchmarks using `cargo bench --bench gateway_bench`. -use criterion::{criterion_group, criterion_main, Criterion}; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use starknet_gateway::bench_test_utils::{BenchTestSetup, BenchTestSetupConfig}; pub fn declare_benchmark(c: &mut Criterion) { c.bench_function("declares", |benchmark| benchmark.iter(|| {})); @@ -20,7 +21,13 @@ pub fn deploy_account_benchmark(c: &mut Criterion) { } pub fn invoke_benchmark(c: &mut Criterion) { - c.bench_function("invokes", |benchmark| benchmark.iter(|| {})); + let tx_generator_config = BenchTestSetupConfig::default(); + let n_txs = tx_generator_config.n_txs; + + let test_setup = BenchTestSetup::new(tx_generator_config); + c.bench_with_input(BenchmarkId::new("invoke", n_txs), &test_setup, |b, s| { + b.to_async(tokio::runtime::Runtime::new().unwrap()).iter(|| s.send_txs_to_gateway()); + }); } pub fn gateway_benchmark(c: &mut Criterion) { diff --git a/crates/starknet_gateway/src/bench_test_utils.rs b/crates/starknet_gateway/src/bench_test_utils.rs new file mode 100644 index 0000000000..4382b7a6b7 --- /dev/null +++ b/crates/starknet_gateway/src/bench_test_utils.rs @@ -0,0 +1,105 @@ +use std::sync::Arc; + +use blockifier::context::ChainInfo; +use blockifier::test_utils::contracts::FeatureContract; +use blockifier::test_utils::{create_trivial_calldata, CairoVersion}; +use mempool_test_utils::starknet_api_test_utils::test_valid_resource_bounds; +use starknet_api::core::ContractAddress; +use starknet_api::invoke_tx_args; +use starknet_api::rpc_transaction::RpcTransaction; +use starknet_api::test_utils::invoke::rpc_invoke_tx; +use starknet_api::test_utils::NonceManager; +use starknet_sierra_compile::config::SierraToCasmCompilationConfig; + +use crate::compilation::GatewayCompiler; +use crate::config::GatewayConfig; +use crate::gateway::GatewayBusinessLogic; +use crate::state_reader_test_utils::local_test_state_reader_factory; + +const N_TXS: usize = 100; + +pub struct BenchTestSetupConfig { + pub n_txs: usize, + pub gateway_config: GatewayConfig, + pub compiler_config: SierraToCasmCompilationConfig, +} + +impl Default for BenchTestSetupConfig { + fn default() -> Self { + Self { + n_txs: N_TXS, + gateway_config: GatewayConfig { + chain_info: ChainInfo::create_for_testing(), + ..Default::default() + }, + compiler_config: SierraToCasmCompilationConfig::default(), + } + } +} + +pub struct BenchTestSetup { + gateway: GatewayBusinessLogic, + txs: Vec, +} + +struct TransactionGenerator { + nonce_manager: NonceManager, + sender_address: ContractAddress, + test_contract_address: ContractAddress, +} + +impl TransactionGenerator { + fn new(cairo_version: CairoVersion) -> Self { + let account_contract = FeatureContract::AccountWithoutValidations(cairo_version); + let test_contract = FeatureContract::TestContract(cairo_version); + let sender_address = account_contract.get_instance_address(0); + let test_contract_address = test_contract.get_instance_address(0); + Self { nonce_manager: NonceManager::default(), sender_address, test_contract_address } + } + + fn generate_invoke(&mut self) -> RpcTransaction { + let invoke_args = invoke_tx_args!( + nonce: self.nonce_manager.next(self.sender_address), + sender_address: self.sender_address, + resource_bounds: test_valid_resource_bounds(), + calldata: create_trivial_calldata(self.test_contract_address), + ); + rpc_invoke_tx(invoke_args) + } +} + +impl BenchTestSetup { + pub fn new(config: BenchTestSetupConfig) -> Self { + let cairo_version = CairoVersion::Cairo0; + let mut tx_generator = TransactionGenerator::new(cairo_version); + + let mut txs: Vec = Vec::with_capacity(config.n_txs); + for _ in 0..config.n_txs { + txs.push(tx_generator. + // TODO(Arni): Do something smarter than generate raw invoke. + generate_invoke()); + } + + let state_reader_factory = local_test_state_reader_factory(cairo_version, false); + let gateway_compiler = + GatewayCompiler::new_command_line_compiler(config.compiler_config.clone()); + + let gateway_business_logic = GatewayBusinessLogic::new( + config.gateway_config, + Arc::new(state_reader_factory), + gateway_compiler, + ); + + Self { gateway: gateway_business_logic, txs } + } + + pub async fn send_txs_to_gateway(&self) { + for tx in &self.txs { + let _tx_hash = self + .gateway + .add_tx(tx.clone(), None) + .await + .expect("Some txs has failed in the gateway."); + } + } +} diff --git a/crates/starknet_gateway/src/gateway.rs b/crates/starknet_gateway/src/gateway.rs index ffc4ecddb4..0bad4ceff0 100644 --- a/crates/starknet_gateway/src/gateway.rs +++ b/crates/starknet_gateway/src/gateway.rs @@ -26,7 +26,7 @@ use crate::utils::compile_contract_and_build_executable_tx; #[path = "gateway_test.rs"] pub mod gateway_test; -struct GatewayBusinessLogic { +pub struct GatewayBusinessLogic { pub stateless_tx_validator: Arc, pub stateful_tx_validator: Arc, pub state_reader_factory: Arc, @@ -76,7 +76,7 @@ impl GatewayBusinessLogic { pub struct Gateway { pub mempool_client: SharedMempoolClient, - business_logic: GatewayBusinessLogic, + pub business_logic: GatewayBusinessLogic, } impl Gateway { diff --git a/crates/starknet_gateway/src/lib.rs b/crates/starknet_gateway/src/lib.rs index 057e1cef10..acdda2b35e 100644 --- a/crates/starknet_gateway/src/lib.rs +++ b/crates/starknet_gateway/src/lib.rs @@ -1,3 +1,5 @@ +#[cfg(any(feature = "testing", test))] +pub mod bench_test_utils; pub mod communication; pub mod compilation; mod compiler_version; @@ -9,7 +11,7 @@ pub mod rpc_state_reader; #[cfg(test)] mod rpc_state_reader_test; pub mod state_reader; -#[cfg(test)] +#[cfg(any(feature = "testing", test))] mod state_reader_test_utils; mod stateful_transaction_validator; mod stateless_transaction_validator;