diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index ecca773a4..e00b04354 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -341,14 +341,6 @@ pub struct LoadAndExecuteSanitizedTransactionsOutput { // Vector of results indicating whether a transaction was executed or could not // be executed. Note executed transactions can still have failed! pub execution_results: Vec, - // Total number of transactions that were executed - pub executed_transactions_count: usize, - // Number of non-vote transactions that were executed - pub executed_non_vote_transactions_count: usize, - // Total number of the executed transactions that returned success/not - // an error. - pub executed_with_successful_result_count: usize, - pub signature_count: u64, } pub struct TransactionSimulationResult { @@ -5187,152 +5179,8 @@ impl Bank { account_overrides, log_messages_bytes_limit, ); - LoadAndExecuteTransactionsOutput { - loaded_transactions: sanitized_output.loaded_transactions, - execution_results: sanitized_output.execution_results, - retryable_transaction_indexes, - executed_transactions_count: sanitized_output.executed_transactions_count, - executed_non_vote_transactions_count: sanitized_output - .executed_non_vote_transactions_count, - executed_with_successful_result_count: sanitized_output - .executed_with_successful_result_count, - signature_count: sanitized_output.signature_count, - error_counters, - } - } - #[allow(clippy::too_many_arguments)] - fn load_and_execute_sanitized_transactions( - &self, - sanitized_txs: &[SanitizedTransaction], - check_results: &mut [TransactionCheckResult], - error_counters: &mut TransactionErrorMetrics, - enable_cpi_recording: bool, - enable_log_recording: bool, - enable_return_data_recording: bool, - timings: &mut ExecuteTimings, - account_overrides: Option<&AccountOverrides>, - log_messages_bytes_limit: Option, - ) -> LoadAndExecuteSanitizedTransactionsOutput { - let mut program_accounts_map = self.filter_executable_program_accounts( - &self.ancestors, - sanitized_txs, - check_results, - PROGRAM_OWNERS, - &self.blockhash_queue.read().unwrap(), - ); - let native_loader = native_loader::id(); - for builtin_program in self.builtin_programs.iter() { - program_accounts_map.insert(*builtin_program, (&native_loader, 0)); - } - - let programs_loaded_for_tx_batch = Rc::new(RefCell::new( - self.replenish_program_cache(&program_accounts_map), - )); - - let mut load_time = Measure::start("accounts_load"); - let mut loaded_transactions = load_accounts( - &self.rc.accounts.accounts_db, - &self.ancestors, - sanitized_txs, - check_results, - &self.blockhash_queue.read().unwrap(), - error_counters, - &self.rent_collector, - &self.feature_set, - &self.fee_structure, - account_overrides, - self.get_reward_interval(), - &program_accounts_map, - &programs_loaded_for_tx_batch.borrow(), - self.should_collect_rent(), - ); - load_time.stop(); - - let mut execution_time = Measure::start("execution_time"); - let mut signature_count: u64 = 0; - - let execution_results: Vec = loaded_transactions - .iter_mut() - .zip(sanitized_txs.iter()) - .map(|(accs, tx)| match accs { - (Err(e), _nonce) => TransactionExecutionResult::NotExecuted(e.clone()), - (Ok(loaded_transaction), nonce) => { - let compute_budget = - if let Some(compute_budget) = self.runtime_config.compute_budget { - compute_budget - } else { - let mut compute_budget_process_transaction_time = - Measure::start("compute_budget_process_transaction_time"); - let maybe_compute_budget = ComputeBudget::try_from_instructions( - tx.message().program_instructions_iter(), - ); - compute_budget_process_transaction_time.stop(); - saturating_add_assign!( - timings - .execute_accessories - .compute_budget_process_transaction_us, - compute_budget_process_transaction_time.as_us() - ); - if let Err(err) = maybe_compute_budget { - return TransactionExecutionResult::NotExecuted(err); - } - maybe_compute_budget.unwrap() - }; - - let result = self.execute_loaded_transaction( - tx, - loaded_transaction, - compute_budget, - nonce.as_ref().map(DurableNonceFee::from), - enable_cpi_recording, - enable_log_recording, - enable_return_data_recording, - timings, - error_counters, - log_messages_bytes_limit, - &programs_loaded_for_tx_batch.borrow(), - ); - - if let TransactionExecutionResult::Executed { - details, - programs_modified_by_tx, - } = &result - { - // Update batch specific cache of the loaded programs with the modifications - // made by the transaction, if it executed successfully. - if details.status.is_ok() { - programs_loaded_for_tx_batch - .borrow_mut() - .merge(programs_modified_by_tx); - } - } - - result - } - }) - .collect(); - - execution_time.stop(); - - const SHRINK_LOADED_PROGRAMS_TO_PERCENTAGE: u8 = 90; - self.loaded_programs_cache - .write() - .unwrap() - .evict_using_2s_random_selection( - Percentage::from(SHRINK_LOADED_PROGRAMS_TO_PERCENTAGE), - self.slot(), - ); - - debug!( - "load: {}us execute: {}us txs_len={}", - load_time.as_us(), - execution_time.as_us(), - sanitized_txs.len(), - ); - - timings.saturating_add_in_place(ExecuteTimingType::LoadUs, load_time.as_us()); - timings.saturating_add_in_place(ExecuteTimingType::ExecuteUs, execution_time.as_us()); + let mut signature_count = 0; let mut executed_transactions_count: usize = 0; let mut executed_non_vote_transactions_count: usize = 0; @@ -5342,7 +5190,7 @@ impl Bank { self.transaction_log_collector_config.read().unwrap(); let mut collect_logs_time = Measure::start("collect_logs_time"); - for (execution_result, tx) in execution_results.iter().zip(sanitized_txs) { + for (execution_result, tx) in sanitized_output.execution_results.iter().zip(sanitized_txs) { if let Some(debug_keys) = &self.transaction_debug_keys { for key in tx.message().account_keys().iter() { if debug_keys.contains(key) { @@ -5446,13 +5294,154 @@ impl Bank { *err_count + executed_with_successful_result_count ); } - LoadAndExecuteSanitizedTransactionsOutput { - loaded_transactions, - execution_results, + + LoadAndExecuteTransactionsOutput { + loaded_transactions: sanitized_output.loaded_transactions, + execution_results: sanitized_output.execution_results, + retryable_transaction_indexes, executed_transactions_count, executed_non_vote_transactions_count, executed_with_successful_result_count, signature_count, + error_counters, + } + } + + #[allow(clippy::too_many_arguments)] + fn load_and_execute_sanitized_transactions( + &self, + sanitized_txs: &[SanitizedTransaction], + check_results: &mut [TransactionCheckResult], + error_counters: &mut TransactionErrorMetrics, + enable_cpi_recording: bool, + enable_log_recording: bool, + enable_return_data_recording: bool, + timings: &mut ExecuteTimings, + account_overrides: Option<&AccountOverrides>, + log_messages_bytes_limit: Option, + ) -> LoadAndExecuteSanitizedTransactionsOutput { + let mut program_accounts_map = self.filter_executable_program_accounts( + &self.ancestors, + sanitized_txs, + check_results, + PROGRAM_OWNERS, + &self.blockhash_queue.read().unwrap(), + ); + let native_loader = native_loader::id(); + for builtin_program in self.builtin_programs.iter() { + program_accounts_map.insert(*builtin_program, (&native_loader, 0)); + } + + let programs_loaded_for_tx_batch = Rc::new(RefCell::new( + self.replenish_program_cache(&program_accounts_map), + )); + + let mut load_time = Measure::start("accounts_load"); + let mut loaded_transactions = load_accounts( + &self.rc.accounts.accounts_db, + &self.ancestors, + sanitized_txs, + check_results, + &self.blockhash_queue.read().unwrap(), + error_counters, + &self.rent_collector, + &self.feature_set, + &self.fee_structure, + account_overrides, + self.get_reward_interval(), + &program_accounts_map, + &programs_loaded_for_tx_batch.borrow(), + self.should_collect_rent(), + ); + load_time.stop(); + + let mut execution_time = Measure::start("execution_time"); + + let execution_results: Vec = loaded_transactions + .iter_mut() + .zip(sanitized_txs.iter()) + .map(|(accs, tx)| match accs { + (Err(e), _nonce) => TransactionExecutionResult::NotExecuted(e.clone()), + (Ok(loaded_transaction), nonce) => { + let compute_budget = + if let Some(compute_budget) = self.runtime_config.compute_budget { + compute_budget + } else { + let mut compute_budget_process_transaction_time = + Measure::start("compute_budget_process_transaction_time"); + let maybe_compute_budget = ComputeBudget::try_from_instructions( + tx.message().program_instructions_iter(), + ); + compute_budget_process_transaction_time.stop(); + saturating_add_assign!( + timings + .execute_accessories + .compute_budget_process_transaction_us, + compute_budget_process_transaction_time.as_us() + ); + if let Err(err) = maybe_compute_budget { + return TransactionExecutionResult::NotExecuted(err); + } + maybe_compute_budget.unwrap() + }; + + let result = self.execute_loaded_transaction( + tx, + loaded_transaction, + compute_budget, + nonce.as_ref().map(DurableNonceFee::from), + enable_cpi_recording, + enable_log_recording, + enable_return_data_recording, + timings, + error_counters, + log_messages_bytes_limit, + &programs_loaded_for_tx_batch.borrow(), + ); + + if let TransactionExecutionResult::Executed { + details, + programs_modified_by_tx, + } = &result + { + // Update batch specific cache of the loaded programs with the modifications + // made by the transaction, if it executed successfully. + if details.status.is_ok() { + programs_loaded_for_tx_batch + .borrow_mut() + .merge(programs_modified_by_tx); + } + } + + result + } + }) + .collect(); + + execution_time.stop(); + + const SHRINK_LOADED_PROGRAMS_TO_PERCENTAGE: u8 = 90; + self.loaded_programs_cache + .write() + .unwrap() + .evict_using_2s_random_selection( + Percentage::from(SHRINK_LOADED_PROGRAMS_TO_PERCENTAGE), + self.slot(), + ); + + debug!( + "load: {}us execute: {}us txs_len={}", + load_time.as_us(), + execution_time.as_us(), + sanitized_txs.len(), + ); + + timings.saturating_add_in_place(ExecuteTimingType::LoadUs, load_time.as_us()); + timings.saturating_add_in_place(ExecuteTimingType::ExecuteUs, execution_time.as_us()); + + LoadAndExecuteSanitizedTransactionsOutput { + loaded_transactions, + execution_results, } }