diff --git a/Cargo.lock b/Cargo.lock index 2362c0e8de3801..9aedd912f45fc5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7404,9 +7404,11 @@ name = "solana-runtime-transaction" version = "2.1.0" dependencies = [ "bincode", + "criterion", "log", "rand 0.8.5", "rustc_version 0.4.0", + "solana-builtins-default-costs", "solana-compute-budget", "solana-program", "solana-sdk", diff --git a/runtime-transaction/Cargo.toml b/runtime-transaction/Cargo.toml index 22635d6c121159..2965564e63d3dc 100644 --- a/runtime-transaction/Cargo.toml +++ b/runtime-transaction/Cargo.toml @@ -21,11 +21,17 @@ name = "solana_runtime_transaction" [dev-dependencies] bincode = { workspace = true } +criterion = { workspace = true } rand = { workspace = true } -solana-program ={ workspace = true } +solana-builtins-default-costs = { workspace = true } +solana-program = { workspace = true } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [build-dependencies] rustc_version = { workspace = true, optional = true } + +[[bench]] +name = "process_compute_budget_instructions" +harness = false diff --git a/runtime-transaction/benches/process_compute_budget_instructions.rs b/runtime-transaction/benches/process_compute_budget_instructions.rs new file mode 100644 index 00000000000000..463a4cda596c3a --- /dev/null +++ b/runtime-transaction/benches/process_compute_budget_instructions.rs @@ -0,0 +1,168 @@ +use { + criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput}, + solana_runtime_transaction::instructions_processor::process_compute_budget_instructions, + solana_sdk::{ + compute_budget::ComputeBudgetInstruction, + instruction::Instruction, + message::Message, + pubkey::Pubkey, + signature::Keypair, + signer::Signer, + system_instruction::{self}, + transaction::{SanitizedTransaction, Transaction}, + }, +}; + +const NUM_TRANSACTIONS_PER_ITER: usize = 1024; +const DUMMY_PROGRAM_ID: &str = "dummmy1111111111111111111111111111111111111"; + +fn build_sanitized_transaction( + payer_keypair: &Keypair, + instructions: &[Instruction], +) -> SanitizedTransaction { + SanitizedTransaction::from_transaction_for_tests(Transaction::new_unsigned(Message::new( + instructions, + Some(&payer_keypair.pubkey()), + ))) +} + +fn bench_process_compute_budget_instructions_empty(c: &mut Criterion) { + c.benchmark_group("bench_process_compute_budget_instructions_empty") + .throughput(Throughput::Elements(NUM_TRANSACTIONS_PER_ITER as u64)) + .bench_function("0 instructions", |bencher| { + let tx = build_sanitized_transaction(&Keypair::new(), &[]); + bencher.iter(|| { + (0..NUM_TRANSACTIONS_PER_ITER).for_each(|_| { + assert!(process_compute_budget_instructions(black_box( + tx.message().program_instructions_iter() + )) + .is_ok()) + }) + }); + }); +} + +fn bench_process_compute_budget_instructions_no_builtins(c: &mut Criterion) { + let num_instructions = 4; + c.benchmark_group("bench_process_compute_budget_instructions_no_builtins") + .throughput(Throughput::Elements(NUM_TRANSACTIONS_PER_ITER as u64)) + .bench_function( + format!("{num_instructions} dummy Instructions"), + |bencher| { + let ixs: Vec<_> = (0..num_instructions) + .map(|_| { + Instruction::new_with_bincode( + DUMMY_PROGRAM_ID.parse().unwrap(), + &(), + vec![], + ) + }) + .collect(); + let tx = build_sanitized_transaction(&Keypair::new(), &ixs); + bencher.iter(|| { + (0..NUM_TRANSACTIONS_PER_ITER).for_each(|_| { + assert!(process_compute_budget_instructions(black_box( + tx.message().program_instructions_iter() + )) + .is_ok()) + }) + }); + }, + ); +} + +fn bench_process_compute_budget_instructions_compute_budgets(c: &mut Criterion) { + c.benchmark_group("bench_process_compute_budget_instructions_compute_budgets") + .throughput(Throughput::Elements(NUM_TRANSACTIONS_PER_ITER as u64)) + .bench_function("4 compute-budget instructions", |bencher| { + let ixs = vec![ + ComputeBudgetInstruction::request_heap_frame(40 * 1024), + ComputeBudgetInstruction::set_compute_unit_limit(u32::MAX), + ComputeBudgetInstruction::set_compute_unit_price(u64::MAX), + ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(u32::MAX), + ]; + let tx = build_sanitized_transaction(&Keypair::new(), &ixs); + bencher.iter(|| { + (0..NUM_TRANSACTIONS_PER_ITER).for_each(|_| { + assert!(process_compute_budget_instructions(black_box( + tx.message().program_instructions_iter() + )) + .is_ok()) + }) + }); + }); +} + +fn bench_process_compute_budget_instructions_builtins(c: &mut Criterion) { + c.benchmark_group("bench_process_compute_budget_instructions_builtins") + .throughput(Throughput::Elements(NUM_TRANSACTIONS_PER_ITER as u64)) + .bench_function("4 dummy builtins", |bencher| { + let ixs = vec![ + Instruction::new_with_bincode(solana_sdk::bpf_loader::id(), &(), vec![]), + Instruction::new_with_bincode(solana_sdk::secp256k1_program::id(), &(), vec![]), + Instruction::new_with_bincode( + solana_sdk::address_lookup_table::program::id(), + &(), + vec![], + ), + Instruction::new_with_bincode(solana_sdk::loader_v4::id(), &(), vec![]), + ]; + let tx = build_sanitized_transaction(&Keypair::new(), &ixs); + bencher.iter(|| { + (0..NUM_TRANSACTIONS_PER_ITER).for_each(|_| { + assert!(process_compute_budget_instructions(black_box( + tx.message().program_instructions_iter() + )) + .is_ok()) + }) + }); + }); +} + +fn bench_process_compute_budget_instructions_mixed(c: &mut Criterion) { + let num_instructions = 355; + c.benchmark_group("bench_process_compute_budget_instructions_mixed") + .throughput(Throughput::Elements(NUM_TRANSACTIONS_PER_ITER as u64)) + .bench_function( + format!("{num_instructions} mixed instructions"), + |bencher| { + let payer_keypair = Keypair::new(); + let mut ixs: Vec<_> = (0..num_instructions) + .map(|_| { + Instruction::new_with_bincode( + DUMMY_PROGRAM_ID.parse().unwrap(), + &(), + vec![], + ) + }) + .collect(); + ixs.extend(vec![ + ComputeBudgetInstruction::request_heap_frame(40 * 1024), + ComputeBudgetInstruction::set_compute_unit_limit(u32::MAX), + ComputeBudgetInstruction::set_compute_unit_price(u64::MAX), + ComputeBudgetInstruction::set_loaded_accounts_data_size_limit(u32::MAX), + system_instruction::transfer(&payer_keypair.pubkey(), &Pubkey::new_unique(), 1), + ]); + let tx = build_sanitized_transaction(&payer_keypair, &ixs); + + bencher.iter(|| { + (0..NUM_TRANSACTIONS_PER_ITER).for_each(|_| { + assert!(process_compute_budget_instructions(black_box( + tx.message().program_instructions_iter() + )) + .is_ok()) + }) + }); + }, + ); +} + +criterion_group!( + benches, + bench_process_compute_budget_instructions_empty, + bench_process_compute_budget_instructions_no_builtins, + bench_process_compute_budget_instructions_compute_budgets, + bench_process_compute_budget_instructions_builtins, + bench_process_compute_budget_instructions_mixed, +); +criterion_main!(benches);