From 73817f448a7211964b125354fd87ec00e35dd6d0 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Sat, 26 Feb 2022 17:07:10 +0000 Subject: [PATCH] test: upgrade benchmarks for new substrate --- --- a/.maintain/frame-weight-template.hbs +++ b/.maintain/frame-weight-template.hbs @@ -7,7 +7,7 @@ //! EXECUTION: {{cmd.execution}}, WASM-EXECUTION: {{cmd.wasm_execution}}, CHAIN: {{cmd.chain}}, DB CACHE: {{cmd.db_cache}} // Executed Command: -{{#each args as |arg|~}} +{{#each args as |arg|}} // {{arg}} {{/each}} @@ -21,76 +21,80 @@ /// Weight functions needed for {{pallet}}. pub trait WeightInfo { - {{~#each benchmarks as |benchmark|}} + {{#each benchmarks as |benchmark|}} fn {{benchmark.name~}} ( {{~#each benchmark.components as |c| ~}} {{c.name}}: u32, {{/each~}} ) -> Weight; - {{~/each}} + {{/each}} } /// Weights for {{pallet}} using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); +{{#if (eq pallet "frame_system")}} +impl WeightInfo for SubstrateWeight { +{{else}} impl WeightInfo for SubstrateWeight { - {{~#each benchmarks as |benchmark|}} - {{~#each benchmark.comments as |comment|}} +{{/if}} + {{#each benchmarks as |benchmark|}} + {{#each benchmark.comments as |comment|}} // {{comment}} - {{~/each}} + {{/each}} fn {{benchmark.name~}} ( {{~#each benchmark.components as |c| ~}} {{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}} ) -> Weight { ({{underscore benchmark.base_weight}} as Weight) - {{~#each benchmark.component_weight as |cw|}} + {{#each benchmark.component_weight as |cw|}} // Standard Error: {{underscore cw.error}} .saturating_add(({{underscore cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight)) - {{~/each}} - {{~#if (ne benchmark.base_reads "0")}} + {{/each}} + {{#if (ne benchmark.base_reads "0")}} .saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}} as Weight)) - {{~/if}} - {{~#each benchmark.component_reads as |cr|}} + {{/if}} + {{#each benchmark.component_reads as |cr|}} .saturating_add(T::DbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as Weight))) - {{~/each}} - {{~#if (ne benchmark.base_writes "0")}} + {{/each}} + {{#if (ne benchmark.base_writes "0")}} .saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}} as Weight)) - {{~/if}} - {{~#each benchmark.component_writes as |cw|}} + {{/if}} + {{#each benchmark.component_writes as |cw|}} .saturating_add(T::DbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight))) - {{~/each}} + {{/each}} } - {{~/each}} + {{/each}} } // For backwards compatibility and tests impl WeightInfo for () { - {{~#each benchmarks as |benchmark|}} - {{~#each benchmark.comments as |comment|}} + {{#each benchmarks as |benchmark|}} + {{#each benchmark.comments as |comment|}} // {{comment}} - {{~/each}} + {{/each}} fn {{benchmark.name~}} ( {{~#each benchmark.components as |c| ~}} {{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}} ) -> Weight { ({{underscore benchmark.base_weight}} as Weight) - {{~#each benchmark.component_weight as |cw|}} + {{#each benchmark.component_weight as |cw|}} // Standard Error: {{underscore cw.error}} .saturating_add(({{underscore cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight)) - {{~/each}} - {{~#if (ne benchmark.base_reads "0")}} + {{/each}} + {{#if (ne benchmark.base_reads "0")}} .saturating_add(RocksDbWeight::get().reads({{benchmark.base_reads}} as Weight)) - {{~/if}} - {{~#each benchmark.component_reads as |cr|}} + {{/if}} + {{#each benchmark.component_reads as |cr|}} .saturating_add(RocksDbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as Weight))) - {{~/each}} - {{~#if (ne benchmark.base_writes "0")}} + {{/each}} + {{#if (ne benchmark.base_writes "0")}} .saturating_add(RocksDbWeight::get().writes({{benchmark.base_writes}} as Weight)) - {{~/if}} - {{~#each benchmark.component_writes as |cw|}} + {{/if}} + {{#each benchmark.component_writes as |cw|}} .saturating_add(RocksDbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight))) - {{~/each}} + {{/each}} } - {{~/each}} + {{/each}} } --- a/pallets/common/src/benchmarking.rs +++ b/pallets/common/src/benchmarking.rs @@ -1,64 +1,87 @@ use sp_std::vec::Vec; use crate::{Config, CollectionHandle}; use up_data_structs::{ - CollectionMode, Collection, CollectionId, MAX_COLLECTION_NAME_LENGTH, + CollectionMode, CreateCollectionData, CollectionId, MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH, OFFCHAIN_SCHEMA_LIMIT, VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, }; -use frame_support::traits::{Currency, Get}; +use frame_support::{ + traits::{Currency, Get}, + pallet_prelude::ConstU32, + BoundedVec, +}; use core::convert::TryInto; use sp_runtime::DispatchError; -pub fn create_data(size: usize) -> Vec { - (0..size).map(|v| (v & 0xff) as u8).collect() +pub fn create_data() -> BoundedVec> { + create_var_data::(S) } -pub fn create_u16_data(size: usize) -> Vec { - (0..size).map(|v| (v & 0xffff) as u16).collect() +pub fn create_u16_data() -> BoundedVec> { + (0..S) + .map(|v| (v & 0xffff) as u16) + .collect::>() + .try_into() + .unwrap() +} +pub fn create_var_data(size: u32) -> BoundedVec> { + assert!( + size <= S, + "size ({}) should be less within bound ({})", + size, + S + ); + (0..size) + .map(|v| (v & 0xff) as u8) + .collect::>() + .try_into() + .unwrap() } pub fn create_collection_raw( owner: T::AccountId, mode: CollectionMode, - handler: impl FnOnce(Collection) -> Result, + handler: impl FnOnce( + T::AccountId, + CreateCollectionData, + ) -> Result, cast: impl FnOnce(CollectionHandle) -> R, ) -> Result { T::Currency::deposit_creating(&owner, T::CollectionCreationPrice::get()); - let name = create_u16_data(MAX_COLLECTION_NAME_LENGTH) - .try_into() - .unwrap(); - let description = create_u16_data(MAX_COLLECTION_DESCRIPTION_LENGTH) - .try_into() - .unwrap(); - let token_prefix = create_data(MAX_TOKEN_PREFIX_LENGTH).try_into().unwrap(); - let offchain_schema = create_data(OFFCHAIN_SCHEMA_LIMIT as usize) - .try_into() - .unwrap(); - let variable_on_chain_schema = create_data(VARIABLE_ON_CHAIN_SCHEMA_LIMIT as usize) - .try_into() - .unwrap(); - let const_on_chain_schema = create_data(CONST_ON_CHAIN_SCHEMA_LIMIT as usize) - .try_into() - .unwrap(); - handler(Collection { + let name = create_u16_data::(); + let description = create_u16_data::(); + let token_prefix = create_data::(); + let offchain_schema = create_data::(); + let variable_on_chain_schema = create_data::(); + let const_on_chain_schema = create_data::(); + handler( owner, - mode, - access: Default::default(), - name, - description, - token_prefix, - mint_mode: true, - offchain_schema, - schema_version: Default::default(), - sponsorship: Default::default(), - limits: Default::default(), - variable_on_chain_schema, - const_on_chain_schema, - meta_update_permission: Default::default(), - }) + CreateCollectionData { + mode, + name, + description, + token_prefix, + offchain_schema, + variable_on_chain_schema, + const_on_chain_schema, + ..Default::default() + }, + ) .and_then(CollectionHandle::try_get) .map(cast) } +/// Helper macros, which handles all benchmarking preparation in semi-declarative way +/// +/// `name` is a substrate account +/// - name: sub[(id)] +/// `name` is a collection with owner `owner` +/// - name: collection(owner) +/// `name` is a cross account based on substrate +/// - name: cross_sub[(id)] +/// `name` is a cross account, which maps to substrate account `name` +/// - name: cross_from_sub +/// `name` is a cross account, which maps to substrate account `other_name` +/// - name: cross_from_sub(other_name) #[macro_export] macro_rules! bench_init { ($name:ident: sub $(($id:expr))?; $($rest:tt)*) => { --- a/pallets/fungible/src/common.rs +++ b/pallets/fungible/src/common.rs @@ -12,7 +12,7 @@ }; pub struct CommonWeights(PhantomData); -impl CommonWeightInfo for CommonWeights { +impl CommonWeightInfo for CommonWeights { fn create_item() -> Weight { >::create_item() } --- a/pallets/fungible/src/lib.rs +++ b/pallets/fungible/src/lib.rs @@ -9,7 +9,7 @@ use pallet_evm_coder_substrate::WithRecorder; use sp_core::H160; use sp_runtime::{ArithmeticError, DispatchError, DispatchResult}; -use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap}; +use sp_std::collections::btree_map::BTreeMap; pub use pallet::*; @@ -222,7 +222,7 @@ pub fn create_multiple_items( collection: &FungibleHandle, sender: &T::CrossAccountId, - data: Vec>, + data: BTreeMap, ) -> DispatchResult { if !collection.is_owner_or_admin(sender) { ensure!( @@ -236,22 +236,18 @@ } } - let mut balances = BTreeMap::new(); - let total_supply = data .iter() - .map(|u| u.1) + .map(|(_, v)| *v) .try_fold(>::get(collection.id), |acc, v| { acc.checked_add(v) }) .ok_or(ArithmeticError::Overflow)?; - for (user, amount) in data.into_iter() { - let balance = balances - .entry(user.clone()) - .or_insert_with(|| >::get((collection.id, user))); - *balance = (*balance) - .checked_add(amount) + let mut balances = data; + for (k, v) in balances.iter_mut() { + *v = >::get((collection.id, &k)) + .checked_add(*v) .ok_or(ArithmeticError::Overflow)?; } --- a/pallets/inflation/src/benchmarking.rs +++ b/pallets/inflation/src/benchmarking.rs @@ -1,7 +1,7 @@ #![cfg(feature = "runtime-benchmarks")] use super::*; -use crate::Module as Inflation; +use crate::Pallet as Inflation; use frame_benchmarking::{benchmarks}; use frame_support::traits::OnInitialize; --- a/pallets/nonfungible/src/benchmarking.rs +++ b/pallets/nonfungible/src/benchmarking.rs @@ -2,18 +2,18 @@ use crate::{Pallet, Config, NonfungibleHandle}; use sp_std::prelude::*; -use pallet_common::benchmarking::{create_collection_raw, create_data}; +use pallet_common::benchmarking::{create_collection_raw, create_data, create_var_data}; use frame_benchmarking::{benchmarks, account}; -use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH}; +use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH, CUSTOM_DATA_LIMIT}; use pallet_common::bench_init; use core::convert::TryInto; const SEED: u32 = 1; fn create_max_item_data(owner: T::CrossAccountId) -> CreateItemData { - let const_data = create_data(CUSTOM_DATA_LIMIT as usize).try_into().unwrap(); - let variable_data = create_data(CUSTOM_DATA_LIMIT as usize).try_into().unwrap(); - CreateItemData { + let const_data = create_data::(); + let variable_data = create_data::(); + CreateItemData:: { const_data, variable_data, owner, @@ -24,7 +24,7 @@ sender: &T::CrossAccountId, owner: T::CrossAccountId, ) -> Result { - >::create_item(&collection, sender, create_max_item_data(owner))?; + >::create_item(&collection, sender, create_max_item_data::(owner))?; Ok(TokenId(>::get(&collection.id))) } @@ -53,7 +53,9 @@ owner: sub; collection: collection(owner); sender: cross_from_sub(owner); to: cross_sub; }; - let data = (0..b).map(|_| create_max_item_data(to.clone())).collect(); + let data = (0..b).map(|_| create_max_item_data::(to.clone())).collect(); + }: {>::create_multiple_items(&collection, &sender, data)?} + }: {>::create_multiple_items(&collection, &sender, data)?} burn_item { @@ -105,6 +107,6 @@ owner: cross_from_sub; sender: cross_sub; }; let item = create_max_item(&collection, &owner, sender.clone())?; - let data = create_data(b as usize); + let data = create_var_data(b).try_into().unwrap(); }: {>::set_variable_metadata(&collection, &sender, item, data)?} } --- a/pallets/nonfungible/src/common.rs +++ b/pallets/nonfungible/src/common.rs @@ -12,7 +12,7 @@ }; pub struct CommonWeights(PhantomData); -impl CommonWeightInfo for CommonWeights { +impl CommonWeightInfo for CommonWeights { fn create_item() -> Weight { >::create_item() } @@ -51,7 +51,7 @@ to: &T::CrossAccountId, ) -> Result, DispatchError> { match data { - up_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData { + up_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData:: { const_data: data.const_data, variable_data: data.variable_data, owner: to.clone(), @@ -68,7 +68,7 @@ data: up_data_structs::CreateItemData, ) -> DispatchResultWithPostInfo { with_weight( - >::create_item(self, &sender, map_create_data(data, &to)?), + >::create_item(self, &sender, map_create_data::(data, &to)?), >::create_item(), ) } --- a/pallets/nonfungible/src/erc.rs +++ b/pallets/nonfungible/src/erc.rs @@ -232,7 +232,7 @@ >::create_item( self, &caller, - CreateItemData { + CreateItemData:: { const_data: BoundedVec::default(), variable_data: BoundedVec::default(), owner: to, @@ -268,7 +268,7 @@ >::create_item( self, &caller, - CreateItemData { + CreateItemData:: { const_data: Vec::::from(token_uri) .try_into() .map_err(|_| "token uri is too long")?, @@ -376,7 +376,7 @@ expected_index = expected_index.checked_add(1).ok_or("item id overflow")?; } let data = (0..total_tokens) - .map(|_| CreateItemData { + .map(|_| CreateItemData:: { const_data: BoundedVec::default(), variable_data: BoundedVec::default(), owner: to.clone(), @@ -409,7 +409,7 @@ } expected_index = expected_index.checked_add(1).ok_or("item id overflow")?; - data.push(CreateItemData { + data.push(CreateItemData:: { const_data: Vec::::from(token_uri) .try_into() .map_err(|_| "token uri is too long")?, --- a/pallets/refungible/src/benchmarking.rs +++ b/pallets/refungible/src/benchmarking.rs @@ -2,24 +2,28 @@ use crate::{Pallet, Config, RefungibleHandle}; use sp_std::prelude::*; -use pallet_common::benchmarking::{create_collection_raw, create_data}; +use pallet_common::benchmarking::{create_collection_raw, create_data, create_var_data}; use frame_benchmarking::{benchmarks, account}; -use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH}; +use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH, CUSTOM_DATA_LIMIT}; use pallet_common::bench_init; use core::convert::TryInto; use core::iter::IntoIterator; const SEED: u32 = 1; -fn create_max_item_data( - users: impl IntoIterator, -) -> CreateItemData { - let const_data = create_data(CUSTOM_DATA_LIMIT as usize).try_into().unwrap(); - let variable_data = create_data(CUSTOM_DATA_LIMIT as usize).try_into().unwrap(); - CreateItemData { +fn create_max_item_data( + users: impl IntoIterator, +) -> CreateRefungibleExData { + let const_data = create_data::(); + let variable_data = create_data::(); + CreateRefungibleExData { const_data, variable_data, - users: users.into_iter().collect(), + users: users + .into_iter() + .collect::>() + .try_into() + .unwrap(), } } fn create_max_item( --- a/pallets/refungible/src/common.rs +++ b/pallets/refungible/src/common.rs @@ -8,8 +8,8 @@ use sp_std::vec::Vec; use crate::{ - AccountBalance, Allowance, Balance, Config, CreateItemData, Error, Owned, Pallet, - RefungibleHandle, SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted, + AccountBalance, Allowance, Balance, Config, Error, Owned, Pallet, RefungibleHandle, + SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted, }; macro_rules! max_weight_of { @@ -22,7 +22,7 @@ } pub struct CommonWeights(PhantomData); -impl CommonWeightInfo for CommonWeights { +impl CommonWeightInfo for CommonWeights { fn create_item() -> Weight { >::create_item() } --- a/pallets/unique/src/benchmarking.rs +++ b/pallets/unique/src/benchmarking.rs @@ -5,9 +5,8 @@ use frame_system::RawOrigin; use frame_benchmarking::{benchmarks, account}; use up_data_structs::*; -use core::convert::TryInto; use sp_runtime::DispatchError; -use pallet_common::benchmarking::{create_data, create_u16_data}; +use pallet_common::benchmarking::{create_data, create_var_data, create_u16_data}; const SEED: u32 = 1; @@ -16,13 +15,9 @@ mode: CollectionMode, ) -> Result { T::Currency::deposit_creating(&owner, T::CollectionCreationPrice::get()); - let col_name = create_u16_data(MAX_COLLECTION_NAME_LENGTH) - .try_into() - .unwrap(); - let col_desc = create_u16_data(MAX_COLLECTION_DESCRIPTION_LENGTH) - .try_into() - .unwrap(); - let token_prefix = create_data(MAX_TOKEN_PREFIX_LENGTH).try_into().unwrap(); + let col_name = create_u16_data::(); + let col_desc = create_u16_data::(); + let token_prefix = create_data::(); >::create_collection( RawOrigin::Signed(owner).into(), col_name, @@ -37,11 +32,10 @@ } benchmarks! { - create_collection { - let col_name: Vec = create_u16_data(MAX_COLLECTION_NAME_LENGTH); - let col_desc: Vec = create_u16_data(MAX_COLLECTION_DESCRIPTION_LENGTH); - let token_prefix: Vec = create_data(MAX_TOKEN_PREFIX_LENGTH); + let col_name = create_u16_data::(); + let col_desc = create_u16_data::(); + let token_prefix = create_data::(); let mode: CollectionMode = CollectionMode::NFT; let caller: T::AccountId = account("caller", 0, SEED); T::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get()); @@ -125,7 +119,7 @@ let caller: T::AccountId = account("caller", 0, SEED); let collection = create_nft_collection::(caller.clone())?; - let data = create_data(b as usize); + let data = create_var_data(b); }: set_offchain_schema(RawOrigin::Signed(caller.clone()), collection, data) set_const_on_chain_schema { @@ -133,7 +127,7 @@ let caller: T::AccountId = account("caller", 0, SEED); let collection = create_nft_collection::(caller.clone())?; - let data = create_data(b as usize); + let data = create_var_data(b); }: set_const_on_chain_schema(RawOrigin::Signed(caller.clone()), collection, data) set_variable_on_chain_schema { @@ -141,7 +135,7 @@ let caller: T::AccountId = account("caller", 0, SEED); let collection = create_nft_collection::(caller.clone())?; - let data = create_data(b as usize); + let data = create_var_data(b); }: set_variable_on_chain_schema(RawOrigin::Signed(caller.clone()), collection, data) set_schema_version { --- a/primitives/data-structs/src/lib.rs +++ b/primitives/data-structs/src/lib.rs @@ -76,9 +76,7 @@ /// create_many call pub const MAX_ITEMS_PER_BATCH: u32 = 200; -parameter_types! { - pub const CustomDataLimit: u32 = CUSTOM_DATA_LIMIT; -} +pub type CustomDataLimit = ConstU32; #[derive( Encode, @@ -417,15 +415,72 @@ } } +fn bounded_debug(v: &BoundedVec, f: &mut fmt::Formatter) -> Result<(), fmt::Error> +where + V: fmt::Debug, +{ + use core::fmt::Debug; + (&v as &Vec).fmt(f) +} + +#[cfg(feature = "serde1")] +#[allow(dead_code)] +mod bounded_map_serde { + use core::convert::TryFrom; + use sp_std::collections::btree_map::BTreeMap; + use frame_support::{traits::Get, storage::bounded_btree_map::BoundedBTreeMap}; + use serde::{ + ser::{self, Serialize}, + de::{self, Deserialize, Error}, + }; + pub fn serialize( + value: &BoundedBTreeMap, + serializer: D, + ) -> Result + where + D: ser::Serializer, + K: Serialize + Ord, + V: Serialize, + { + (value as &BTreeMap<_, _>).serialize(serializer) + } + + pub fn deserialize<'de, D, K, V, S>( + deserializer: D, + ) -> Result, D::Error> + where + D: de::Deserializer<'de>, + K: de::Deserialize<'de> + Ord, + V: de::Deserialize<'de>, + S: Get, + { + let map = >::deserialize(deserializer)?; + let len = map.len(); + TryFrom::try_from(map).map_err(|_| D::Error::invalid_length(len, &"lesser size")) + } +} + +fn bounded_map_debug( + v: &BoundedBTreeMap, + f: &mut fmt::Formatter, +) -> Result<(), fmt::Error> +where + K: fmt::Debug + Ord, + V: fmt::Debug, +{ + use core::fmt::Debug; + (&v as &BTreeMap).fmt(f) +} + #[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)] #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))] #[derivative(Debug)] pub struct CreateNftData { #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))] - #[derivative(Debug = "ignore")] + #[derivative(Debug(format_with = "bounded_debug"))] pub const_data: BoundedVec, #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))] - #[derivative(Debug = "ignore")] + #[derivative(Debug(format_with = "bounded_debug"))] pub variable_data: BoundedVec, } @@ -440,10 +495,10 @@ #[derivative(Debug)] pub struct CreateReFungibleData { #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))] - #[derivative(Debug = "ignore")] + #[derivative(Debug(format_with = "bounded_debug"))] pub const_data: BoundedVec, #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))] - #[derivative(Debug = "ignore")] + #[derivative(Debug(format_with = "bounded_debug"))] pub variable_data: BoundedVec, pub pieces: u128, } -- gitstuff