Cost model uses compute_unit to replace microsecond as cost unit (#18934)
* wip - cost_update_services to log both us and cu for each instruction to determine possible ratio * replace microsecond with compute_unit as cost unit
This commit is contained in:
@ -12,19 +12,26 @@ use log::*;
|
|||||||
use solana_sdk::{pubkey::Pubkey, sanitized_transaction::SanitizedTransaction};
|
use solana_sdk::{pubkey::Pubkey, sanitized_transaction::SanitizedTransaction};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
// Guestimated from mainnet-beta data, sigver averages 1us, average read 7us and average write 25us
|
// 07-27-2021, compute_unit to microsecond conversion ratio collected from mainnet-beta
|
||||||
|
// differs between instructions. Some bpf instruction has much higher CU/US ratio
|
||||||
|
// (eg 7vxeyaXGLqcp66fFShqUdHxdacp4k4kwUpRSSeoZLCZ4 has average ratio 135), others
|
||||||
|
// have lower ratio (eg 9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin has an average ratio 14).
|
||||||
|
// With this, I am guestimating the flat_fee for sigver and account read/write
|
||||||
|
// as following. This can be adjusted when needed.
|
||||||
const SIGVER_COST: u64 = 1;
|
const SIGVER_COST: u64 = 1;
|
||||||
const NON_SIGNED_READONLY_ACCOUNT_ACCESS_COST: u64 = 7;
|
const NON_SIGNED_READONLY_ACCOUNT_ACCESS_COST: u64 = 1;
|
||||||
const NON_SIGNED_WRITABLE_ACCOUNT_ACCESS_COST: u64 = 25;
|
const NON_SIGNED_WRITABLE_ACCOUNT_ACCESS_COST: u64 = 2;
|
||||||
const SIGNED_READONLY_ACCOUNT_ACCESS_COST: u64 =
|
const SIGNED_READONLY_ACCOUNT_ACCESS_COST: u64 =
|
||||||
SIGVER_COST + NON_SIGNED_READONLY_ACCOUNT_ACCESS_COST;
|
SIGVER_COST + NON_SIGNED_READONLY_ACCOUNT_ACCESS_COST;
|
||||||
const SIGNED_WRITABLE_ACCOUNT_ACCESS_COST: u64 =
|
const SIGNED_WRITABLE_ACCOUNT_ACCESS_COST: u64 =
|
||||||
SIGVER_COST + NON_SIGNED_WRITABLE_ACCOUNT_ACCESS_COST;
|
SIGVER_COST + NON_SIGNED_WRITABLE_ACCOUNT_ACCESS_COST;
|
||||||
|
|
||||||
// Sampled from mainnet-beta, the instruction execution timings stats are (in us):
|
// 07-27-2021, cost model limit is set to "worst case scenario", which is the
|
||||||
// min=194, max=62164, avg=8214.49, med=2243
|
// max compute unit it can execute. From mainnet-beta, the max CU of instruction
|
||||||
pub const ACCOUNT_MAX_COST: u64 = 100_000_000;
|
// is 3753, round up to 4_000. Say we allows max 50_000 instruction per writable i
|
||||||
pub const BLOCK_MAX_COST: u64 = 2_500_000_000;
|
// account, and 1_000_000 instruction per block. It comes to following limits:
|
||||||
|
pub const ACCOUNT_MAX_COST: u64 = 200_000_000;
|
||||||
|
pub const BLOCK_MAX_COST: u64 = 4_000_000_000;
|
||||||
|
|
||||||
const MAX_WRITABLE_ACCOUNTS: usize = 256;
|
const MAX_WRITABLE_ACCOUNTS: usize = 256;
|
||||||
|
|
||||||
|
@ -137,9 +137,12 @@ impl CostUpdateService {
|
|||||||
let mut dirty = false;
|
let mut dirty = false;
|
||||||
{
|
{
|
||||||
let mut cost_model_mutable = cost_model.write().unwrap();
|
let mut cost_model_mutable = cost_model.write().unwrap();
|
||||||
for (program_id, tining) in &execute_timings.details.per_program_timings {
|
for (program_id, timing) in &execute_timings.details.per_program_timings {
|
||||||
let cost = tining.accumulated_us / tining.count as u64;
|
if timing.count < 1 {
|
||||||
match cost_model_mutable.upsert_instruction_cost(program_id, cost) {
|
continue;
|
||||||
|
}
|
||||||
|
let units = timing.accumulated_units / timing.count as u64;
|
||||||
|
match cost_model_mutable.upsert_instruction_cost(program_id, units) {
|
||||||
Ok(c) => {
|
Ok(c) => {
|
||||||
debug!(
|
debug!(
|
||||||
"after replayed into bank, instruction {:?} has averaged cost {}",
|
"after replayed into bank, instruction {:?} has averaged cost {}",
|
||||||
@ -220,7 +223,7 @@ mod tests {
|
|||||||
let accumulated_us: u64 = 1000;
|
let accumulated_us: u64 = 1000;
|
||||||
let accumulated_units: u64 = 100;
|
let accumulated_units: u64 = 100;
|
||||||
let count: u32 = 10;
|
let count: u32 = 10;
|
||||||
expected_cost = accumulated_us / count as u64;
|
expected_cost = accumulated_units / count as u64;
|
||||||
|
|
||||||
execute_timings.details.per_program_timings.insert(
|
execute_timings.details.per_program_timings.insert(
|
||||||
program_key_1,
|
program_key_1,
|
||||||
@ -255,7 +258,7 @@ mod tests {
|
|||||||
let accumulated_units: u64 = 200;
|
let accumulated_units: u64 = 200;
|
||||||
let count: u32 = 10;
|
let count: u32 = 10;
|
||||||
// to expect new cost is Average(new_value, existing_value)
|
// to expect new cost is Average(new_value, existing_value)
|
||||||
expected_cost = ((accumulated_us / count as u64) + expected_cost) / 2;
|
expected_cost = ((accumulated_units / count as u64) + expected_cost) / 2;
|
||||||
|
|
||||||
execute_timings.details.per_program_timings.insert(
|
execute_timings.details.per_program_timings.insert(
|
||||||
program_key_1,
|
program_key_1,
|
||||||
|
Reference in New Issue
Block a user