mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-15 13:51:11 +00:00
contracts: Simplify benchmarks (#13595)
* Remove batching * Benchmark in bytes not kilobytes * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * Add rationale for picking batch numbers --------- Co-authored-by: command-bot <>
This commit is contained in:
committed by
GitHub
parent
3a3d93afee
commit
91bb2d29ca
@@ -512,7 +512,7 @@ pub fn max_pages<T: Config>() -> u32 {
|
|||||||
|
|
||||||
fn inject_gas_metering<T: Config>(module: Module) -> Module {
|
fn inject_gas_metering<T: Config>(module: Module) -> Module {
|
||||||
let schedule = T::Schedule::get();
|
let schedule = T::Schedule::get();
|
||||||
let gas_rules = schedule.rules(&module, Determinism::Deterministic);
|
let gas_rules = schedule.rules(Determinism::Deterministic);
|
||||||
let backend = gas_metering::host_function::Injector::new("seal0", "gas");
|
let backend = gas_metering::host_function::Injector::new("seal0", "gas");
|
||||||
gas_metering::inject(module, backend, &gas_rules).unwrap()
|
gas_metering::inject(module, backend, &gas_rules).unwrap()
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -27,18 +27,9 @@ use scale_info::TypeInfo;
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sp_runtime::RuntimeDebug;
|
use sp_runtime::RuntimeDebug;
|
||||||
use sp_std::{marker::PhantomData, vec::Vec};
|
use sp_std::marker::PhantomData;
|
||||||
use wasm_instrument::{gas_metering, parity_wasm::elements};
|
use wasm_instrument::{gas_metering, parity_wasm::elements};
|
||||||
|
|
||||||
/// How many API calls are executed in a single batch. The reason for increasing the amount
|
|
||||||
/// of API calls in batches (per benchmark component increase) is so that the linear regression
|
|
||||||
/// has an easier time determining the contribution of that component.
|
|
||||||
pub const API_BENCHMARK_BATCH_SIZE: u32 = 80;
|
|
||||||
|
|
||||||
/// How many instructions are executed in a single batch. The reasoning is the same
|
|
||||||
/// as for `API_BENCHMARK_BATCH_SIZE`.
|
|
||||||
pub const INSTR_BENCHMARK_BATCH_SIZE: u32 = 100;
|
|
||||||
|
|
||||||
/// Definition of the cost schedule and other parameterizations for the wasm vm.
|
/// Definition of the cost schedule and other parameterizations for the wasm vm.
|
||||||
///
|
///
|
||||||
/// Its [`Default`] implementation is the designated way to initialize this type. It uses
|
/// Its [`Default`] implementation is the designated way to initialize this type. It uses
|
||||||
@@ -200,7 +191,6 @@ pub struct InstructionWeights<T: Config> {
|
|||||||
pub br_table_per_entry: u32,
|
pub br_table_per_entry: u32,
|
||||||
pub call: u32,
|
pub call: u32,
|
||||||
pub call_indirect: u32,
|
pub call_indirect: u32,
|
||||||
pub call_indirect_per_param: u32,
|
|
||||||
pub call_per_local: u32,
|
pub call_per_local: u32,
|
||||||
pub local_get: u32,
|
pub local_get: u32,
|
||||||
pub local_set: u32,
|
pub local_set: u32,
|
||||||
@@ -451,66 +441,22 @@ macro_rules! cost_args {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! cost_batched_args {
|
macro_rules! cost_instr_no_params {
|
||||||
($name:ident, $( $arg: expr ),+) => {
|
($name:ident) => {
|
||||||
cost_args!($name, $( $arg ),+) / u64::from(API_BENCHMARK_BATCH_SIZE)
|
cost_args!($name, 1).ref_time() as u32
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! cost_instr_no_params_with_batch_size {
|
|
||||||
($name:ident, $batch_size:expr) => {
|
|
||||||
(cost_args!($name, 1).ref_time() / u64::from($batch_size)) as u32
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! cost_instr_with_batch_size {
|
|
||||||
($name:ident, $num_params:expr, $batch_size:expr) => {
|
|
||||||
cost_instr_no_params_with_batch_size!($name, $batch_size).saturating_sub(
|
|
||||||
(cost_instr_no_params_with_batch_size!(instr_i64const, $batch_size) / 2)
|
|
||||||
.saturating_mul($num_params),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! cost_instr {
|
|
||||||
($name:ident, $num_params:expr) => {
|
|
||||||
cost_instr_with_batch_size!($name, $num_params, INSTR_BENCHMARK_BATCH_SIZE)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! cost_byte_args {
|
|
||||||
($name:ident, $( $arg: expr ),+) => {
|
|
||||||
cost_args!($name, $( $arg ),+) / 1024
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! cost_byte_batched_args {
|
|
||||||
($name:ident, $( $arg: expr ),+) => {
|
|
||||||
cost_batched_args!($name, $( $arg ),+) / 1024
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! cost {
|
macro_rules! cost {
|
||||||
($name:ident) => {
|
($name:ident) => {
|
||||||
cost_args!($name, 1)
|
cost_args!($name, 1)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! cost_batched {
|
macro_rules! cost_instr {
|
||||||
($name:ident) => {
|
($name:ident, $num_params:expr) => {
|
||||||
cost_batched_args!($name, 1)
|
cost_instr_no_params!($name)
|
||||||
};
|
.saturating_sub((cost_instr_no_params!(instr_i64const) / 2).saturating_mul($num_params))
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! cost_byte {
|
|
||||||
($name:ident) => {
|
|
||||||
cost_byte_args!($name, 1)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! cost_byte_batched {
|
|
||||||
($name:ident) => {
|
|
||||||
cost_byte_batched_args!($name, 1)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,7 +479,6 @@ impl Default for Limits {
|
|||||||
|
|
||||||
impl<T: Config> Default for InstructionWeights<T> {
|
impl<T: Config> Default for InstructionWeights<T> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let max_pages = Limits::default().memory_pages;
|
|
||||||
Self {
|
Self {
|
||||||
version: 4,
|
version: 4,
|
||||||
fallback: 0,
|
fallback: 0,
|
||||||
@@ -548,7 +493,6 @@ impl<T: Config> Default for InstructionWeights<T> {
|
|||||||
br_table_per_entry: cost_instr!(instr_br_table_per_entry, 0),
|
br_table_per_entry: cost_instr!(instr_br_table_per_entry, 0),
|
||||||
call: cost_instr!(instr_call, 2),
|
call: cost_instr!(instr_call, 2),
|
||||||
call_indirect: cost_instr!(instr_call_indirect, 3),
|
call_indirect: cost_instr!(instr_call_indirect, 3),
|
||||||
call_indirect_per_param: cost_instr!(instr_call_indirect_per_param, 0),
|
|
||||||
call_per_local: cost_instr!(instr_call_per_local, 0),
|
call_per_local: cost_instr!(instr_call_per_local, 0),
|
||||||
local_get: cost_instr!(instr_local_get, 1),
|
local_get: cost_instr!(instr_local_get, 1),
|
||||||
local_set: cost_instr!(instr_local_set, 1),
|
local_set: cost_instr!(instr_local_set, 1),
|
||||||
@@ -556,7 +500,7 @@ impl<T: Config> Default for InstructionWeights<T> {
|
|||||||
global_get: cost_instr!(instr_global_get, 1),
|
global_get: cost_instr!(instr_global_get, 1),
|
||||||
global_set: cost_instr!(instr_global_set, 1),
|
global_set: cost_instr!(instr_global_set, 1),
|
||||||
memory_current: cost_instr!(instr_memory_current, 1),
|
memory_current: cost_instr!(instr_memory_current, 1),
|
||||||
memory_grow: cost_instr_with_batch_size!(instr_memory_grow, 1, max_pages),
|
memory_grow: cost_instr!(instr_memory_grow, 1),
|
||||||
i64clz: cost_instr!(instr_i64clz, 2),
|
i64clz: cost_instr!(instr_i64clz, 2),
|
||||||
i64ctz: cost_instr!(instr_i64ctz, 2),
|
i64ctz: cost_instr!(instr_i64ctz, 2),
|
||||||
i64popcnt: cost_instr!(instr_i64popcnt, 2),
|
i64popcnt: cost_instr!(instr_i64popcnt, 2),
|
||||||
@@ -597,89 +541,85 @@ impl<T: Config> Default for InstructionWeights<T> {
|
|||||||
impl<T: Config> Default for HostFnWeights<T> {
|
impl<T: Config> Default for HostFnWeights<T> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
caller: cost_batched!(seal_caller),
|
caller: cost!(seal_caller),
|
||||||
is_contract: cost_batched!(seal_is_contract),
|
is_contract: cost!(seal_is_contract),
|
||||||
code_hash: cost_batched!(seal_code_hash),
|
code_hash: cost!(seal_code_hash),
|
||||||
own_code_hash: cost_batched!(seal_own_code_hash),
|
own_code_hash: cost!(seal_own_code_hash),
|
||||||
caller_is_origin: cost_batched!(seal_caller_is_origin),
|
caller_is_origin: cost!(seal_caller_is_origin),
|
||||||
address: cost_batched!(seal_address),
|
address: cost!(seal_address),
|
||||||
gas_left: cost_batched!(seal_gas_left),
|
gas_left: cost!(seal_gas_left),
|
||||||
balance: cost_batched!(seal_balance),
|
balance: cost!(seal_balance),
|
||||||
value_transferred: cost_batched!(seal_value_transferred),
|
value_transferred: cost!(seal_value_transferred),
|
||||||
minimum_balance: cost_batched!(seal_minimum_balance),
|
minimum_balance: cost!(seal_minimum_balance),
|
||||||
block_number: cost_batched!(seal_block_number),
|
block_number: cost!(seal_block_number),
|
||||||
now: cost_batched!(seal_now),
|
now: cost!(seal_now),
|
||||||
weight_to_fee: cost_batched!(seal_weight_to_fee),
|
weight_to_fee: cost!(seal_weight_to_fee),
|
||||||
// Manually remove proof size from basic block cost.
|
// Manually remove proof size from basic block cost.
|
||||||
//
|
//
|
||||||
// Due to imperfect benchmarking some host functions incur a small
|
// Due to imperfect benchmarking some host functions incur a small
|
||||||
// amount of proof size. Usually this is ok. However, charging a basic block is such
|
// amount of proof size. Usually this is ok. However, charging a basic block is such
|
||||||
// a frequent operation that this would be a vast overestimation.
|
// a frequent operation that this would be a vast overestimation.
|
||||||
gas: cost_batched!(seal_gas).set_proof_size(0),
|
gas: cost!(seal_gas).set_proof_size(0),
|
||||||
input: cost_batched!(seal_input),
|
input: cost!(seal_input),
|
||||||
input_per_byte: cost_byte_batched!(seal_input_per_kb),
|
input_per_byte: cost!(seal_input_per_byte),
|
||||||
r#return: cost!(seal_return),
|
r#return: cost!(seal_return),
|
||||||
return_per_byte: cost_byte!(seal_return_per_kb),
|
return_per_byte: cost!(seal_return_per_byte),
|
||||||
terminate: cost!(seal_terminate),
|
terminate: cost!(seal_terminate),
|
||||||
random: cost_batched!(seal_random),
|
random: cost!(seal_random),
|
||||||
deposit_event: cost_batched!(seal_deposit_event),
|
deposit_event: cost!(seal_deposit_event),
|
||||||
deposit_event_per_topic: cost_batched_args!(seal_deposit_event_per_topic_and_kb, 1, 0),
|
deposit_event_per_topic: cost_args!(seal_deposit_event_per_topic_and_byte, 1, 0),
|
||||||
deposit_event_per_byte: cost_byte_batched_args!(
|
deposit_event_per_byte: cost_args!(seal_deposit_event_per_topic_and_byte, 0, 1),
|
||||||
seal_deposit_event_per_topic_and_kb,
|
debug_message: cost!(seal_debug_message),
|
||||||
0,
|
debug_message_per_byte: cost!(seal_debug_message_per_byte),
|
||||||
1
|
set_storage: cost!(seal_set_storage),
|
||||||
),
|
set_code_hash: cost!(seal_set_code_hash),
|
||||||
debug_message: cost_batched!(seal_debug_message),
|
set_storage_per_new_byte: cost!(seal_set_storage_per_new_byte),
|
||||||
debug_message_per_byte: cost_byte!(seal_debug_message_per_kb),
|
set_storage_per_old_byte: cost!(seal_set_storage_per_old_byte),
|
||||||
set_storage: cost_batched!(seal_set_storage),
|
clear_storage: cost!(seal_clear_storage),
|
||||||
set_code_hash: cost_batched!(seal_set_code_hash),
|
clear_storage_per_byte: cost!(seal_clear_storage_per_byte),
|
||||||
set_storage_per_new_byte: cost_byte_batched!(seal_set_storage_per_new_kb),
|
contains_storage: cost!(seal_contains_storage),
|
||||||
set_storage_per_old_byte: cost_byte_batched!(seal_set_storage_per_old_kb),
|
contains_storage_per_byte: cost!(seal_contains_storage_per_byte),
|
||||||
clear_storage: cost_batched!(seal_clear_storage),
|
get_storage: cost!(seal_get_storage),
|
||||||
clear_storage_per_byte: cost_byte_batched!(seal_clear_storage_per_kb),
|
get_storage_per_byte: cost!(seal_get_storage_per_byte),
|
||||||
contains_storage: cost_batched!(seal_contains_storage),
|
take_storage: cost!(seal_take_storage),
|
||||||
contains_storage_per_byte: cost_byte_batched!(seal_contains_storage_per_kb),
|
take_storage_per_byte: cost!(seal_take_storage_per_byte),
|
||||||
get_storage: cost_batched!(seal_get_storage),
|
transfer: cost!(seal_transfer),
|
||||||
get_storage_per_byte: cost_byte_batched!(seal_get_storage_per_kb),
|
call: cost!(seal_call),
|
||||||
take_storage: cost_batched!(seal_take_storage),
|
delegate_call: cost!(seal_delegate_call),
|
||||||
take_storage_per_byte: cost_byte_batched!(seal_take_storage_per_kb),
|
call_transfer_surcharge: cost_args!(seal_call_per_transfer_clone_byte, 1, 0),
|
||||||
transfer: cost_batched!(seal_transfer),
|
call_per_cloned_byte: cost_args!(seal_call_per_transfer_clone_byte, 0, 1),
|
||||||
call: cost_batched!(seal_call),
|
instantiate: cost!(seal_instantiate),
|
||||||
delegate_call: cost_batched!(seal_delegate_call),
|
instantiate_transfer_surcharge: cost_args!(
|
||||||
call_transfer_surcharge: cost_batched_args!(seal_call_per_transfer_clone_kb, 1, 0),
|
seal_instantiate_per_transfer_input_salt_byte,
|
||||||
call_per_cloned_byte: cost_byte_batched_args!(seal_call_per_transfer_clone_kb, 0, 1),
|
|
||||||
instantiate: cost_batched!(seal_instantiate),
|
|
||||||
instantiate_transfer_surcharge: cost_batched_args!(
|
|
||||||
seal_instantiate_per_transfer_input_salt_kb,
|
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
0
|
0
|
||||||
),
|
),
|
||||||
instantiate_per_input_byte: cost_byte_batched_args!(
|
instantiate_per_input_byte: cost_args!(
|
||||||
seal_instantiate_per_transfer_input_salt_kb,
|
seal_instantiate_per_transfer_input_salt_byte,
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
0
|
0
|
||||||
),
|
),
|
||||||
instantiate_per_salt_byte: cost_byte_batched_args!(
|
instantiate_per_salt_byte: cost_args!(
|
||||||
seal_instantiate_per_transfer_input_salt_kb,
|
seal_instantiate_per_transfer_input_salt_byte,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
1
|
1
|
||||||
),
|
),
|
||||||
hash_sha2_256: cost_batched!(seal_hash_sha2_256),
|
hash_sha2_256: cost!(seal_hash_sha2_256),
|
||||||
hash_sha2_256_per_byte: cost_byte_batched!(seal_hash_sha2_256_per_kb),
|
hash_sha2_256_per_byte: cost!(seal_hash_sha2_256_per_byte),
|
||||||
hash_keccak_256: cost_batched!(seal_hash_keccak_256),
|
hash_keccak_256: cost!(seal_hash_keccak_256),
|
||||||
hash_keccak_256_per_byte: cost_byte_batched!(seal_hash_keccak_256_per_kb),
|
hash_keccak_256_per_byte: cost!(seal_hash_keccak_256_per_byte),
|
||||||
hash_blake2_256: cost_batched!(seal_hash_blake2_256),
|
hash_blake2_256: cost!(seal_hash_blake2_256),
|
||||||
hash_blake2_256_per_byte: cost_byte_batched!(seal_hash_blake2_256_per_kb),
|
hash_blake2_256_per_byte: cost!(seal_hash_blake2_256_per_byte),
|
||||||
hash_blake2_128: cost_batched!(seal_hash_blake2_128),
|
hash_blake2_128: cost!(seal_hash_blake2_128),
|
||||||
hash_blake2_128_per_byte: cost_byte_batched!(seal_hash_blake2_128_per_kb),
|
hash_blake2_128_per_byte: cost!(seal_hash_blake2_128_per_byte),
|
||||||
ecdsa_recover: cost_batched!(seal_ecdsa_recover),
|
ecdsa_recover: cost!(seal_ecdsa_recover),
|
||||||
ecdsa_to_eth_address: cost_batched!(seal_ecdsa_to_eth_address),
|
ecdsa_to_eth_address: cost!(seal_ecdsa_to_eth_address),
|
||||||
reentrance_count: cost_batched!(seal_reentrance_count),
|
reentrance_count: cost!(seal_reentrance_count),
|
||||||
account_reentrance_count: cost_batched!(seal_account_reentrance_count),
|
account_reentrance_count: cost!(seal_account_reentrance_count),
|
||||||
instantiation_nonce: cost_batched!(seal_instantiation_nonce),
|
instantiation_nonce: cost!(seal_instantiation_nonce),
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -687,29 +627,12 @@ impl<T: Config> Default for HostFnWeights<T> {
|
|||||||
|
|
||||||
struct ScheduleRules<'a, T: Config> {
|
struct ScheduleRules<'a, T: Config> {
|
||||||
schedule: &'a Schedule<T>,
|
schedule: &'a Schedule<T>,
|
||||||
params: Vec<u32>,
|
|
||||||
determinism: Determinism,
|
determinism: Determinism,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Config> Schedule<T> {
|
impl<T: Config> Schedule<T> {
|
||||||
pub(crate) fn rules(
|
pub(crate) fn rules(&self, determinism: Determinism) -> impl gas_metering::Rules + '_ {
|
||||||
&self,
|
ScheduleRules { schedule: self, determinism }
|
||||||
module: &elements::Module,
|
|
||||||
determinism: Determinism,
|
|
||||||
) -> impl gas_metering::Rules + '_ {
|
|
||||||
ScheduleRules {
|
|
||||||
schedule: self,
|
|
||||||
params: module
|
|
||||||
.type_section()
|
|
||||||
.iter()
|
|
||||||
.flat_map(|section| section.types())
|
|
||||||
.map(|func| {
|
|
||||||
let elements::Type::Function(func) = func;
|
|
||||||
func.params().len() as u32
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
determinism,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -717,7 +640,6 @@ impl<'a, T: Config> gas_metering::Rules for ScheduleRules<'a, T> {
|
|||||||
fn instruction_cost(&self, instruction: &elements::Instruction) -> Option<u32> {
|
fn instruction_cost(&self, instruction: &elements::Instruction) -> Option<u32> {
|
||||||
use self::elements::Instruction::*;
|
use self::elements::Instruction::*;
|
||||||
let w = &self.schedule.instruction_weights;
|
let w = &self.schedule.instruction_weights;
|
||||||
let max_params = self.schedule.limits.parameters;
|
|
||||||
|
|
||||||
let weight = match *instruction {
|
let weight = match *instruction {
|
||||||
End | Unreachable | Return | Else => 0,
|
End | Unreachable | Return | Else => 0,
|
||||||
@@ -753,7 +675,7 @@ impl<'a, T: Config> gas_metering::Rules for ScheduleRules<'a, T> {
|
|||||||
SetGlobal(_) => w.global_set,
|
SetGlobal(_) => w.global_set,
|
||||||
CurrentMemory(_) => w.memory_current,
|
CurrentMemory(_) => w.memory_current,
|
||||||
GrowMemory(_) => w.memory_grow,
|
GrowMemory(_) => w.memory_grow,
|
||||||
CallIndirect(idx, _) => *self.params.get(idx as usize).unwrap_or(&max_params),
|
CallIndirect(_, _) => w.call_indirect,
|
||||||
BrTable(ref data) => w
|
BrTable(ref data) => w
|
||||||
.br_table
|
.br_table
|
||||||
.saturating_add(w.br_table_per_entry.saturating_mul(data.table.len() as u32)),
|
.saturating_add(w.br_table_per_entry.saturating_mul(data.table.len() as u32)),
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ impl<'a, T: Config> ContractModule<'a, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn inject_gas_metering(self, determinism: Determinism) -> Result<Self, &'static str> {
|
fn inject_gas_metering(self, determinism: Determinism) -> Result<Self, &'static str> {
|
||||||
let gas_rules = self.schedule.rules(&self.module, determinism);
|
let gas_rules = self.schedule.rules(determinism);
|
||||||
let backend = gas_metering::host_function::Injector::new("seal0", "gas");
|
let backend = gas_metering::host_function::Injector::new("seal0", "gas");
|
||||||
let contract_module = gas_metering::inject(self.module, backend, &gas_rules)
|
let contract_module = gas_metering::inject(self.module, backend, &gas_rules)
|
||||||
.map_err(|_| "gas instrumentation failed")?;
|
.map_err(|_| "gas instrumentation failed")?;
|
||||||
|
|||||||
+1634
-1689
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user