From 0ed23899e79253a4449954f8b91f77981eba6a8f Mon Sep 17 00:00:00 2001 From: Tao Zhu Date: Wed, 16 Mar 2022 10:34:15 -0500 Subject: [PATCH] directly use compute_budget MAX_UNITS and DEFAULT_UNITS --- cli/src/cluster_query.rs | 4 +-- core/src/cost_update_service.rs | 8 +++--- program-runtime/src/compute_budget.rs | 17 ++++------- program-runtime/src/invoke_context.rs | 9 +++--- runtime/src/bank.rs | 11 +++++-- runtime/src/cost_model.rs | 2 +- runtime/src/execute_cost_table.rs | 41 +++++++++++++-------------- 7 files changed, 44 insertions(+), 48 deletions(-) diff --git a/cli/src/cluster_query.rs b/cli/src/cluster_query.rs index 8835868a3..1fb3119a3 100644 --- a/cli/src/cluster_query.rs +++ b/cli/src/cluster_query.rs @@ -33,7 +33,7 @@ use { rpc_request::DELINQUENT_VALIDATOR_SLOT_DISTANCE, rpc_response::SlotInfo, }, - solana_program_runtime::compute_budget::ComputeBudget, + solana_program_runtime::compute_budget, solana_remote_wallet::remote_wallet::RemoteWalletManager, solana_sdk::{ account::from_account, @@ -1409,7 +1409,7 @@ pub fn process_ping( )]; if let Some(additional_fee) = additional_fee { ixs.push(ComputeBudgetInstruction::request_units( - ComputeBudget::new(false).max_units as u32, + compute_budget::DEFAULT_UNITS, *additional_fee, )); } diff --git a/core/src/cost_update_service.rs b/core/src/cost_update_service.rs index 35a82f8d8..d2b4a0bfa 100644 --- a/core/src/cost_update_service.rs +++ b/core/src/cost_update_service.rs @@ -288,7 +288,7 @@ mod tests { // new erroring compute costs let cost_per_error = 1000; // the expect cost is (previous_cost + new_cost)/2 = (100 + 1000)/2 = 550 - let expect_units = 550; + let expected_units = 550; { let errored_txs_compute_consumed = vec![cost_per_error; 3]; let total_errored_units = errored_txs_compute_consumed.iter().sum(); @@ -307,7 +307,7 @@ mod tests { 1 ); assert_eq!( - Some(&expect_units), + Some(&expected_units), cost_model .read() .unwrap() @@ -319,7 +319,7 @@ mod tests { // Test updating cost model with only erroring compute costs where the error cost is // `smaller_cost_per_error`, less than the current instruction cost for the program. // The cost should not decrease for these new lesser errors - let smaller_cost_per_error = expect_units - 10; + let smaller_cost_per_error = expected_units - 10; { let errored_txs_compute_consumed = vec![smaller_cost_per_error; 3]; let total_errored_units = errored_txs_compute_consumed.iter().sum(); @@ -338,7 +338,7 @@ mod tests { 1 ); assert_eq!( - Some(&expect_units), + Some(&expected_units), cost_model .read() .unwrap() diff --git a/program-runtime/src/compute_budget.rs b/program-runtime/src/compute_budget.rs index b3bba0d03..dfacf2a57 100644 --- a/program-runtime/src/compute_budget.rs +++ b/program-runtime/src/compute_budget.rs @@ -7,7 +7,8 @@ use solana_sdk::{ transaction::TransactionError, }; -const MAX_UNITS: u32 = 1_400_000; +pub const DEFAULT_UNITS: u32 = 200_000; +pub const MAX_UNITS: u32 = 1_400_000; const MAX_HEAP_FRAME_BYTES: u32 = 256 * 1024; #[cfg(RUSTC_WITH_SPECIALIZATION)] @@ -67,14 +68,14 @@ pub struct ComputeBudget { impl Default for ComputeBudget { fn default() -> Self { - Self::new(true) + Self::new(MAX_UNITS) } } impl ComputeBudget { - pub fn new(use_max_units_default: bool) -> Self { + pub fn new(max_units: u32) -> Self { ComputeBudget { - max_units: ComputeBudget::get_max_units(use_max_units_default), + max_units: max_units as u64, log_64_units: 100, create_program_address_units: 1500, invoke_units: 1000, @@ -97,14 +98,6 @@ impl ComputeBudget { } } - pub fn get_max_units(use_max_units_default: bool) -> u64 { - if use_max_units_default { - MAX_UNITS as u64 - } else { - 200_000 - } - } - pub fn process_message( &mut self, message: &SanitizedMessage, diff --git a/program-runtime/src/invoke_context.rs b/program-runtime/src/invoke_context.rs index 545c6ade9..3b90fa1fb 100644 --- a/program-runtime/src/invoke_context.rs +++ b/program-runtime/src/invoke_context.rs @@ -1193,6 +1193,7 @@ pub fn visit_each_account_once( mod tests { use { super::*, + crate::compute_budget, serde::{Deserialize, Serialize}, solana_sdk::account::{ReadableAccount, WritableAccount}, }; @@ -1674,12 +1675,12 @@ mod tests { let mut transaction_context = TransactionContext::new(accounts, 1, 3); let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); invoke_context.feature_set = Arc::new(feature_set); - invoke_context.compute_budget = ComputeBudget::new(false); + invoke_context.compute_budget = ComputeBudget::new(compute_budget::DEFAULT_UNITS); invoke_context.push(&[], &[0], &[]).unwrap(); assert_eq!( *invoke_context.get_compute_budget(), - ComputeBudget::new(false) + ComputeBudget::new(compute_budget::DEFAULT_UNITS) ); invoke_context.pop().unwrap(); @@ -1687,7 +1688,7 @@ mod tests { let expected_compute_budget = ComputeBudget { max_units: 500_000, heap_size: Some(256_usize.saturating_mul(1024)), - ..ComputeBudget::new(false) + ..ComputeBudget::new(compute_budget::DEFAULT_UNITS) }; assert_eq!( *invoke_context.get_compute_budget(), @@ -1698,7 +1699,7 @@ mod tests { invoke_context.push(&[], &[0], &[]).unwrap(); assert_eq!( *invoke_context.get_compute_budget(), - ComputeBudget::new(false) + ComputeBudget::new(compute_budget::DEFAULT_UNITS) ); invoke_context.pop().unwrap(); } diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 4924fa6c0..57f50deb5 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -76,7 +76,7 @@ use { solana_metrics::{inc_new_counter_debug, inc_new_counter_info}, solana_program_runtime::{ accounts_data_meter::MAX_ACCOUNTS_DATA_LEN, - compute_budget::ComputeBudget, + compute_budget::{self, ComputeBudget}, invoke_context::{ BuiltinProgram, Executor, Executors, ProcessInstructionWithContext, TransactionExecutor, }, @@ -4053,9 +4053,14 @@ impl Bank { signature_count += u64::from(tx.message().header().num_required_signatures); let tx_wide_compute_cap = feature_set.is_active(&tx_wide_compute_cap::id()); + let compute_budget_max_units = if tx_wide_compute_cap { + compute_budget::MAX_UNITS + } else { + compute_budget::DEFAULT_UNITS + }; let mut compute_budget = self .compute_budget - .unwrap_or_else(|| ComputeBudget::new(tx_wide_compute_cap)); + .unwrap_or_else(|| ComputeBudget::new(compute_budget_max_units)); if tx_wide_compute_cap { let mut compute_budget_process_transaction_time = Measure::start("compute_budget_process_transaction_time"); @@ -16925,7 +16930,7 @@ pub(crate) mod tests { let compute_budget = bank .compute_budget - .unwrap_or_else(|| ComputeBudget::new(false)); + .unwrap_or_else(|| ComputeBudget::new(compute_budget::DEFAULT_UNITS)); let transaction_context = TransactionContext::new( loaded_txs[0].0.as_ref().unwrap().accounts.clone(), compute_budget.max_invoke_depth.saturating_add(1), diff --git a/runtime/src/cost_model.rs b/runtime/src/cost_model.rs index 66148e248..c3ee7998c 100644 --- a/runtime/src/cost_model.rs +++ b/runtime/src/cost_model.rs @@ -115,7 +115,7 @@ impl CostModel { None => { let default_value = self.instruction_execution_cost_table.get_default_units(); debug!( - "Instruction {:?} does not have aggregated cost, using default value {}", + "Program {:?} does not have aggregated cost, using default value {}", program_key, default_value ); default_value diff --git a/runtime/src/execute_cost_table.rs b/runtime/src/execute_cost_table.rs index 6cb5f15cc..c1ac08f2a 100644 --- a/runtime/src/execute_cost_table.rs +++ b/runtime/src/execute_cost_table.rs @@ -4,7 +4,7 @@ /// When its capacity limit is reached, it prunes old and less-used programs /// to make room for new ones. use { - log::*, solana_program_runtime::compute_budget::ComputeBudget, solana_sdk::pubkey::Pubkey, + log::*, solana_program_runtime::compute_budget::DEFAULT_UNITS, solana_sdk::pubkey::Pubkey, std::collections::HashMap, }; @@ -47,13 +47,12 @@ impl ExecuteCostTable { self.table.len() } - // default program cost to max_units + /// default program cost, set to ComputeBudget::DEFAULT_UNITS pub fn get_default_units(&self) -> u64 { - let use_max_units_default = false; - ComputeBudget::get_max_units(use_max_units_default) + DEFAULT_UNITS as u64 } - // average cost of all recorded programs + /// average cost of all recorded programs pub fn get_average_units(&self) -> u64 { if self.table.is_empty() { self.get_default_units() @@ -62,8 +61,8 @@ impl ExecuteCostTable { } } - // the most frequently occurring program's cost - pub fn get_mode_units(&self) -> u64 { + /// the most frequently occurring program's cost + pub fn get_statistical_mode_units(&self) -> u64 { if self.occurrences.is_empty() { self.get_default_units() } else { @@ -78,15 +77,15 @@ impl ExecuteCostTable { } } - // returns None if program doesn't exist in table. In this case, - // `get_default_units()`, `get_average_units()` or `get_mode_units()` - // can be used to assign a value to new program. + /// returns None if program doesn't exist in table. In this case, + /// `get_default_units()`, `get_average_units()` or `get_statistical_mode_units()` + /// can be used to assign a value to new program. pub fn get_cost(&self, key: &Pubkey) -> Option<&u64> { self.table.get(key) } - // update-or-insert should be infallible. Query the result of upsert, - // often requires additional calculation, should be lazy. + /// update-or-insert should be infallible. Query the result of upsert, + /// often requires additional calculation, should be lazy. pub fn upsert(&mut self, key: &Pubkey, value: u64) { let need_to_add = !self.table.contains_key(key); let current_size = self.get_count(); @@ -105,11 +104,9 @@ impl ExecuteCostTable { *timestamp = Self::micros_since_epoch(); } - // prune the old programs so the table contains `new_size` of records, - // where `old` is defined as weighted age, which is negatively correlated - // with program's age and - // positively correlated with how frequently the program - // is executed (eg. occurrence), + /// prune the old programs so the table contains `new_size` of records, + /// where `old` is defined as weighted age, which is negatively correlated + /// with program's age and how frequently the program is occurrenced. fn prune_to(&mut self, new_size: &usize) { debug!( "prune cost table, current size {}, new size {}", @@ -228,14 +225,14 @@ mod tests { testee.upsert(&key1, cost1); assert_eq!(1, testee.get_count()); assert_eq!(cost1, testee.get_average_units()); - assert_eq!(cost1, testee.get_mode_units()); + assert_eq!(cost1, testee.get_statistical_mode_units()); assert_eq!(&cost1, testee.get_cost(&key1).unwrap()); // insert 2nd record testee.upsert(&key2, cost2); assert_eq!(2, testee.get_count()); assert_eq!((cost1 + cost2) / 2_u64, testee.get_average_units()); - assert_eq!(cost2, testee.get_mode_units()); + assert_eq!(cost2, testee.get_statistical_mode_units()); assert_eq!(&cost1, testee.get_cost(&key1).unwrap()); assert_eq!(&cost2, testee.get_cost(&key2).unwrap()); @@ -246,7 +243,7 @@ mod tests { ((cost1 + cost2) / 2 + cost2) / 2_u64, testee.get_average_units() ); - assert_eq!((cost1 + cost2) / 2, testee.get_mode_units()); + assert_eq!((cost1 + cost2) / 2, testee.get_statistical_mode_units()); assert_eq!(&((cost1 + cost2) / 2), testee.get_cost(&key1).unwrap()); assert_eq!(&cost2, testee.get_cost(&key2).unwrap()); } @@ -281,7 +278,7 @@ mod tests { testee.upsert(&key3, cost3); assert_eq!(2, testee.get_count()); assert_eq!((cost2 + cost3) / 2_u64, testee.get_average_units()); - assert_eq!(cost3, testee.get_mode_units()); + assert_eq!(cost3, testee.get_statistical_mode_units()); assert!(testee.get_cost(&key1).is_none()); assert_eq!(&cost2, testee.get_cost(&key2).unwrap()); assert_eq!(&cost3, testee.get_cost(&key3).unwrap()); @@ -294,7 +291,7 @@ mod tests { ((cost1 + cost2) / 2 + cost4) / 2_u64, testee.get_average_units() ); - assert_eq!((cost1 + cost2) / 2, testee.get_mode_units()); + assert_eq!((cost1 + cost2) / 2, testee.get_statistical_mode_units()); assert_eq!(2, testee.get_count()); assert!(testee.get_cost(&key1).is_none()); assert_eq!(&((cost1 + cost2) / 2), testee.get_cost(&key2).unwrap());