--- a/pallets/nonfungible/Cargo.toml +++ b/pallets/nonfungible/Cargo.toml @@ -20,6 +20,7 @@ evm-coder = { default-features = false, path = '../../crates/evm-coder' } pallet-evm-coder-substrate = { default-features = false, path = '../evm-coder-substrate' } ethereum = { default-features = false, version = "0.9.0" } +frame-benchmarking = { default-features = false, optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.10' } [features] default = ["std"] @@ -33,5 +34,10 @@ "evm-coder/std", "ethereum/std", "pallet-evm-coder-substrate/std", + 'frame-benchmarking/std', +] +runtime-benchmarks = [ + 'frame-benchmarking', + 'frame-support/runtime-benchmarks', + 'frame-system/runtime-benchmarks', ] -runtime-benchmarks = [] --- a/pallets/nonfungible/src/benchmarking.rs +++ b/pallets/nonfungible/src/benchmarking.rs @@ -1 +1,101 @@ -#![cfg(feature = "runtime-benchmarking")] +use super::*; +use crate::{Pallet, Config, NonfungibleHandle}; + +use sp_std::prelude::*; +use pallet_common::benchmarking::{create_collection_raw, create_data}; +use frame_benchmarking::{benchmarks, account}; +use nft_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH}; +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 { + const_data, + variable_data, + owner, + } +} +fn create_max_item( + collection: &NonfungibleHandle, + sender: &T::CrossAccountId, + owner: T::CrossAccountId, +) -> Result { + >::create_item(&collection, sender, create_max_item_data(owner))?; + Ok(TokenId(>::get(&collection.id))) +} + +fn create_collection( + owner: T::AccountId, +) -> Result, DispatchError> { + create_collection_raw( + owner, + CollectionMode::NFT, + >::init_collection, + NonfungibleHandle::cast, + ) +} + +benchmarks! { + create_item { + bench_init!{ + owner: sub; collection: collection(owner); + sender: cross_from_sub(owner); to: cross_sub; + }; + }: {create_max_item(&collection, &sender, to.clone())?} + + create_multiple_items { + let b in 0..MAX_ITEMS_PER_BATCH; + bench_init!{ + 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(); + }: {>::create_multiple_items(&collection, &sender, data)?} + + burn_item { + bench_init!{ + owner: sub; collection: collection(owner); + sender: cross_from_sub(owner); burner: cross_sub; + }; + let item = create_max_item(&collection, &sender, burner.clone())?; + }: {>::burn(&collection, &burner, item)?} + + transfer { + bench_init!{ + owner: sub; collection: collection(owner); + owner: cross_from_sub; sender: cross_sub; receiver: cross_sub; + }; + let item = create_max_item(&collection, &owner, sender.clone())?; + }: {>::transfer(&collection, &sender, &receiver, item)?} + + approve { + bench_init!{ + owner: sub; collection: collection(owner); + owner: cross_from_sub; sender: cross_sub; spender: cross_sub; + }; + let item = create_max_item(&collection, &owner, sender.clone())?; + }: {>::set_allowance(&collection, &sender, item, Some(&spender))?} + + transfer_from { + bench_init!{ + owner: sub; collection: collection(owner); + owner: cross_from_sub; sender: cross_sub; spender: cross_sub; receiver: cross_sub; + }; + let item = create_max_item(&collection, &owner, sender.clone())?; + >::set_allowance(&collection, &sender, item, Some(&spender))?; + }: {>::transfer_from(&collection, &spender, &sender, &receiver, item)?} + + set_variable_metadata { + let b in 0..CUSTOM_DATA_LIMIT; + bench_init!{ + owner: sub; collection: collection(owner); + owner: cross_from_sub; sender: cross_sub; + }; + let item = create_max_item(&collection, &owner, sender.clone())?; + let data = create_data(b as usize); + }: {>::set_variable_metadata(&collection, &sender, item, data)?} +} --- a/pallets/nonfungible/src/common.rs +++ b/pallets/nonfungible/src/common.rs @@ -9,8 +9,8 @@ use sp_std::vec::Vec; use crate::{ - AccountBalance, Allowance, Config, CreateItemData, DataKind, Error, NonfungibleHandle, Owned, - Owner, Pallet, SelfWeightOf, TokenData, weights::WeightInfo, + AccountBalance, Allowance, Config, CreateItemData, Error, NonfungibleHandle, Owned, Pallet, + SelfWeightOf, TokenData, weights::WeightInfo, TokensMinted, }; pub struct CommonWeights(PhantomData); @@ -39,8 +39,8 @@ >::transfer_from() } - fn set_variable_metadata(_bytes: u32) -> Weight { - >::set_variable_metadata() + fn set_variable_metadata(bytes: u32) -> Weight { + >::set_variable_metadata(bytes) } } @@ -67,7 +67,7 @@ ) -> DispatchResultWithPostInfo { with_weight( >::create_item(self, &sender, map_create_data(data, &to)?), - >::create_item(), + >::create_item(), ) } @@ -85,7 +85,7 @@ let amount = data.len(); with_weight( >::create_multiple_items(self, &sender, data), - >::create_multiple_items(amount as u32), + >::create_multiple_items(amount as u32), ) } @@ -99,7 +99,7 @@ if amount == 1 { with_weight( >::burn(&self, &sender, token), - >::burn_item(), + >::burn_item(), ) } else { Ok(().into()) @@ -117,7 +117,7 @@ if amount == 1 { with_weight( >::transfer(&self, &from, &to, token), - >::transfer(), + >::transfer(), ) } else { Ok(().into()) @@ -139,7 +139,7 @@ } else { >::set_allowance(&self, &sender, token, None) }, - >::approve(), + >::approve(), ) } @@ -156,7 +156,7 @@ if amount == 1 { with_weight( >::transfer_from(&self, &sender, &from, &to, token), - >::transfer_from(), + >::transfer_from(), ) } else { Ok(().into()) @@ -169,9 +169,10 @@ token: TokenId, data: Vec, ) -> DispatchResultWithPostInfo { + let len = data.len(); with_weight( >::set_variable_metadata(&self, &sender, token, data), - >::set_variable_metadata(), + >::set_variable_metadata(len as u32), ) } --- a/pallets/nonfungible/src/lib.rs +++ b/pallets/nonfungible/src/lib.rs @@ -16,6 +16,7 @@ use codec::{Encode, Decode}; pub use pallet::*; +#[cfg(feature = "runtime-benchmarks")] pub mod benchmarking; pub mod common; pub mod erc; --- a/pallets/nonfungible/src/weights.rs +++ b/pallets/nonfungible/src/weights.rs @@ -1,3 +1,27 @@ +// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs + +//! Autogenerated weights for pallet_nonfungible +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2021-10-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 128 + +// Executed Command: +// target/release/nft +// benchmark +// --pallet +// pallet-nonfungible +// --wasm-execution +// compiled +// --extrinsic +// * +// --template +// .maintain/frame-weight-template.hbs +// --steps=50 +// --repeat=20 +// --output=./pallets/nonfungible/src/weights.rs + + #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] @@ -5,33 +29,144 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use sp_std::marker::PhantomData; +/// Weight functions needed for pallet_nonfungible. pub trait WeightInfo { fn create_item() -> Weight; - fn create_multiple_items(b: u32) -> Weight; + fn create_multiple_items(b: u32, ) -> Weight; fn burn_item() -> Weight; fn transfer() -> Weight; fn approve() -> Weight; fn transfer_from() -> Weight; - fn set_variable_metadata() -> Weight; + fn set_variable_metadata(b: u32, ) -> Weight; } +/// Weights for pallet_nonfungible using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - fn create_item() -> Weight {0} - fn create_multiple_items(_b: u32) -> Weight {0} - fn burn_item() -> Weight {0} - fn transfer() -> Weight {0} - fn approve() -> Weight {0} - fn transfer_from() -> Weight {0} - fn set_variable_metadata() -> Weight {0} + // Storage: Nonfungible TokensMinted (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:1 w:1) + // Storage: Nonfungible TokenData (r:0 w:1) + // Storage: Nonfungible Owned (r:0 w:1) + fn create_item() -> Weight { + (16_902_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + } + // Storage: Nonfungible TokensMinted (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:1 w:1) + // Storage: Nonfungible TokenData (r:0 w:4) + // Storage: Nonfungible Owned (r:0 w:4) + fn create_multiple_items(b: u32, ) -> Weight { + (15_860_000 as Weight) + // Standard Error: 5_000 + .saturating_add((3_916_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(b as Weight))) + } + // Storage: Nonfungible TokenData (r:1 w:1) + // Storage: Nonfungible TokensBurnt (r:1 w:1) + // Storage: Nonfungible Allowance (r:1 w:0) + // Storage: Nonfungible Owned (r:0 w:1) + fn burn_item() -> Weight { + (17_966_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Nonfungible TokenData (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:2 w:2) + // Storage: Nonfungible Allowance (r:1 w:0) + // Storage: Nonfungible Owned (r:0 w:2) + fn transfer() -> Weight { + (23_886_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + } + // Storage: Nonfungible TokenData (r:1 w:0) + // Storage: Nonfungible Allowance (r:1 w:1) + fn approve() -> Weight { + (14_697_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: Nonfungible Allowance (r:1 w:1) + // Storage: Nonfungible TokenData (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:2 w:2) + // Storage: Nonfungible Owned (r:0 w:2) + fn transfer_from() -> Weight { + (28_001_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: Nonfungible TokenData (r:1 w:1) + fn set_variable_metadata(_b: u32, ) -> Weight { + (6_380_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } } +// For backwards compatibility and tests impl WeightInfo for () { - fn create_item() -> Weight {0} - fn create_multiple_items(_b: u32) -> Weight {0} - fn burn_item() -> Weight {0} - fn transfer() -> Weight {0} - fn approve() -> Weight {0} - fn transfer_from() -> Weight {0} - fn set_variable_metadata() -> Weight {0} + // Storage: Nonfungible TokensMinted (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:1 w:1) + // Storage: Nonfungible TokenData (r:0 w:1) + // Storage: Nonfungible Owned (r:0 w:1) + fn create_item() -> Weight { + (16_902_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + } + // Storage: Nonfungible TokensMinted (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:1 w:1) + // Storage: Nonfungible TokenData (r:0 w:4) + // Storage: Nonfungible Owned (r:0 w:4) + fn create_multiple_items(b: u32, ) -> Weight { + (15_860_000 as Weight) + // Standard Error: 5_000 + .saturating_add((3_916_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes((2 as Weight).saturating_mul(b as Weight))) + } + // Storage: Nonfungible TokenData (r:1 w:1) + // Storage: Nonfungible TokensBurnt (r:1 w:1) + // Storage: Nonfungible Allowance (r:1 w:0) + // Storage: Nonfungible Owned (r:0 w:1) + fn burn_item() -> Weight { + (17_966_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + // Storage: Nonfungible TokenData (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:2 w:2) + // Storage: Nonfungible Allowance (r:1 w:0) + // Storage: Nonfungible Owned (r:0 w:2) + fn transfer() -> Weight { + (23_886_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + } + // Storage: Nonfungible TokenData (r:1 w:0) + // Storage: Nonfungible Allowance (r:1 w:1) + fn approve() -> Weight { + (14_697_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: Nonfungible Allowance (r:1 w:1) + // Storage: Nonfungible TokenData (r:1 w:1) + // Storage: Nonfungible AccountBalance (r:2 w:2) + // Storage: Nonfungible Owned (r:0 w:2) + fn transfer_from() -> Weight { + (28_001_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) + } + // Storage: Nonfungible TokenData (r:1 w:1) + fn set_variable_metadata(_b: u32, ) -> Weight { + (6_380_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } }