directly use compute_budget MAX_UNITS and DEFAULT_UNITS

This commit is contained in:
Tao Zhu 2022-03-16 10:34:15 -05:00 committed by Tao Zhu
parent a4cacf3389
commit 0ed23899e7
7 changed files with 44 additions and 48 deletions

View File

@ -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,
));
}

View File

@ -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()

View File

@ -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,

View File

@ -1193,6 +1193,7 @@ pub fn visit_each_account_once<E>(
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();
}

View File

@ -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),

View File

@ -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

View File

@ -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());