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