From 34853d29f081e6a8647365029c9f81d849474bf8 Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Sun, 28 Feb 2021 18:04:48 +0800 Subject: [PATCH 01/18] Trying to benchmark pallet-example Signed-off-by: Jimmy Chu --- Cargo.lock | 3 ++- bin/node/runtime/Cargo.toml | 3 +++ bin/node/runtime/src/lib.rs | 6 ++++++ frame/example/Cargo.toml | 2 +- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9660e11884c86..7dd34a00e4add 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4113,6 +4113,7 @@ dependencies = [ "pallet-democracy", "pallet-election-provider-multi-phase", "pallet-elections-phragmen", + "pallet-example", "pallet-gilt", "pallet-grandpa", "pallet-identity", @@ -4761,7 +4762,7 @@ dependencies = [ [[package]] name = "pallet-example" -version = "2.0.0" +version = "3.0.0" dependencies = [ "frame-benchmarking", "frame-support", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 7669273f0c82d..c56b8638f1b2c 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -57,6 +57,7 @@ pallet-contracts-rpc-runtime-api = { version = "3.0.0", default-features = false pallet-democracy = { version = "3.0.0", default-features = false, path = "../../../frame/democracy" } pallet-election-provider-multi-phase = { version = "3.0.0", default-features = false, path = "../../../frame/election-provider-multi-phase" } pallet-elections-phragmen = { version = "3.0.0", default-features = false, path = "../../../frame/elections-phragmen" } +pallet-example = { version = "3.0.0", default-features = false, path = "../../../frame/example" } pallet-gilt = { version = "3.0.0", default-features = false, path = "../../../frame/gilt" } pallet-grandpa = { version = "3.0.0", default-features = false, path = "../../../frame/grandpa" } pallet-im-online = { version = "3.0.0", default-features = false, path = "../../../frame/im-online" } @@ -112,6 +113,7 @@ std = [ "pallet-contracts-rpc-runtime-api/std", "pallet-democracy/std", "pallet-elections-phragmen/std", + "pallet-example/std", "frame-executive/std", "pallet-gilt/std", "pallet-grandpa/std", @@ -172,6 +174,7 @@ runtime-benchmarks = [ "pallet-contracts/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-elections-phragmen/runtime-benchmarks", + "pallet-example/runtime-benchmarks", "pallet-gilt/runtime-benchmarks", "pallet-grandpa/runtime-benchmarks", "pallet-identity/runtime-benchmarks", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index a63fb341ddac8..bc59d3feb205f 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1071,6 +1071,10 @@ impl pallet_gilt::Config for Runtime { type WeightInfo = pallet_gilt::weights::SubstrateWeight; } +impl pallet_example::Config for Runtime { + type Event = Event; +} + construct_runtime!( pub enum Runtime where Block = Block, @@ -1115,6 +1119,7 @@ construct_runtime!( Mmr: pallet_mmr::{Module, Storage}, Lottery: pallet_lottery::{Module, Call, Storage, Event}, Gilt: pallet_gilt::{Module, Call, Storage, Event, Config}, + Example: pallet_example::{Module, Call, Storage, Event}, } ); @@ -1454,6 +1459,7 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_democracy, Democracy); add_benchmark!(params, batches, pallet_election_provider_multi_phase, ElectionProviderMultiPhase); add_benchmark!(params, batches, pallet_elections_phragmen, Elections); + add_benchmark!(params, batches, pallet_example, Example); add_benchmark!(params, batches, pallet_gilt, Gilt); add_benchmark!(params, batches, pallet_grandpa, Grandpa); add_benchmark!(params, batches, pallet_identity, Identity); diff --git a/frame/example/Cargo.toml b/frame/example/Cargo.toml index 618730688458e..40feda2d0bb66 100644 --- a/frame/example/Cargo.toml +++ b/frame/example/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-example" -version = "2.0.0" +version = "3.0.0" authors = ["Parity Technologies "] edition = "2018" license = "Unlicense" From 19ff8c4ced1e0988b9adf4542a66d4977cc017e1 Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Tue, 2 Mar 2021 16:02:55 +0800 Subject: [PATCH 02/18] added the weights info in function Signed-off-by: Jimmy Chu --- bin/node/runtime/src/lib.rs | 1 + frame/example/src/benchmarking.rs | 40 ++++++ frame/example/src/lib.rs | 218 +++--------------------------- frame/example/src/tests.rs | 160 ++++++++++++++++++++++ frame/example/src/weights.rs | 60 ++++++++ 5 files changed, 278 insertions(+), 201 deletions(-) create mode 100644 frame/example/src/benchmarking.rs create mode 100644 frame/example/src/tests.rs create mode 100644 frame/example/src/weights.rs diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index bc59d3feb205f..ffbd4c10554ac 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1073,6 +1073,7 @@ impl pallet_gilt::Config for Runtime { impl pallet_example::Config for Runtime { type Event = Event; + type WeightInfo = pallet_example::weights::WeightInfo; } construct_runtime!( diff --git a/frame/example/src/benchmarking.rs b/frame/example/src/benchmarking.rs new file mode 100644 index 0000000000000..c3da1a0030737 --- /dev/null +++ b/frame/example/src/benchmarking.rs @@ -0,0 +1,40 @@ +#![cfg(feature = "runtime-benchmarks")] + +use crate::*; + +mod benchmarking { + use super::*; + use frame_benchmarking::{benchmarks, account, impl_benchmark_test_suite}; + use frame_system::RawOrigin; + + benchmarks!{ + // This will measure the execution time of `accumulate_dummy` for b in [1..1000] range. + accumulate_dummy { + let b in 1 .. 1000; + let caller = account("caller", 0, 0); + }: _ (RawOrigin::Signed(caller), b.into()) + + // This will measure the execution time of `set_dummy` for b in [1..1000] range. + set_dummy { + let b in 1 .. 1000; + }: set_dummy (RawOrigin::Root, b.into()) + + // This will measure the execution time of `set_dummy` for b in [1..10] range. + another_set_dummy { + let b in 1 .. 10; + }: set_dummy (RawOrigin::Root, b.into()) + + // This will measure the execution time of sorting a vector. + sort_vector { + let x in 0 .. 10000; + let mut m = Vec::::new(); + for i in (0..x).rev() { + m.push(i); + } + }: { + m.sort(); + } + } + + impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test); +} diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index b4ae35c5508a9..7314bc03c0bfb 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -255,12 +255,12 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] +use sp_std::prelude::*; use sp_std::marker::PhantomData; use frame_support::{ dispatch::DispatchResult, traits::IsSubType, weights::{DispatchClass, ClassifyDispatch, WeighData, Weight, PaysFee, Pays}, }; -use sp_std::prelude::*; use frame_system::{ensure_signed}; use codec::{Encode, Decode}; use sp_runtime::{ @@ -318,6 +318,11 @@ type BalanceOf = ::Balance; // Re-export pallet items so that they can be accessed from the crate namespace. pub use pallet::*; +mod tests; +mod benchmarking; +pub mod weights; +pub use weights::WeightInfo; + // Definition of the pallet logic, to be aggregated at runtime definition through // `construct_runtime`. #[frame_support::pallet] @@ -327,6 +332,13 @@ pub mod pallet { use frame_system::pallet_prelude::*; use super::*; + pub trait WeightInfoTrait { + fn accumulate_dummy(_b: u32, ) -> Weight; + fn set_dummy(_b: u32, ) -> Weight; + fn another_set_dummy(b: u32, ) -> Weight; + fn sort_vector(x: u32, ) -> Weight; + } + /// Our pallet's configuration trait. All our types and constants go in here. If the /// pallet is dependent on specific other pallets, then their configuration traits /// should be added to our implied traits list. @@ -336,6 +348,7 @@ pub mod pallet { pub trait Config: pallet_balances::Config + frame_system::Config { /// The overarching event type. type Event: From> + IsType<::Event>; + type WeightInfo: WeightInfoTrait; } // Simple declaration of the `Pallet` type. It is placeholder we use to implement traits and @@ -455,7 +468,7 @@ pub mod pallet { // difficulty) of the transaction and the latter demonstrates the [`DispatchClass`] of the // call. A higher weight means a larger transaction (less of which can be placed in a // single block). - #[pallet::weight(0)] + #[pallet::weight(::WeightInfo::accumulate_dummy(0))] pub(super) fn accumulate_dummy( origin: OriginFor, increase_by: T::Balance @@ -496,7 +509,8 @@ pub mod pallet { // calls to be executed - we don't need to care why. Because it's privileged, we can // assume it's a one-off operation and substantial processing/storage/memory can be used // without worrying about gameability or attack scenarios. - #[pallet::weight(WeightForSetDummy::(>::from(100u32)))] + #[pallet::weight(::WeightInfo::another_set_dummy( + (*new_value).saturated_into()))] fn set_dummy( origin: OriginFor, #[pallet::compact] new_value: T::Balance, @@ -691,201 +705,3 @@ where } } } - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking { - use super::*; - use frame_benchmarking::{benchmarks, account, impl_benchmark_test_suite}; - use frame_system::RawOrigin; - - benchmarks!{ - // This will measure the execution time of `accumulate_dummy` for b in [1..1000] range. - accumulate_dummy { - let b in 1 .. 1000; - let caller = account("caller", 0, 0); - }: _ (RawOrigin::Signed(caller), b.into()) - - // This will measure the execution time of `set_dummy` for b in [1..1000] range. - set_dummy { - let b in 1 .. 1000; - }: set_dummy (RawOrigin::Root, b.into()) - - // This will measure the execution time of `set_dummy` for b in [1..10] range. - another_set_dummy { - let b in 1 .. 10; - }: set_dummy (RawOrigin::Root, b.into()) - - // This will measure the execution time of sorting a vector. - sort_vector { - let x in 0 .. 10000; - let mut m = Vec::::new(); - for i in (0..x).rev() { - m.push(i); - } - }: { - m.sort(); - } - } - - impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test); -} - -#[cfg(test)] -mod tests { - use super::*; - - use frame_support::{ - assert_ok, parameter_types, - weights::{DispatchInfo, GetDispatchInfo}, traits::{OnInitialize, OnFinalize} - }; - use sp_core::H256; - // The testing primitives are very useful for avoiding having to work with signatures - // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. - use sp_runtime::{ - testing::Header, BuildStorage, - traits::{BlakeTwo256, IdentityLookup}, - }; - // Reexport crate as its pallet name for construct_runtime. - use crate as pallet_example; - - type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; - type Block = frame_system::mocking::MockBlock; - - // For testing the pallet, we construct a mock runtime. - frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Module, Call, Config, Storage, Event}, - Balances: pallet_balances::{Module, Call, Storage, Config, Event}, - Example: pallet_example::{Module, Call, Storage, Config, Event}, - } - ); - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub BlockWeights: frame_system::limits::BlockWeights = - frame_system::limits::BlockWeights::simple_max(1024); - } - impl frame_system::Config for Test { - type BaseCallFilter = (); - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Call = Call; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = Event; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - } - parameter_types! { - pub const ExistentialDeposit: u64 = 1; - } - impl pallet_balances::Config for Test { - type MaxLocks = (); - type Balance = u64; - type DustRemoval = (); - type Event = Event; - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); - } - impl Config for Test { - type Event = Event; - } - - // This function basically just builds a genesis storage key/value store according to - // our desired mockup. - pub fn new_test_ext() -> sp_io::TestExternalities { - let t = GenesisConfig { - // We use default for brevity, but you can configure as desired if needed. - frame_system: Some(Default::default()), - pallet_balances: Some(Default::default()), - pallet_example: Some(pallet_example::GenesisConfig { - dummy: 42, - // we configure the map with (key, value) pairs. - bar: vec![(1, 2), (2, 3)], - foo: 24, - }), - }.build_storage().unwrap(); - t.into() - } - - #[test] - fn it_works_for_optional_value() { - new_test_ext().execute_with(|| { - // Check that GenesisBuilder works properly. - assert_eq!(Example::dummy(), Some(42)); - - // Check that accumulate works when we have Some value in Dummy already. - assert_ok!(Example::accumulate_dummy(Origin::signed(1), 27)); - assert_eq!(Example::dummy(), Some(69)); - - // Check that finalizing the block removes Dummy from storage. - >::on_finalize(1); - assert_eq!(Example::dummy(), None); - - // Check that accumulate works when we Dummy has None in it. - >::on_initialize(2); - assert_ok!(Example::accumulate_dummy(Origin::signed(1), 42)); - assert_eq!(Example::dummy(), Some(42)); - }); - } - - #[test] - fn it_works_for_default_value() { - new_test_ext().execute_with(|| { - assert_eq!(Example::foo(), 24); - assert_ok!(Example::accumulate_foo(Origin::signed(1), 1)); - assert_eq!(Example::foo(), 25); - }); - } - - #[test] - fn signed_ext_watch_dummy_works() { - new_test_ext().execute_with(|| { - let call = >::set_dummy(10).into(); - let info = DispatchInfo::default(); - - assert_eq!( - WatchDummy::(PhantomData).validate(&1, &call, &info, 150) - .unwrap() - .priority, - u64::max_value(), - ); - assert_eq!( - WatchDummy::(PhantomData).validate(&1, &call, &info, 250), - InvalidTransaction::ExhaustsResources.into(), - ); - }) - } - - #[test] - fn weights_work() { - // must have a defined weight. - let default_call = >::accumulate_dummy(10); - let info = default_call.get_dispatch_info(); - // aka. `let info = as GetDispatchInfo>::get_dispatch_info(&default_call);` - assert_eq!(info.weight, 0); - - // must have a custom weight of `100 * arg = 2000` - let custom_call = >::set_dummy(20); - let info = custom_call.get_dispatch_info(); - assert_eq!(info.weight, 2000); - } -} diff --git a/frame/example/src/tests.rs b/frame/example/src/tests.rs new file mode 100644 index 0000000000000..f1e8f0407e5a1 --- /dev/null +++ b/frame/example/src/tests.rs @@ -0,0 +1,160 @@ +#![cfg(test)] + +mod tests { + use super::*; + + use frame_support::{ + assert_ok, parameter_types, + weights::{DispatchInfo, GetDispatchInfo}, traits::{OnInitialize, OnFinalize} + }; + use sp_core::H256; + // The testing primitives are very useful for avoiding having to work with signatures + // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. + use sp_runtime::{ + testing::Header, BuildStorage, + traits::{BlakeTwo256, IdentityLookup}, + }; + // Reexport crate as its pallet name for construct_runtime. + use crate as pallet_example; + + type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; + type Block = frame_system::mocking::MockBlock; + + // For testing the pallet, we construct a mock runtime. + frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Module, Call, Config, Storage, Event}, + Balances: pallet_balances::{Module, Call, Storage, Config, Event}, + Example: pallet_example::{Module, Call, Storage, Config, Event}, + } + ); + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::simple_max(1024); + } + impl frame_system::Config for Test { + type BaseCallFilter = (); + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = Call; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + } + parameter_types! { + pub const ExistentialDeposit: u64 = 1; + } + impl pallet_balances::Config for Test { + type MaxLocks = (); + type Balance = u64; + type DustRemoval = (); + type Event = Event; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + } + impl Config for Test { + type Event = Event; + } + + // This function basically just builds a genesis storage key/value store according to + // our desired mockup. + pub fn new_test_ext() -> sp_io::TestExternalities { + let t = GenesisConfig { + // We use default for brevity, but you can configure as desired if needed. + frame_system: Some(Default::default()), + pallet_balances: Some(Default::default()), + pallet_example: Some(pallet_example::GenesisConfig { + dummy: 42, + // we configure the map with (key, value) pairs. + bar: vec![(1, 2), (2, 3)], + foo: 24, + }), + }.build_storage().unwrap(); + t.into() + } + + #[test] + fn it_works_for_optional_value() { + new_test_ext().execute_with(|| { + // Check that GenesisBuilder works properly. + assert_eq!(Example::dummy(), Some(42)); + + // Check that accumulate works when we have Some value in Dummy already. + assert_ok!(Example::accumulate_dummy(Origin::signed(1), 27)); + assert_eq!(Example::dummy(), Some(69)); + + // Check that finalizing the block removes Dummy from storage. + >::on_finalize(1); + assert_eq!(Example::dummy(), None); + + // Check that accumulate works when we Dummy has None in it. + >::on_initialize(2); + assert_ok!(Example::accumulate_dummy(Origin::signed(1), 42)); + assert_eq!(Example::dummy(), Some(42)); + }); + } + + #[test] + fn it_works_for_default_value() { + new_test_ext().execute_with(|| { + assert_eq!(Example::foo(), 24); + assert_ok!(Example::accumulate_foo(Origin::signed(1), 1)); + assert_eq!(Example::foo(), 25); + }); + } + + #[test] + fn signed_ext_watch_dummy_works() { + new_test_ext().execute_with(|| { + let call = >::set_dummy(10).into(); + let info = DispatchInfo::default(); + + assert_eq!( + WatchDummy::(PhantomData).validate(&1, &call, &info, 150) + .unwrap() + .priority, + u64::max_value(), + ); + assert_eq!( + WatchDummy::(PhantomData).validate(&1, &call, &info, 250), + InvalidTransaction::ExhaustsResources.into(), + ); + }) + } + + #[test] + fn weights_work() { + // must have a defined weight. + let default_call = >::accumulate_dummy(10); + let info = default_call.get_dispatch_info(); + // aka. `let info = as GetDispatchInfo>::get_dispatch_info(&default_call);` + assert_eq!(info.weight, 0); + + // must have a custom weight of `100 * arg = 2000` + let custom_call = >::set_dummy(20); + let info = custom_call.get_dispatch_info(); + assert_eq!(info.weight, 2000); + } +} diff --git a/frame/example/src/weights.rs b/frame/example/src/weights.rs new file mode 100644 index 0000000000000..5ef86912c0fb1 --- /dev/null +++ b/frame/example/src/weights.rs @@ -0,0 +1,60 @@ +//! Autogenerated weights for pallet_example +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 +//! DATE: 2021-03-01, STEPS: [50, ], REPEAT: 20, LOW RANGE: [], HIGH RANGE: [] +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 + +// Executed Command: +// ./target/debug/substrate +// benchmark +// --chain +// dev +// --execution +// wasm +// --wasm-execution +// compiled +// --pallet +// pallet_example +// --extrinsic +// * +// --steps +// 50 +// --repeat +// 20 +// --output +// ./ +// --log +// benchmark + + +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; +use crate::WeightInfoTrait; + +/// Weight functions for pallet_example. +pub struct WeightInfo(PhantomData); +impl WeightInfoTrait for WeightInfo { + fn accumulate_dummy(_b: u32, ) -> Weight { + (2_065_526_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn set_dummy(_b: u32, ) -> Weight { + (229_850_000 as Weight) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn another_set_dummy(b: u32, ) -> Weight { + (228_835_000 as Weight) + // Standard Error: 62_000 + .saturating_add((20_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn sort_vector(x: u32, ) -> Weight { + (123_304_000 as Weight) + // Standard Error: 0 + .saturating_add((5_000 as Weight).saturating_mul(x as Weight)) + } +} From 6e5902a6dbc68741499d0befcb69e4f0cf4ab452 Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Mon, 8 Mar 2021 12:21:32 +0800 Subject: [PATCH 03/18] updated naming Signed-off-by: Jimmy Chu --- frame/example/src/lib.rs | 2 +- frame/example/src/weights.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index 7314bc03c0bfb..3c6b0ce4db9d1 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -332,7 +332,7 @@ pub mod pallet { use frame_system::pallet_prelude::*; use super::*; - pub trait WeightInfoTrait { + pub trait WeightInfo { fn accumulate_dummy(_b: u32, ) -> Weight; fn set_dummy(_b: u32, ) -> Weight; fn another_set_dummy(b: u32, ) -> Weight; diff --git a/frame/example/src/weights.rs b/frame/example/src/weights.rs index 5ef86912c0fb1..3255c2f4c0db2 100644 --- a/frame/example/src/weights.rs +++ b/frame/example/src/weights.rs @@ -32,11 +32,11 @@ use frame_support::{traits::Get, weights::Weight}; use sp_std::marker::PhantomData; -use crate::WeightInfoTrait; +use crate::WeightInfo; /// Weight functions for pallet_example. pub struct WeightInfo(PhantomData); -impl WeightInfoTrait for WeightInfo { +impl WeightInfo for WeightInfo { fn accumulate_dummy(_b: u32, ) -> Weight { (2_065_526_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) From c4c037674231f3e4bf50d72335a62dd79fed6808 Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Tue, 9 Mar 2021 17:10:35 +0800 Subject: [PATCH 04/18] updated with benchmarking and weight Signed-off-by: Jimmy Chu --- bin/node/runtime/src/lib.rs | 2 +- frame/example/src/lib.rs | 13 ++++++++----- frame/example/src/weights.rs | 4 ++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index ffbd4c10554ac..1417f37c3ec4b 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1073,7 +1073,7 @@ impl pallet_gilt::Config for Runtime { impl pallet_example::Config for Runtime { type Event = Event; - type WeightInfo = pallet_example::weights::WeightInfo; + type WeightInfo = pallet_example::weights::SubstrateWeight; } construct_runtime!( diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index 3c6b0ce4db9d1..e9d99af682cfc 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -321,7 +321,7 @@ pub use pallet::*; mod tests; mod benchmarking; pub mod weights; -pub use weights::WeightInfo; +pub use weights::SubstrateWeight; // Definition of the pallet logic, to be aggregated at runtime definition through // `construct_runtime`. @@ -348,7 +348,7 @@ pub mod pallet { pub trait Config: pallet_balances::Config + frame_system::Config { /// The overarching event type. type Event: From> + IsType<::Event>; - type WeightInfo: WeightInfoTrait; + type WeightInfo: WeightInfo; } // Simple declaration of the `Pallet` type. It is placeholder we use to implement traits and @@ -468,7 +468,9 @@ pub mod pallet { // difficulty) of the transaction and the latter demonstrates the [`DispatchClass`] of the // call. A higher weight means a larger transaction (less of which can be placed in a // single block). - #[pallet::weight(::WeightInfo::accumulate_dummy(0))] + #[pallet::weight( + ::WeightInfo::accumulate_dummy(0) + )] pub(super) fn accumulate_dummy( origin: OriginFor, increase_by: T::Balance @@ -509,8 +511,9 @@ pub mod pallet { // calls to be executed - we don't need to care why. Because it's privileged, we can // assume it's a one-off operation and substantial processing/storage/memory can be used // without worrying about gameability or attack scenarios. - #[pallet::weight(::WeightInfo::another_set_dummy( - (*new_value).saturated_into()))] + #[pallet::weight( + ::WeightInfo::set_dummy((*new_value).saturated_into()) + )] fn set_dummy( origin: OriginFor, #[pallet::compact] new_value: T::Balance, diff --git a/frame/example/src/weights.rs b/frame/example/src/weights.rs index 3255c2f4c0db2..650fdb0cf53f3 100644 --- a/frame/example/src/weights.rs +++ b/frame/example/src/weights.rs @@ -35,8 +35,8 @@ use sp_std::marker::PhantomData; use crate::WeightInfo; /// Weight functions for pallet_example. -pub struct WeightInfo(PhantomData); -impl WeightInfo for WeightInfo { +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { fn accumulate_dummy(_b: u32, ) -> Weight { (2_065_526_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) From 2a3ea00a1d914ade3f7be52afe42125dfbbc1e85 Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Tue, 9 Mar 2021 17:51:48 +0800 Subject: [PATCH 05/18] Updated test for pallet-example Signed-off-by: Jimmy Chu --- frame/elections-phragmen/src/lib.rs | 2 +- frame/example/src/tests.rs | 23 +++++++++++++---------- frame/example/src/weights.rs | 25 ++++++++++++++++++++++++- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index 779570ca633ee..446f635965e7e 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -1084,7 +1084,7 @@ mod tests { type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); - type SS58Prefix = (); + type SS58Prefix = (); } parameter_types! { diff --git a/frame/example/src/tests.rs b/frame/example/src/tests.rs index f1e8f0407e5a1..853fd614a25f6 100644 --- a/frame/example/src/tests.rs +++ b/frame/example/src/tests.rs @@ -1,7 +1,7 @@ #![cfg(test)] mod tests { - use super::*; + use crate::*; use frame_support::{ assert_ok, parameter_types, @@ -76,6 +76,7 @@ mod tests { } impl Config for Test { type Event = Event; + type WeightInfo = (); } // This function basically just builds a genesis storage key/value store according to @@ -83,14 +84,14 @@ mod tests { pub fn new_test_ext() -> sp_io::TestExternalities { let t = GenesisConfig { // We use default for brevity, but you can configure as desired if needed. - frame_system: Some(Default::default()), - pallet_balances: Some(Default::default()), - pallet_example: Some(pallet_example::GenesisConfig { + frame_system: Default::default(), + pallet_balances: Default::default(), + pallet_example: pallet_example::GenesisConfig { dummy: 42, // we configure the map with (key, value) pairs. bar: vec![(1, 2), (2, 3)], foo: 24, - }), + }, }.build_storage().unwrap(); t.into() } @@ -148,13 +149,15 @@ mod tests { fn weights_work() { // must have a defined weight. let default_call = >::accumulate_dummy(10); - let info = default_call.get_dispatch_info(); + let info1 = default_call.get_dispatch_info(); // aka. `let info = as GetDispatchInfo>::get_dispatch_info(&default_call);` - assert_eq!(info.weight, 0); + assert!(info1.weight > 0); + - // must have a custom weight of `100 * arg = 2000` + // `set_dummy` is simpler than `accumulate_dummy`, and the weight + // should be less. let custom_call = >::set_dummy(20); - let info = custom_call.get_dispatch_info(); - assert_eq!(info.weight, 2000); + let info2 = custom_call.get_dispatch_info(); + assert!(info1.weight > info2.weight); } } diff --git a/frame/example/src/weights.rs b/frame/example/src/weights.rs index 650fdb0cf53f3..9dfdf1a11231d 100644 --- a/frame/example/src/weights.rs +++ b/frame/example/src/weights.rs @@ -30,7 +30,7 @@ #![allow(unused_parens)] #![allow(unused_imports)] -use frame_support::{traits::Get, weights::Weight}; +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use sp_std::marker::PhantomData; use crate::WeightInfo; @@ -58,3 +58,26 @@ impl WeightInfo for SubstrateWeight { .saturating_add((5_000 as Weight).saturating_mul(x as Weight)) } } + +impl WeightInfo for () { + fn accumulate_dummy(_b: u32, ) -> Weight { + (2_065_526_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn set_dummy(_b: u32, ) -> Weight { + (229_850_000 as Weight) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn another_set_dummy(b: u32, ) -> Weight { + (228_835_000 as Weight) + // Standard Error: 62_000 + .saturating_add((20_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn sort_vector(x: u32, ) -> Weight { + (123_304_000 as Weight) + // Standard Error: 0 + .saturating_add((5_000 as Weight).saturating_mul(x as Weight)) + } +} From 3d68f869f54e2cd2f14e092c13ecfaa4ae349c3e Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Tue, 9 Mar 2021 18:38:44 +0800 Subject: [PATCH 06/18] adding weights.rs benchmarked in release mode Signed-off-by: Jimmy Chu --- frame/example/src/weights.rs | 97 +++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 40 deletions(-) diff --git a/frame/example/src/weights.rs b/frame/example/src/weights.rs index 9dfdf1a11231d..b283c0bee9d40 100644 --- a/frame/example/src/weights.rs +++ b/frame/example/src/weights.rs @@ -1,30 +1,39 @@ +// This file is part of Substrate. + +// Copyright (C) 2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + //! Autogenerated weights for pallet_example //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-03-01, STEPS: [50, ], REPEAT: 20, LOW RANGE: [], HIGH RANGE: [] +//! DATE: 2021-03-09, STEPS: `[10, ]`, REPEAT: 5, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: -// ./target/debug/substrate -// benchmark -// --chain -// dev -// --execution -// wasm -// --wasm-execution -// compiled -// --pallet -// pallet_example -// --extrinsic -// * -// --steps -// 50 -// --repeat -// 20 -// --output -// ./ -// --log +// target/release/substrate // benchmark +// --chain=dev +// --steps=10 +// --repeat=5 +// --pallet=pallet_example +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./frame/example/src/weights.rs +// --template=./.maintain/frame-weight-template.hbs #![allow(unused_parens)] @@ -32,52 +41,60 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use sp_std::marker::PhantomData; -use crate::WeightInfo; -/// Weight functions for pallet_example. +/// Weight functions needed for pallet_example. +pub trait WeightInfo { + fn accumulate_dummy(b: u32, ) -> Weight; + fn set_dummy(b: u32, ) -> Weight; + fn another_set_dummy(b: u32, ) -> Weight; + fn sort_vector(x: u32, ) -> Weight; +} + +/// Weights for pallet_example using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - fn accumulate_dummy(_b: u32, ) -> Weight { - (2_065_526_000 as Weight) + fn accumulate_dummy(b: u32, ) -> Weight { + (49_663_000 as Weight) + // Standard Error: 3_000 + .saturating_add((6_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn set_dummy(_b: u32, ) -> Weight { - (229_850_000 as Weight) + (5_884_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - fn another_set_dummy(b: u32, ) -> Weight { - (228_835_000 as Weight) - // Standard Error: 62_000 - .saturating_add((20_000 as Weight).saturating_mul(b as Weight)) + fn another_set_dummy(_b: u32, ) -> Weight { + (6_643_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn sort_vector(x: u32, ) -> Weight { - (123_304_000 as Weight) + (2_169_000 as Weight) // Standard Error: 0 - .saturating_add((5_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((4_000 as Weight).saturating_mul(x as Weight)) } } +// For backwards compatibility and tests impl WeightInfo for () { - fn accumulate_dummy(_b: u32, ) -> Weight { - (2_065_526_000 as Weight) + fn accumulate_dummy(b: u32, ) -> Weight { + (49_663_000 as Weight) + // Standard Error: 3_000 + .saturating_add((6_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn set_dummy(_b: u32, ) -> Weight { - (229_850_000 as Weight) + (5_884_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - fn another_set_dummy(b: u32, ) -> Weight { - (228_835_000 as Weight) - // Standard Error: 62_000 - .saturating_add((20_000 as Weight).saturating_mul(b as Weight)) + fn another_set_dummy(_b: u32, ) -> Weight { + (6_643_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn sort_vector(x: u32, ) -> Weight { - (123_304_000 as Weight) + (2_169_000 as Weight) // Standard Error: 0 - .saturating_add((5_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((4_000 as Weight).saturating_mul(x as Weight)) } } From c436b1479ce2e7744ecb1426874e29a0d325d6a2 Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Tue, 9 Mar 2021 18:41:35 +0800 Subject: [PATCH 07/18] Removed pallet-example from node-runtime Signed-off-by: Jimmy Chu --- bin/node/runtime/Cargo.toml | 1 - bin/node/runtime/src/lib.rs | 7 ------- 2 files changed, 8 deletions(-) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 8f0bd9cee22db..50babff31bad3 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -58,7 +58,6 @@ pallet-contracts-rpc-runtime-api = { version = "3.0.0", default-features = false pallet-democracy = { version = "3.0.0", default-features = false, path = "../../../frame/democracy" } pallet-election-provider-multi-phase = { version = "3.0.0", default-features = false, path = "../../../frame/election-provider-multi-phase" } pallet-elections-phragmen = { version = "3.0.0", default-features = false, path = "../../../frame/elections-phragmen" } -pallet-example = { version = "3.0.0", default-features = false, path = "../../../frame/example" } pallet-gilt = { version = "3.0.0", default-features = false, path = "../../../frame/gilt" } pallet-grandpa = { version = "3.0.0", default-features = false, path = "../../../frame/grandpa" } pallet-im-online = { version = "3.0.0", default-features = false, path = "../../../frame/im-online" } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 11556c4c79079..a0b966c63c33b 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1071,11 +1071,6 @@ impl pallet_gilt::Config for Runtime { type WeightInfo = pallet_gilt::weights::SubstrateWeight; } -impl pallet_example::Config for Runtime { - type Event = Event; - type WeightInfo = pallet_example::weights::SubstrateWeight; -} - construct_runtime!( pub enum Runtime where Block = Block, @@ -1120,7 +1115,6 @@ construct_runtime!( Mmr: pallet_mmr::{Module, Storage}, Lottery: pallet_lottery::{Module, Call, Storage, Event}, Gilt: pallet_gilt::{Module, Call, Storage, Event, Config}, - Example: pallet_example::{Module, Call, Storage, Event}, } ); @@ -1459,7 +1453,6 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_democracy, Democracy); add_benchmark!(params, batches, pallet_election_provider_multi_phase, ElectionProviderMultiPhase); add_benchmark!(params, batches, pallet_elections_phragmen, Elections); - add_benchmark!(params, batches, pallet_example, Example); add_benchmark!(params, batches, pallet_gilt, Gilt); add_benchmark!(params, batches, pallet_grandpa, Grandpa); add_benchmark!(params, batches, pallet_identity, Identity); From 3ab9102ea67ec88945fbb2ab48ccd1a15e49bffb Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Tue, 9 Mar 2021 18:48:03 +0800 Subject: [PATCH 08/18] adjusted Signed-off-by: Jimmy Chu --- Cargo.lock | 1 - bin/node/runtime/Cargo.toml | 2 -- frame/example/src/lib.rs | 15 +++++---------- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 15b2392c2e8db..09db85a2b78bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4175,7 +4175,6 @@ dependencies = [ "pallet-democracy", "pallet-election-provider-multi-phase", "pallet-elections-phragmen", - "pallet-example", "pallet-gilt", "pallet-grandpa", "pallet-identity", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 50babff31bad3..43ecca7e74456 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -113,7 +113,6 @@ std = [ "pallet-contracts-rpc-runtime-api/std", "pallet-democracy/std", "pallet-elections-phragmen/std", - "pallet-example/std", "frame-executive/std", "pallet-gilt/std", "pallet-grandpa/std", @@ -175,7 +174,6 @@ runtime-benchmarks = [ "pallet-contracts/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-elections-phragmen/runtime-benchmarks", - "pallet-example/runtime-benchmarks", "pallet-gilt/runtime-benchmarks", "pallet-grandpa/runtime-benchmarks", "pallet-identity/runtime-benchmarks", diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index e9d99af682cfc..e971a454bff2b 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -255,8 +255,10 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -use sp_std::prelude::*; -use sp_std::marker::PhantomData; +use sp_std::{ + prelude::*, + marker::PhantomData +}; use frame_support::{ dispatch::DispatchResult, traits::IsSubType, weights::{DispatchClass, ClassifyDispatch, WeighData, Weight, PaysFee, Pays}, @@ -321,7 +323,7 @@ pub use pallet::*; mod tests; mod benchmarking; pub mod weights; -pub use weights::SubstrateWeight; +pub use weights::*; // Definition of the pallet logic, to be aggregated at runtime definition through // `construct_runtime`. @@ -332,13 +334,6 @@ pub mod pallet { use frame_system::pallet_prelude::*; use super::*; - pub trait WeightInfo { - fn accumulate_dummy(_b: u32, ) -> Weight; - fn set_dummy(_b: u32, ) -> Weight; - fn another_set_dummy(b: u32, ) -> Weight; - fn sort_vector(x: u32, ) -> Weight; - } - /// Our pallet's configuration trait. All our types and constants go in here. If the /// pallet is dependent on specific other pallets, then their configuration traits /// should be added to our implied traits list. From 8d2cdf996c59e81f51d0ef216fe959282ec18a5b Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Fri, 12 Mar 2021 19:23:34 +0800 Subject: [PATCH 09/18] modification based on peer comments Signed-off-by: Jimmy Chu --- frame/example/src/benchmarking.rs | 81 +++++--- frame/example/src/lib.rs | 2 +- frame/example/src/tests.rs | 320 ++++++++++++++++-------------- 3 files changed, 217 insertions(+), 186 deletions(-) diff --git a/frame/example/src/benchmarking.rs b/frame/example/src/benchmarking.rs index c3da1a0030737..967e5db8b1025 100644 --- a/frame/example/src/benchmarking.rs +++ b/frame/example/src/benchmarking.rs @@ -1,40 +1,55 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Benchmarking for pallet-example. + #![cfg(feature = "runtime-benchmarks")] use crate::*; +use frame_benchmarking::{benchmarks, whitelisted_caller, impl_benchmark_test_suite}; +use frame_system::RawOrigin; + +benchmarks!{ + // This will measure the execution time of `accumulate_dummy` for b in [1..1000] range. + accumulate_dummy { + let b in 1 .. 1000; + let caller: T::AccountId = whitelisted_caller(); + }: _(RawOrigin::Signed(caller), b.into()) -mod benchmarking { - use super::*; - use frame_benchmarking::{benchmarks, account, impl_benchmark_test_suite}; - use frame_system::RawOrigin; - - benchmarks!{ - // This will measure the execution time of `accumulate_dummy` for b in [1..1000] range. - accumulate_dummy { - let b in 1 .. 1000; - let caller = account("caller", 0, 0); - }: _ (RawOrigin::Signed(caller), b.into()) - - // This will measure the execution time of `set_dummy` for b in [1..1000] range. - set_dummy { - let b in 1 .. 1000; - }: set_dummy (RawOrigin::Root, b.into()) - - // This will measure the execution time of `set_dummy` for b in [1..10] range. - another_set_dummy { - let b in 1 .. 10; - }: set_dummy (RawOrigin::Root, b.into()) - - // This will measure the execution time of sorting a vector. - sort_vector { - let x in 0 .. 10000; - let mut m = Vec::::new(); - for i in (0..x).rev() { - m.push(i); - } - }: { - m.sort(); + // This will measure the execution time of `set_dummy` for b in [1..1000] range. + set_dummy { + let b in 1 .. 1000; + }: _(RawOrigin::Root, b.into()) + + // This will measure the execution time of `set_dummy` for b in [1..10] range. + another_set_dummy { + let b in 1 .. 10; + }: set_dummy(RawOrigin::Root, b.into()) + + // This will measure the execution time of sorting a vector. + sort_vector { + let x in 0 .. 10000; + let mut m = Vec::::new(); + for i in (0..x).rev() { + m.push(i); } + }: { + m.sort(); } - - impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test); } + +impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test); diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index e971a454bff2b..795d8d3902dc3 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -464,7 +464,7 @@ pub mod pallet { // call. A higher weight means a larger transaction (less of which can be placed in a // single block). #[pallet::weight( - ::WeightInfo::accumulate_dummy(0) + ::WeightInfo::accumulate_dummy((*increase_by).saturated_into()) )] pub(super) fn accumulate_dummy( origin: OriginFor, diff --git a/frame/example/src/tests.rs b/frame/example/src/tests.rs index 853fd614a25f6..9a74ab3efd30b 100644 --- a/frame/example/src/tests.rs +++ b/frame/example/src/tests.rs @@ -1,163 +1,179 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Tests for pallet-example. + #![cfg(test)] -mod tests { - use crate::*; - - use frame_support::{ - assert_ok, parameter_types, - weights::{DispatchInfo, GetDispatchInfo}, traits::{OnInitialize, OnFinalize} - }; - use sp_core::H256; - // The testing primitives are very useful for avoiding having to work with signatures - // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. - use sp_runtime::{ - testing::Header, BuildStorage, - traits::{BlakeTwo256, IdentityLookup}, - }; - // Reexport crate as its pallet name for construct_runtime. - use crate as pallet_example; - - type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; - type Block = frame_system::mocking::MockBlock; - - // For testing the pallet, we construct a mock runtime. - frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Module, Call, Config, Storage, Event}, - Balances: pallet_balances::{Module, Call, Storage, Config, Event}, - Example: pallet_example::{Module, Call, Storage, Config, Event}, - } - ); - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub BlockWeights: frame_system::limits::BlockWeights = - frame_system::limits::BlockWeights::simple_max(1024); - } - impl frame_system::Config for Test { - type BaseCallFilter = (); - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Call = Call; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = Event; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - } - parameter_types! { - pub const ExistentialDeposit: u64 = 1; - } - impl pallet_balances::Config for Test { - type MaxLocks = (); - type Balance = u64; - type DustRemoval = (); - type Event = Event; - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); - } - impl Config for Test { - type Event = Event; - type WeightInfo = (); +use crate::*; +use frame_support::{ + assert_ok, parameter_types, + weights::{DispatchInfo, GetDispatchInfo}, traits::{OnInitialize, OnFinalize} +}; +use sp_core::H256; +// The testing primitives are very useful for avoiding having to work with signatures +// or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. +use sp_runtime::{ + testing::Header, BuildStorage, + traits::{BlakeTwo256, IdentityLookup}, +}; +// Reexport crate as its pallet name for construct_runtime. +use crate as pallet_example; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +// For testing the pallet, we construct a mock runtime. +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Module, Call, Config, Storage, Event}, + Balances: pallet_balances::{Module, Call, Storage, Config, Event}, + Example: pallet_example::{Module, Call, Storage, Config, Event}, } +); - // This function basically just builds a genesis storage key/value store according to - // our desired mockup. - pub fn new_test_ext() -> sp_io::TestExternalities { - let t = GenesisConfig { - // We use default for brevity, but you can configure as desired if needed. - frame_system: Default::default(), - pallet_balances: Default::default(), - pallet_example: pallet_example::GenesisConfig { - dummy: 42, - // we configure the map with (key, value) pairs. - bar: vec![(1, 2), (2, 3)], - foo: 24, - }, - }.build_storage().unwrap(); - t.into() - } +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::simple_max(1024); +} +impl frame_system::Config for Test { + type BaseCallFilter = (); + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = Call; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); +} +parameter_types! { + pub const ExistentialDeposit: u64 = 1; +} +impl pallet_balances::Config for Test { + type MaxLocks = (); + type Balance = u64; + type DustRemoval = (); + type Event = Event; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} +impl Config for Test { + type Event = Event; + type WeightInfo = (); +} - #[test] - fn it_works_for_optional_value() { - new_test_ext().execute_with(|| { - // Check that GenesisBuilder works properly. - assert_eq!(Example::dummy(), Some(42)); - - // Check that accumulate works when we have Some value in Dummy already. - assert_ok!(Example::accumulate_dummy(Origin::signed(1), 27)); - assert_eq!(Example::dummy(), Some(69)); - - // Check that finalizing the block removes Dummy from storage. - >::on_finalize(1); - assert_eq!(Example::dummy(), None); - - // Check that accumulate works when we Dummy has None in it. - >::on_initialize(2); - assert_ok!(Example::accumulate_dummy(Origin::signed(1), 42)); - assert_eq!(Example::dummy(), Some(42)); - }); - } +// This function basically just builds a genesis storage key/value store according to +// our desired mockup. +pub fn new_test_ext() -> sp_io::TestExternalities { + let t = GenesisConfig { + // We use default for brevity, but you can configure as desired if needed. + frame_system: Default::default(), + pallet_balances: Default::default(), + pallet_example: pallet_example::GenesisConfig { + dummy: 42, + // we configure the map with (key, value) pairs. + bar: vec![(1, 2), (2, 3)], + foo: 24, + }, + }.build_storage().unwrap(); + t.into() +} - #[test] - fn it_works_for_default_value() { - new_test_ext().execute_with(|| { - assert_eq!(Example::foo(), 24); - assert_ok!(Example::accumulate_foo(Origin::signed(1), 1)); - assert_eq!(Example::foo(), 25); - }); - } +#[test] +fn it_works_for_optional_value() { + new_test_ext().execute_with(|| { + // Check that GenesisBuilder works properly. + assert_eq!(Example::dummy(), Some(42)); + + // Check that accumulate works when we have Some value in Dummy already. + assert_ok!(Example::accumulate_dummy(Origin::signed(1), 27)); + assert_eq!(Example::dummy(), Some(69)); + + // Check that finalizing the block removes Dummy from storage. + >::on_finalize(1); + assert_eq!(Example::dummy(), None); + + // Check that accumulate works when we Dummy has None in it. + >::on_initialize(2); + assert_ok!(Example::accumulate_dummy(Origin::signed(1), 42)); + assert_eq!(Example::dummy(), Some(42)); + }); +} - #[test] - fn signed_ext_watch_dummy_works() { - new_test_ext().execute_with(|| { - let call = >::set_dummy(10).into(); - let info = DispatchInfo::default(); - - assert_eq!( - WatchDummy::(PhantomData).validate(&1, &call, &info, 150) - .unwrap() - .priority, - u64::max_value(), - ); - assert_eq!( - WatchDummy::(PhantomData).validate(&1, &call, &info, 250), - InvalidTransaction::ExhaustsResources.into(), - ); - }) - } +#[test] +fn it_works_for_default_value() { + new_test_ext().execute_with(|| { + assert_eq!(Example::foo(), 24); + assert_ok!(Example::accumulate_foo(Origin::signed(1), 1)); + assert_eq!(Example::foo(), 25); + }); +} - #[test] - fn weights_work() { - // must have a defined weight. - let default_call = >::accumulate_dummy(10); - let info1 = default_call.get_dispatch_info(); - // aka. `let info = as GetDispatchInfo>::get_dispatch_info(&default_call);` - assert!(info1.weight > 0); +#[test] +fn signed_ext_watch_dummy_works() { + new_test_ext().execute_with(|| { + let call = >::set_dummy(10).into(); + let info = DispatchInfo::default(); + + assert_eq!( + WatchDummy::(PhantomData).validate(&1, &call, &info, 150) + .unwrap() + .priority, + u64::max_value(), + ); + assert_eq!( + WatchDummy::(PhantomData).validate(&1, &call, &info, 250), + InvalidTransaction::ExhaustsResources.into(), + ); + }) +} +#[test] +fn weights_work() { + // must have a defined weight. + let default_call = >::accumulate_dummy(10); + let info1 = default_call.get_dispatch_info(); + // aka. `let info = as GetDispatchInfo>::get_dispatch_info(&default_call);` + assert!(info1.weight > 0); - // `set_dummy` is simpler than `accumulate_dummy`, and the weight - // should be less. - let custom_call = >::set_dummy(20); - let info2 = custom_call.get_dispatch_info(); - assert!(info1.weight > info2.weight); - } + + // `set_dummy` is simpler than `accumulate_dummy`, and the weight + // should be less. + let custom_call = >::set_dummy(20); + let info2 = custom_call.get_dispatch_info(); + assert!(info1.weight > info2.weight); } From abd4507c320ec7a8da2b542558983a448bac23df Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Fri, 19 Mar 2021 11:28:29 +0800 Subject: [PATCH 10/18] updated so far Signed-off-by: Jimmy Chu --- Cargo.lock | 1 + bin/node/runtime/Cargo.toml | 3 ++ bin/node/runtime/src/lib.rs | 7 ++++ frame/example/src/benchmarking.rs | 6 +-- frame/example/src/lib.rs | 69 +++++++++++++++++++------------ frame/example/src/tests.rs | 11 ++++- frame/example/src/weights.rs | 62 +++++++++++++-------------- 7 files changed, 92 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 09db85a2b78bc..15b2392c2e8db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4175,6 +4175,7 @@ dependencies = [ "pallet-democracy", "pallet-election-provider-multi-phase", "pallet-elections-phragmen", + "pallet-example", "pallet-gilt", "pallet-grandpa", "pallet-identity", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 43ecca7e74456..a68af58d79627 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -58,6 +58,7 @@ pallet-contracts-rpc-runtime-api = { version = "3.0.0", default-features = false pallet-democracy = { version = "3.0.0", default-features = false, path = "../../../frame/democracy" } pallet-election-provider-multi-phase = { version = "3.0.0", default-features = false, path = "../../../frame/election-provider-multi-phase" } pallet-elections-phragmen = { version = "3.0.0", default-features = false, path = "../../../frame/elections-phragmen" } +pallet-example = { version = "3.0.0", default-features = false, path = "../../../frame/example" } pallet-gilt = { version = "3.0.0", default-features = false, path = "../../../frame/gilt" } pallet-grandpa = { version = "3.0.0", default-features = false, path = "../../../frame/grandpa" } pallet-im-online = { version = "3.0.0", default-features = false, path = "../../../frame/im-online" } @@ -112,6 +113,7 @@ std = [ "pallet-contracts-primitives/std", "pallet-contracts-rpc-runtime-api/std", "pallet-democracy/std", + "pallet-example/std", "pallet-elections-phragmen/std", "frame-executive/std", "pallet-gilt/std", @@ -174,6 +176,7 @@ runtime-benchmarks = [ "pallet-contracts/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-elections-phragmen/runtime-benchmarks", + "pallet-example/runtime-benchmarks", "pallet-gilt/runtime-benchmarks", "pallet-grandpa/runtime-benchmarks", "pallet-identity/runtime-benchmarks", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index a0b966c63c33b..ce013b42eddb9 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -659,6 +659,11 @@ parameter_types! { pub const TechnicalMaxMembers: u32 = 100; } +impl pallet_example::Config for Runtime { + type Event = Event; + type WeightInfo = pallet_example::weights::SubstrateWeight; +} + type TechnicalCollective = pallet_collective::Instance2; impl pallet_collective::Config for Runtime { type Origin = Origin; @@ -1115,6 +1120,7 @@ construct_runtime!( Mmr: pallet_mmr::{Module, Storage}, Lottery: pallet_lottery::{Module, Call, Storage, Event}, Gilt: pallet_gilt::{Module, Call, Storage, Event, Config}, + Example: pallet_example::{Module, Call, Storage, Event}, } ); @@ -1453,6 +1459,7 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_democracy, Democracy); add_benchmark!(params, batches, pallet_election_provider_multi_phase, ElectionProviderMultiPhase); add_benchmark!(params, batches, pallet_elections_phragmen, Elections); + add_benchmark!(params, batches, pallet_example, Example); add_benchmark!(params, batches, pallet_gilt, Gilt); add_benchmark!(params, batches, pallet_grandpa, Grandpa); add_benchmark!(params, batches, pallet_identity, Identity); diff --git a/frame/example/src/benchmarking.rs b/frame/example/src/benchmarking.rs index 967e5db8b1025..fe6f025ebd481 100644 --- a/frame/example/src/benchmarking.rs +++ b/frame/example/src/benchmarking.rs @@ -27,6 +27,7 @@ benchmarks!{ // This will measure the execution time of `accumulate_dummy` for b in [1..1000] range. accumulate_dummy { let b in 1 .. 1000; + // The caller account is whitelisted for DB reads/write by the benchmarking macro. let caller: T::AccountId = whitelisted_caller(); }: _(RawOrigin::Signed(caller), b.into()) @@ -35,11 +36,6 @@ benchmarks!{ let b in 1 .. 1000; }: _(RawOrigin::Root, b.into()) - // This will measure the execution time of `set_dummy` for b in [1..10] range. - another_set_dummy { - let b in 1 .. 10; - }: set_dummy(RawOrigin::Root, b.into()) - // This will measure the execution time of sorting a vector. sort_vector { let x in 0 .. 10000; diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index 795d8d3902dc3..57cc2e48e4d79 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -260,20 +260,34 @@ use sp_std::{ marker::PhantomData }; use frame_support::{ - dispatch::DispatchResult, traits::IsSubType, + runtime_print, dispatch::DispatchResult, traits::IsSubType, weights::{DispatchClass, ClassifyDispatch, WeighData, Weight, PaysFee, Pays}, }; use frame_system::{ensure_signed}; use codec::{Encode, Decode}; use sp_runtime::{ traits::{ - SignedExtension, Bounded, SaturatedConversion, DispatchInfoOf, + SignedExtension, Bounded, SaturatedConversion, DispatchInfoOf, Saturating }, transaction_validity::{ ValidTransaction, TransactionValidityError, InvalidTransaction, TransactionValidity, }, }; +// Re-export pallet items so that they can be accessed from the crate namespace. +pub use pallet::*; + +#[cfg(test)] +mod tests; + +mod benchmarking; +pub mod weights; +pub use weights::*; + +/// A type alias for the balance type from this pallet's point of view. +type BalanceOf = ::Balance; +const MILLICENTS: u32 = 1_000_000_000; + // A custom weight calculator tailored for the dispatch call `set_dummy()`. This actually examines // the arguments and makes a decision based upon them. // @@ -294,7 +308,9 @@ impl WeighData<(&BalanceOf,)> for WeightForSetDum { fn weigh_data(&self, target: (&BalanceOf,)) -> Weight { let multiplier = self.0; - (*target.0 * multiplier).saturated_into::() + // *target.0 is the amount passed into the extrinsic + let cents = *target.0 / >::from(MILLICENTS); + (cents * multiplier).saturated_into::() } } @@ -314,17 +330,6 @@ impl PaysFee<(&BalanceOf,)> for WeightForSetDummy } } -/// A type alias for the balance type from this pallet's point of view. -type BalanceOf = ::Balance; - -// Re-export pallet items so that they can be accessed from the crate namespace. -pub use pallet::*; - -mod tests; -mod benchmarking; -pub mod weights; -pub use weights::*; - // Definition of the pallet logic, to be aggregated at runtime definition through // `construct_runtime`. #[frame_support::pallet] @@ -463,13 +468,16 @@ pub mod pallet { // difficulty) of the transaction and the latter demonstrates the [`DispatchClass`] of the // call. A higher weight means a larger transaction (less of which can be placed in a // single block). + // + // The weight for this extrinsic we rely on the auto-generated `WeightInfo` from the benchmark + // toolchain. #[pallet::weight( ::WeightInfo::accumulate_dummy((*increase_by).saturated_into()) )] pub(super) fn accumulate_dummy( origin: OriginFor, increase_by: T::Balance - ) -> DispatchResultWithPostInfo { + ) -> DispatchResult { // This is a public call, so we ensure that the origin is some signed account. let _sender = ensure_signed(origin)?; @@ -488,15 +496,16 @@ pub mod pallet { // Here's the new one of read and then modify the value. >::mutate(|dummy| { - let new_dummy = dummy.map_or(increase_by, |dummy| dummy + increase_by); + // Using `saturating_add` instead of a regular `+` to avoid overflowing + let new_dummy = dummy.map_or(increase_by, |d| d.saturating_add(increase_by)); *dummy = Some(new_dummy); }); // Let's deposit an event to let the outside world know this happened. - Self::deposit_event(Event::Dummy(increase_by)); + Self::deposit_event(Event::AccumulateDummy(increase_by)); // All good, no refund. - Ok(().into()) + Ok(()) } /// A privileged call; in this case it resets our dummy value to something new. @@ -506,19 +515,25 @@ pub mod pallet { // calls to be executed - we don't need to care why. Because it's privileged, we can // assume it's a one-off operation and substantial processing/storage/memory can be used // without worrying about gameability or attack scenarios. - #[pallet::weight( - ::WeightInfo::set_dummy((*new_value).saturated_into()) - )] - fn set_dummy( + // + // The weight for this extrinsic we use our own weight object `WeightForSetDummy` to determine + // its weight + #[pallet::weight(WeightForSetDummy::(>::from(100u32)))] + pub(super) fn set_dummy( origin: OriginFor, #[pallet::compact] new_value: T::Balance, - ) -> DispatchResultWithPostInfo { + ) -> DispatchResult { ensure_root(origin)?; + + // TODO: add comment + runtime_print!("New value is now: {:?}", new_value); + // Put the new value into storage. >::put(new_value); + Self::deposit_event(Event::SetDummy(new_value)); // All good, no refund. - Ok(().into()) + Ok(()) } } @@ -532,7 +547,8 @@ pub mod pallet { pub enum Event { // Just a normal `enum`, here's a dummy event to ensure it compiles. /// Dummy event, just here so there's a generic type that's used. - Dummy(BalanceOf), + AccumulateDummy(BalanceOf), + SetDummy(BalanceOf), } // pallet::storage attributes allow for type-safe usage of the Substrate storage database, @@ -564,7 +580,6 @@ pub mod pallet { #[pallet::getter(fn foo)] pub(super) type Foo = StorageValue<_, T::Balance, ValueQuery>; - // The genesis config type. #[pallet::genesis_config] pub struct GenesisConfig { @@ -612,7 +627,7 @@ impl Pallet { let prev = >::get(); // Because Foo has 'default', the type of 'foo' in closure is the raw type instead of an Option<> type. let result = >::mutate(|foo| { - *foo = *foo + increase_by; + *foo = foo.saturating_add(increase_by); *foo }); assert!(prev + increase_by == result); diff --git a/frame/example/src/tests.rs b/frame/example/src/tests.rs index 9a74ab3efd30b..09cc9eafdde1f 100644 --- a/frame/example/src/tests.rs +++ b/frame/example/src/tests.rs @@ -17,8 +17,6 @@ //! Tests for pallet-example. -#![cfg(test)] - use crate::*; use frame_support::{ assert_ok, parameter_types, @@ -143,6 +141,15 @@ fn it_works_for_default_value() { }); } +#[test] +fn set_dummy_works() { + new_test_ext().execute_with(|| { + let test_val = 133; + assert_ok!(Example::set_dummy(Origin::root(), test_val.into())); + assert_eq!(Example::dummy(), Some(test_val)); + }); +} + #[test] fn signed_ext_watch_dummy_works() { new_test_ext().execute_with(|| { diff --git a/frame/example/src/weights.rs b/frame/example/src/weights.rs index b283c0bee9d40..71f4e31ea2164 100644 --- a/frame/example/src/weights.rs +++ b/frame/example/src/weights.rs @@ -18,22 +18,31 @@ //! Autogenerated weights for pallet_example //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-03-09, STEPS: `[10, ]`, REPEAT: 5, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-03-15, STEPS: `[100, ]`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: -// target/release/substrate +// ./target/release/substrate // benchmark -// --chain=dev -// --steps=10 -// --repeat=5 -// --pallet=pallet_example -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./frame/example/src/weights.rs -// --template=./.maintain/frame-weight-template.hbs +// --chain +// dev +// --execution +// wasm +// --wasm-execution +// compiled +// --pallet +// pallet_example +// --extrinsic +// * +// --steps +// 100 +// --repeat +// 10 +// --raw +// --output +// ./ +// --template +// ./.maintain/frame-weight-template.hbs #![allow(unused_parens)] @@ -46,30 +55,23 @@ use sp_std::marker::PhantomData; pub trait WeightInfo { fn accumulate_dummy(b: u32, ) -> Weight; fn set_dummy(b: u32, ) -> Weight; - fn another_set_dummy(b: u32, ) -> Weight; fn sort_vector(x: u32, ) -> Weight; } /// Weights for pallet_example using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - fn accumulate_dummy(b: u32, ) -> Weight { - (49_663_000 as Weight) - // Standard Error: 3_000 - .saturating_add((6_000 as Weight).saturating_mul(b as Weight)) + fn accumulate_dummy(_b: u32, ) -> Weight { + (51_353_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn set_dummy(_b: u32, ) -> Weight { - (5_884_000 as Weight) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) - } - fn another_set_dummy(_b: u32, ) -> Weight { - (6_643_000 as Weight) + (5_834_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn sort_vector(x: u32, ) -> Weight { - (2_169_000 as Weight) + (2_569_000 as Weight) // Standard Error: 0 .saturating_add((4_000 as Weight).saturating_mul(x as Weight)) } @@ -77,23 +79,17 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { - fn accumulate_dummy(b: u32, ) -> Weight { - (49_663_000 as Weight) - // Standard Error: 3_000 - .saturating_add((6_000 as Weight).saturating_mul(b as Weight)) + fn accumulate_dummy(_b: u32, ) -> Weight { + (51_353_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn set_dummy(_b: u32, ) -> Weight { - (5_884_000 as Weight) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) - } - fn another_set_dummy(_b: u32, ) -> Weight { - (6_643_000 as Weight) + (5_834_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn sort_vector(x: u32, ) -> Weight { - (2_169_000 as Weight) + (2_569_000 as Weight) // Standard Error: 0 .saturating_add((4_000 as Weight).saturating_mul(x as Weight)) } From 761487311454bead81d087b6cea0eaf2fa1fe683 Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Sat, 20 Mar 2021 13:50:07 +0800 Subject: [PATCH 11/18] updated Signed-off-by: Jimmy Chu --- Cargo.lock | 1 + bin/node/runtime/src/lib.rs | 10 ++- frame/example/Cargo.toml | 7 +- frame/example/src/lib.rs | 144 +++++++++++++++++++++--------------- 4 files changed, 96 insertions(+), 66 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2167e98eab552..18ca84cb2d00e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4851,6 +4851,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "log", "pallet-balances", "parity-scale-codec", "serde", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 9c29b98ff22a9..c28b6136c3a27 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -661,16 +661,20 @@ impl pallet_elections_phragmen::Config for Runtime { } parameter_types! { - pub const TechnicalMotionDuration: BlockNumber = 5 * DAYS; - pub const TechnicalMaxProposals: u32 = 100; - pub const TechnicalMaxMembers: u32 = 100; + pub const MagicNumber: Balance = 1 * DOLLARS; } impl pallet_example::Config for Runtime { type Event = Event; type WeightInfo = pallet_example::weights::SubstrateWeight; + type MagicNumber = MagicNumber; } +parameter_types! { + pub const TechnicalMotionDuration: BlockNumber = 5 * DAYS; + pub const TechnicalMaxProposals: u32 = 100; + pub const TechnicalMaxMembers: u32 = 100; +} type TechnicalCollective = pallet_collective::Instance2; impl pallet_collective::Config for Runtime { type Origin = Origin; diff --git a/frame/example/Cargo.toml b/frame/example/Cargo.toml index b06b6d162d4a1..e24616bc84cf3 100644 --- a/frame/example/Cargo.toml +++ b/frame/example/Cargo.toml @@ -21,8 +21,8 @@ pallet-balances = { version = "3.0.0", default-features = false, path = "../bala sp-runtime = { version = "3.0.0", default-features = false, path = "../../primitives/runtime" } sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "3.0.0", default-features = false, path = "../../primitives/io" } - frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true } +log = { version = "0.4.14", default-features = false } [dev-dependencies] sp-core = { version = "3.0.0", path = "../../primitives/core", default-features = false } @@ -30,14 +30,15 @@ sp-core = { version = "3.0.0", path = "../../primitives/core", default-features [features] default = ["std"] std = [ - "serde", "codec/std", - "sp-runtime/std", "frame-benchmarking/std", "frame-support/std", "frame-system/std", + "log/std", "pallet-balances/std", + "serde", "sp-io/std", + "sp-runtime/std", "sp-std/std" ] runtime-benchmarks = ["frame-benchmarking"] diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index 57cc2e48e4d79..f7503b3807036 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -260,7 +260,7 @@ use sp_std::{ marker::PhantomData }; use frame_support::{ - runtime_print, dispatch::DispatchResult, traits::IsSubType, + dispatch::DispatchResult, traits::IsSubType, weights::{DispatchClass, ClassifyDispatch, WeighData, Weight, PaysFee, Pays}, }; use frame_system::{ensure_signed}; @@ -274,6 +274,8 @@ use sp_runtime::{ }, }; +use log::info; + // Re-export pallet items so that they can be accessed from the crate namespace. pub use pallet::*; @@ -346,6 +348,9 @@ pub mod pallet { /// `frame_system::Config` should always be included. #[pallet::config] pub trait Config: pallet_balances::Config + frame_system::Config { + #[pallet::constant] + type MagicNumber: Get; + /// The overarching event type. type Event: From> + IsType<::Event>; type WeightInfo: WeightInfo; @@ -497,8 +502,9 @@ pub mod pallet { // Here's the new one of read and then modify the value. >::mutate(|dummy| { // Using `saturating_add` instead of a regular `+` to avoid overflowing - let new_dummy = dummy.map_or(increase_by, |d| d.saturating_add(increase_by)); - *dummy = Some(new_dummy); + // let new_dummy = dummy.map_or(increase_by, |d| d.saturating_add(increase_by)); + // *dummy = Some(new_dummy); + *dummy = dummy.saturating_add(increase_by); }); // Let's deposit an event to let the outside world know this happened. @@ -523,18 +529,35 @@ pub mod pallet { origin: OriginFor, #[pallet::compact] new_value: T::Balance, ) -> DispatchResult { - ensure_root(origin)?; + // ensure_root(origin)?; + let acct = ensure_signed(origin)?; - // TODO: add comment - runtime_print!("New value is now: {:?}", new_value); + // Print out log or debug message in the console via log::{error, warn, info, debug, trace}, + // accepting format strings similar to `println!`. + // https://substrate.dev/rustdocs/v3.0.0/log/index.html + info!("New value is now: {:?}", new_value); // Put the new value into storage. - >::put(new_value); + >::set(new_value); Self::deposit_event(Event::SetDummy(new_value)); + >::set(>::from(33_000_000u32)); + // All good, no refund. Ok(()) } + + #[pallet::weight(0)] + pub(super) fn set_bar( + origin: OriginFor, + #[pallet::compact] new_value: T::Balance, + ) -> DispatchResult { + let acct = ensure_signed(origin)?; + + >::insert(acct.clone(), new_value); + Self::deposit_event(Event::SetBar(acct, new_value)); + Ok(()) + } } /// Events are a simple means of reporting specific conditions and @@ -549,6 +572,7 @@ pub mod pallet { /// Dummy event, just here so there's a generic type that's used. AccumulateDummy(BalanceOf), SetDummy(BalanceOf), + SetBar(T::AccountId, BalanceOf), } // pallet::storage attributes allow for type-safe usage of the Substrate storage database, @@ -568,12 +592,12 @@ pub mod pallet { // `fn getter_name() -> Type` for basic value items or // `fn getter_name(key: KeyType) -> ValueType` for map items. #[pallet::getter(fn dummy)] - pub(super) type Dummy = StorageValue<_, T::Balance>; + pub(super) type Dummy = StorageValue<_, T::Balance, ValueQuery>; // A map that has enumerable entries. #[pallet::storage] #[pallet::getter(fn bar)] - pub(super) type Bar = StorageMap<_, Blake2_128Concat, T::AccountId, T::Balance, ValueQuery>; + pub(super) type Bar = StorageMap<_, Blake2_128Concat, T::AccountId, T::Balance>; // this one uses the query kind: `ValueQuery`, we'll demonstrate the usage of 'mutate' API. #[pallet::storage] @@ -667,54 +691,54 @@ impl Pallet { // types defined in the runtime. Lookup `pub type SignedExtra = (...)` in `node/runtime` and // `node-template` for an example of this. -/// A simple signed extension that checks for the `set_dummy` call. In that case, it increases the -/// priority and prints some log. -/// -/// Additionally, it drops any transaction with an encoded length higher than 200 bytes. No -/// particular reason why, just to demonstrate the power of signed extensions. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct WatchDummy(PhantomData); - -impl sp_std::fmt::Debug for WatchDummy { - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "WatchDummy") - } -} - -impl SignedExtension for WatchDummy -where - ::Call: IsSubType>, -{ - const IDENTIFIER: &'static str = "WatchDummy"; - type AccountId = T::AccountId; - type Call = ::Call; - type AdditionalSigned = (); - type Pre = (); - - fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } - - fn validate( - &self, - _who: &Self::AccountId, - call: &Self::Call, - _info: &DispatchInfoOf, - len: usize, - ) -> TransactionValidity { - // if the transaction is too big, just drop it. - if len > 200 { - return InvalidTransaction::ExhaustsResources.into() - } - - // check for `set_dummy` - match call.is_sub_type() { - Some(Call::set_dummy(..)) => { - sp_runtime::print("set_dummy was received."); - - let mut valid_tx = ValidTransaction::default(); - valid_tx.priority = Bounded::max_value(); - Ok(valid_tx) - } - _ => Ok(Default::default()), - } - } -} +// A simple signed extension that checks for the `set_dummy` call. In that case, it increases the +// priority and prints some log. +// +// Additionally, it drops any transaction with an encoded length higher than 200 bytes. No +// particular reason why, just to demonstrate the power of signed extensions. +// #[derive(Encode, Decode, Clone, Eq, PartialEq)] +// pub struct WatchDummy(PhantomData); + +// impl sp_std::fmt::Debug for WatchDummy { +// fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { +// write!(f, "WatchDummy") +// } +// } + +// impl SignedExtension for WatchDummy +// where +// ::Call: IsSubType>, +// { +// const IDENTIFIER: &'static str = "WatchDummy"; +// type AccountId = T::AccountId; +// type Call = ::Call; +// type AdditionalSigned = (); +// type Pre = (); + +// fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } + +// fn validate( +// &self, +// _who: &Self::AccountId, +// call: &Self::Call, +// _info: &DispatchInfoOf, +// len: usize, +// ) -> TransactionValidity { +// // if the transaction is too big, just drop it. +// if len > 200 { +// return InvalidTransaction::ExhaustsResources.into() +// } + +// // check for `set_dummy` +// match call.is_sub_type() { +// Some(Call::set_dummy(..)) => { +// sp_runtime::print("set_dummy was received."); + +// let mut valid_tx = ValidTransaction::default(); +// valid_tx.priority = Bounded::max_value(); +// Ok(valid_tx) +// } +// _ => Ok(Default::default()), +// } +// } +// } From 911fdcc51bc9e330067ee596ea642d44f21a2cfc Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Sat, 20 Mar 2021 16:40:34 +0800 Subject: [PATCH 12/18] updated Signed-off-by: Jimmy Chu --- frame/example/src/lib.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index f7503b3807036..6a9ae5172650e 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -502,9 +502,8 @@ pub mod pallet { // Here's the new one of read and then modify the value. >::mutate(|dummy| { // Using `saturating_add` instead of a regular `+` to avoid overflowing - // let new_dummy = dummy.map_or(increase_by, |d| d.saturating_add(increase_by)); - // *dummy = Some(new_dummy); - *dummy = dummy.saturating_add(increase_by); + let new_dummy = dummy.map_or(increase_by, |d| d.saturating_add(increase_by)); + *dummy = Some(new_dummy); }); // Let's deposit an event to let the outside world know this happened. @@ -538,7 +537,7 @@ pub mod pallet { info!("New value is now: {:?}", new_value); // Put the new value into storage. - >::set(new_value); + >::put(new_value); Self::deposit_event(Event::SetDummy(new_value)); >::set(>::from(33_000_000u32)); @@ -592,7 +591,7 @@ pub mod pallet { // `fn getter_name() -> Type` for basic value items or // `fn getter_name(key: KeyType) -> ValueType` for map items. #[pallet::getter(fn dummy)] - pub(super) type Dummy = StorageValue<_, T::Balance, ValueQuery>; + pub(super) type Dummy = StorageValue<_, T::Balance>; // A map that has enumerable entries. #[pallet::storage] From a291e1328e9ebb1aa6b7817be98e06455a557b24 Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Thu, 25 Mar 2021 19:50:59 +0800 Subject: [PATCH 13/18] updated code Signed-off-by: Jimmy Chu --- frame/example/src/benchmarking.rs | 29 ++++++-- frame/example/src/lib.rs | 119 +++++++++++++----------------- frame/example/src/tests.rs | 29 ++++---- frame/example/src/weights.rs | 26 ++++--- 4 files changed, 108 insertions(+), 95 deletions(-) diff --git a/frame/example/src/benchmarking.rs b/frame/example/src/benchmarking.rs index fe6f025ebd481..ff28c45103f53 100644 --- a/frame/example/src/benchmarking.rs +++ b/frame/example/src/benchmarking.rs @@ -23,19 +23,37 @@ use crate::*; use frame_benchmarking::{benchmarks, whitelisted_caller, impl_benchmark_test_suite}; use frame_system::RawOrigin; +// To actually run this benchmark on pallet-example, we need to put this pallet into the +// runtime and compile it with `runtime-benchmarks` feature. The detail procedures are +// documented at: +// https://substrate.dev/docs/en/knowledgebase/runtime/benchmarking#how-to-benchmark +// +// The auto-generated weight estimate of this pallet is copied over to the `weights.rs` file. +// The exact command of how the estimate generated is printed at the top of the file. + +// Details on using the benchmarks macro can be seen at: +// https://substrate.dev/rustdocs/v3.0.0/frame_benchmarking/macro.benchmarks.html benchmarks!{ + // This will measure the execution time of `set_dummy` for b in [1..1000] range. + set_dummy_benchmark { + // This is the benchmark setup phase + let b in 1 .. 1000; + }: set_dummy(RawOrigin::Root, b.into()) // The execution phase is just running `set_dummy` extrinsic call + verify { + // This is the optional benchmark verification phase, asserting certain states. + assert_eq!(Pallet::::dummy(), Some(b.into())) + } + // This will measure the execution time of `accumulate_dummy` for b in [1..1000] range. + // The benchmark execution phase is shorthanded. When the name of the benchmark case is the same + // as the extrinsic call. `_(...)` is used to represent the extrinsic name. + // The benchmark verification phase is omitted. accumulate_dummy { let b in 1 .. 1000; // The caller account is whitelisted for DB reads/write by the benchmarking macro. let caller: T::AccountId = whitelisted_caller(); }: _(RawOrigin::Signed(caller), b.into()) - // This will measure the execution time of `set_dummy` for b in [1..1000] range. - set_dummy { - let b in 1 .. 1000; - }: _(RawOrigin::Root, b.into()) - // This will measure the execution time of sorting a vector. sort_vector { let x in 0 .. 10000; @@ -44,6 +62,7 @@ benchmarks!{ m.push(i); } }: { + // The benchmark execution phase could also be a closure with custom code m.sort(); } } diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index 6a9ae5172650e..b410361037461 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -348,6 +348,7 @@ pub mod pallet { /// `frame_system::Config` should always be included. #[pallet::config] pub trait Config: pallet_balances::Config + frame_system::Config { + // Setting a constant config parameter from the runtime #[pallet::constant] type MagicNumber: Get; @@ -372,14 +373,12 @@ pub mod pallet { fn on_initialize(_n: T::BlockNumber) -> Weight { // Anything that needs to be done at the start of the block. // We don't do anything here. - 0 } // `on_finalize` is executed at the end of block after all extrinsic are dispatched. fn on_finalize(_n: T::BlockNumber) { - // We just kill our dummy storage item. - >::kill(); + // Perform necessary data/state clean up here. } // A runtime code run after every block and have access to extended set of APIs. @@ -388,7 +387,9 @@ pub mod pallet { fn offchain_worker(_n: T::BlockNumber) { // We don't do anything here. // but we could dispatch extrinsic (transaction/unsigned/inherent) using - // sp_io::submit_extrinsic + // sp_io::submit_extrinsic. + // To see example on offchain worker, please refer to example-offchain-worker pallet + // accompanied in this repository. } } @@ -528,8 +529,7 @@ pub mod pallet { origin: OriginFor, #[pallet::compact] new_value: T::Balance, ) -> DispatchResult { - // ensure_root(origin)?; - let acct = ensure_signed(origin)?; + ensure_root(origin)?; // Print out log or debug message in the console via log::{error, warn, info, debug, trace}, // accepting format strings similar to `println!`. @@ -538,25 +538,12 @@ pub mod pallet { // Put the new value into storage. >::put(new_value); - Self::deposit_event(Event::SetDummy(new_value)); - >::set(>::from(33_000_000u32)); + Self::deposit_event(Event::SetDummy(new_value)); // All good, no refund. Ok(()) } - - #[pallet::weight(0)] - pub(super) fn set_bar( - origin: OriginFor, - #[pallet::compact] new_value: T::Balance, - ) -> DispatchResult { - let acct = ensure_signed(origin)?; - - >::insert(acct.clone(), new_value); - Self::deposit_event(Event::SetBar(acct, new_value)); - Ok(()) - } } /// Events are a simple means of reporting specific conditions and @@ -695,49 +682,49 @@ impl Pallet { // // Additionally, it drops any transaction with an encoded length higher than 200 bytes. No // particular reason why, just to demonstrate the power of signed extensions. -// #[derive(Encode, Decode, Clone, Eq, PartialEq)] -// pub struct WatchDummy(PhantomData); - -// impl sp_std::fmt::Debug for WatchDummy { -// fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { -// write!(f, "WatchDummy") -// } -// } - -// impl SignedExtension for WatchDummy -// where -// ::Call: IsSubType>, -// { -// const IDENTIFIER: &'static str = "WatchDummy"; -// type AccountId = T::AccountId; -// type Call = ::Call; -// type AdditionalSigned = (); -// type Pre = (); - -// fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } - -// fn validate( -// &self, -// _who: &Self::AccountId, -// call: &Self::Call, -// _info: &DispatchInfoOf, -// len: usize, -// ) -> TransactionValidity { -// // if the transaction is too big, just drop it. -// if len > 200 { -// return InvalidTransaction::ExhaustsResources.into() -// } - -// // check for `set_dummy` -// match call.is_sub_type() { -// Some(Call::set_dummy(..)) => { -// sp_runtime::print("set_dummy was received."); - -// let mut valid_tx = ValidTransaction::default(); -// valid_tx.priority = Bounded::max_value(); -// Ok(valid_tx) -// } -// _ => Ok(Default::default()), -// } -// } -// } +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct WatchDummy(PhantomData); + +impl sp_std::fmt::Debug for WatchDummy { + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + write!(f, "WatchDummy") + } +} + +impl SignedExtension for WatchDummy +where + ::Call: IsSubType>, +{ + const IDENTIFIER: &'static str = "WatchDummy"; + type AccountId = T::AccountId; + type Call = ::Call; + type AdditionalSigned = (); + type Pre = (); + + fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) } + + fn validate( + &self, + _who: &Self::AccountId, + call: &Self::Call, + _info: &DispatchInfoOf, + len: usize, + ) -> TransactionValidity { + // if the transaction is too big, just drop it. + if len > 200 { + return InvalidTransaction::ExhaustsResources.into() + } + + // check for `set_dummy` + match call.is_sub_type() { + Some(Call::set_dummy(..)) => { + sp_runtime::print("set_dummy was received."); + + let mut valid_tx = ValidTransaction::default(); + valid_tx.priority = Bounded::max_value(); + Ok(valid_tx) + } + _ => Ok(Default::default()), + } + } +} diff --git a/frame/example/src/tests.rs b/frame/example/src/tests.rs index 09cc9eafdde1f..ed866344a4b18 100644 --- a/frame/example/src/tests.rs +++ b/frame/example/src/tests.rs @@ -20,7 +20,7 @@ use crate::*; use frame_support::{ assert_ok, parameter_types, - weights::{DispatchInfo, GetDispatchInfo}, traits::{OnInitialize, OnFinalize} + weights::{DispatchInfo, GetDispatchInfo}, traits::OnInitialize }; use sp_core::H256; // The testing primitives are very useful for avoiding having to work with signatures @@ -42,9 +42,9 @@ frame_support::construct_runtime!( NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic, { - System: frame_system::{Module, Call, Config, Storage, Event}, - Balances: pallet_balances::{Module, Call, Storage, Config, Event}, - Example: pallet_example::{Module, Call, Storage, Config, Event}, + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + Example: pallet_example::{Pallet, Call, Storage, Config, Event}, } ); @@ -89,7 +89,12 @@ impl pallet_balances::Config for Test { type AccountStore = System; type WeightInfo = (); } + +parameter_types! { + pub const MagicNumber: u64 = 1_000_000_000; +} impl Config for Test { + type MagicNumber = MagicNumber; type Event = Event; type WeightInfo = (); } @@ -115,20 +120,18 @@ pub fn new_test_ext() -> sp_io::TestExternalities { fn it_works_for_optional_value() { new_test_ext().execute_with(|| { // Check that GenesisBuilder works properly. - assert_eq!(Example::dummy(), Some(42)); + let val1 = 42; + let val2 = 27; + assert_eq!(Example::dummy(), Some(val1)); // Check that accumulate works when we have Some value in Dummy already. - assert_ok!(Example::accumulate_dummy(Origin::signed(1), 27)); - assert_eq!(Example::dummy(), Some(69)); - - // Check that finalizing the block removes Dummy from storage. - >::on_finalize(1); - assert_eq!(Example::dummy(), None); + assert_ok!(Example::accumulate_dummy(Origin::signed(1), val2)); + assert_eq!(Example::dummy(), Some(val1 + val2)); // Check that accumulate works when we Dummy has None in it. >::on_initialize(2); - assert_ok!(Example::accumulate_dummy(Origin::signed(1), 42)); - assert_eq!(Example::dummy(), Some(42)); + assert_ok!(Example::accumulate_dummy(Origin::signed(1), val1)); + assert_eq!(Example::dummy(), Some(val1 + val2 + val1)); }); } diff --git a/frame/example/src/weights.rs b/frame/example/src/weights.rs index 71f4e31ea2164..db6491335c76f 100644 --- a/frame/example/src/weights.rs +++ b/frame/example/src/weights.rs @@ -53,21 +53,23 @@ use sp_std::marker::PhantomData; /// Weight functions needed for pallet_example. pub trait WeightInfo { + fn set_dummy_benchmark(b: u32, ) -> Weight; fn accumulate_dummy(b: u32, ) -> Weight; - fn set_dummy(b: u32, ) -> Weight; fn sort_vector(x: u32, ) -> Weight; } /// Weights for pallet_example using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - fn accumulate_dummy(_b: u32, ) -> Weight { - (51_353_000 as Weight) - .saturating_add(T::DbWeight::get().reads(1 as Weight)) + fn set_dummy_benchmark(b: u32, ) -> Weight { + (5_834_000 as Weight) + .saturating_add((24_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - fn set_dummy(_b: u32, ) -> Weight { - (5_834_000 as Weight) + fn accumulate_dummy(b: u32, ) -> Weight { + (51_353_000 as Weight) + .saturating_add((14_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn sort_vector(x: u32, ) -> Weight { @@ -79,13 +81,15 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { - fn accumulate_dummy(_b: u32, ) -> Weight { - (51_353_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + fn set_dummy_benchmark(b: u32, ) -> Weight { + (5_834_000 as Weight) + .saturating_add((24_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - fn set_dummy(_b: u32, ) -> Weight { - (5_834_000 as Weight) + fn accumulate_dummy(b: u32, ) -> Weight { + (51_353_000 as Weight) + .saturating_add((14_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn sort_vector(x: u32, ) -> Weight { From 612cde9cd649abbf7299ffb3afb7c6933e5f2b12 Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Thu, 25 Mar 2021 20:07:56 +0800 Subject: [PATCH 14/18] Added explanation on impl_benchmark_test_suite! macro Signed-off-by: Jimmy Chu --- frame/example/src/benchmarking.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frame/example/src/benchmarking.rs b/frame/example/src/benchmarking.rs index ff28c45103f53..73c9a456b3b04 100644 --- a/frame/example/src/benchmarking.rs +++ b/frame/example/src/benchmarking.rs @@ -67,4 +67,10 @@ benchmarks!{ } } +// This line generates test cases for benchmarking, and could be run by: +// `cargo test -p pallet-example --all-features`, you will see an additional line of: +// `test benchmarking::benchmark_tests::test_benchmarks ... ok` in the result. +// +// The line generates three steps per benchmark, with repeat=1 and the three steps are +// [low, mid, high] of the range. impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test); From f4ff4f7932ac959bcb1e853bca0eb835d6ff0f2d Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Thu, 25 Mar 2021 20:10:40 +0800 Subject: [PATCH 15/18] Remove pallet-example from runtime Signed-off-by: Jimmy Chu --- bin/node/runtime/Cargo.toml | 3 --- bin/node/runtime/src/lib.rs | 13 +------------ 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index a68af58d79627..43ecca7e74456 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -58,7 +58,6 @@ pallet-contracts-rpc-runtime-api = { version = "3.0.0", default-features = false pallet-democracy = { version = "3.0.0", default-features = false, path = "../../../frame/democracy" } pallet-election-provider-multi-phase = { version = "3.0.0", default-features = false, path = "../../../frame/election-provider-multi-phase" } pallet-elections-phragmen = { version = "3.0.0", default-features = false, path = "../../../frame/elections-phragmen" } -pallet-example = { version = "3.0.0", default-features = false, path = "../../../frame/example" } pallet-gilt = { version = "3.0.0", default-features = false, path = "../../../frame/gilt" } pallet-grandpa = { version = "3.0.0", default-features = false, path = "../../../frame/grandpa" } pallet-im-online = { version = "3.0.0", default-features = false, path = "../../../frame/im-online" } @@ -113,7 +112,6 @@ std = [ "pallet-contracts-primitives/std", "pallet-contracts-rpc-runtime-api/std", "pallet-democracy/std", - "pallet-example/std", "pallet-elections-phragmen/std", "frame-executive/std", "pallet-gilt/std", @@ -176,7 +174,6 @@ runtime-benchmarks = [ "pallet-contracts/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-elections-phragmen/runtime-benchmarks", - "pallet-example/runtime-benchmarks", "pallet-gilt/runtime-benchmarks", "pallet-grandpa/runtime-benchmarks", "pallet-identity/runtime-benchmarks", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index c28b6136c3a27..12de6d54aaf3f 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -660,21 +660,12 @@ impl pallet_elections_phragmen::Config for Runtime { type WeightInfo = pallet_elections_phragmen::weights::SubstrateWeight; } -parameter_types! { - pub const MagicNumber: Balance = 1 * DOLLARS; -} - -impl pallet_example::Config for Runtime { - type Event = Event; - type WeightInfo = pallet_example::weights::SubstrateWeight; - type MagicNumber = MagicNumber; -} - parameter_types! { pub const TechnicalMotionDuration: BlockNumber = 5 * DAYS; pub const TechnicalMaxProposals: u32 = 100; pub const TechnicalMaxMembers: u32 = 100; } + type TechnicalCollective = pallet_collective::Instance2; impl pallet_collective::Config for Runtime { type Origin = Origin; @@ -1133,7 +1124,6 @@ construct_runtime!( Mmr: pallet_mmr::{Pallet, Storage}, Lottery: pallet_lottery::{Pallet, Call, Storage, Event}, Gilt: pallet_gilt::{Pallet, Call, Storage, Event, Config}, - Example: pallet_example::{Pallet, Call, Storage, Event}, } ); @@ -1480,7 +1470,6 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_democracy, Democracy); add_benchmark!(params, batches, pallet_election_provider_multi_phase, ElectionProviderMultiPhase); add_benchmark!(params, batches, pallet_elections_phragmen, Elections); - add_benchmark!(params, batches, pallet_example, Example); add_benchmark!(params, batches, pallet_gilt, Gilt); add_benchmark!(params, batches, pallet_grandpa, Grandpa); add_benchmark!(params, batches, pallet_identity, Identity); From a103aca03a6aa565d7399eeec2a11440308b3936 Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Thu, 25 Mar 2021 20:13:22 +0800 Subject: [PATCH 16/18] rm pallet-example Signed-off-by: Jimmy Chu --- Cargo.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 369a845839d78..480ceb47c20a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4300,7 +4300,6 @@ dependencies = [ "pallet-democracy", "pallet-election-provider-multi-phase", "pallet-elections-phragmen", - "pallet-example", "pallet-gilt", "pallet-grandpa", "pallet-identity", From f28e4307624ff986cce078c1a529a863a96c6953 Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Mon, 29 Mar 2021 15:58:48 +0800 Subject: [PATCH 17/18] Update frame/example/src/benchmarking.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- frame/example/src/benchmarking.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/example/src/benchmarking.rs b/frame/example/src/benchmarking.rs index 73c9a456b3b04..64602ca41cee9 100644 --- a/frame/example/src/benchmarking.rs +++ b/frame/example/src/benchmarking.rs @@ -46,7 +46,7 @@ benchmarks!{ // This will measure the execution time of `accumulate_dummy` for b in [1..1000] range. // The benchmark execution phase is shorthanded. When the name of the benchmark case is the same - // as the extrinsic call. `_(...)` is used to represent the extrinsic name. + // as the extrinsic call. `_(...)` is used to represent the extrinsic name. // The benchmark verification phase is omitted. accumulate_dummy { let b in 1 .. 1000; From 60b614d00adefbdb435e0a43ce47cb48b398b0bc Mon Sep 17 00:00:00 2001 From: Jimmy Chu Date: Mon, 29 Mar 2021 20:02:21 +0800 Subject: [PATCH 18/18] additional comment on manually configuring weight Signed-off-by: Jimmy Chu --- frame/example/src/lib.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index b410361037461..fd1bc292ac8aa 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -273,7 +273,6 @@ use sp_runtime::{ ValidTransaction, TransactionValidityError, InvalidTransaction, TransactionValidity, }, }; - use log::info; // Re-export pallet items so that they can be accessed from the crate namespace. @@ -294,7 +293,7 @@ const MILLICENTS: u32 = 1_000_000_000; // the arguments and makes a decision based upon them. // // The `WeightData` trait has access to the arguments of the dispatch that it wants to assign a -// weight to. Nonetheless, the trait itself can not make any assumptions about what the generic type +// weight to. Nonetheless, the trait itself cannot make any assumptions about what the generic type // of the arguments (`T`) is. Based on our needs, we could replace `T` with a more concrete type // while implementing the trait. The `pallet::weight` expects whatever implements `WeighData` to // replace `T` with a tuple of the dispatch arguments. This is exactly how we will craft the @@ -304,6 +303,13 @@ const MILLICENTS: u32 = 1_000_000_000; // - The final weight of each dispatch is calculated as the argument of the call multiplied by the // parameter given to the `WeightForSetDummy`'s constructor. // - assigns a dispatch class `operational` if the argument of the call is more than 1000. +// +// More information can be read at: +// - https://substrate.dev/docs/en/knowledgebase/learn-substrate/weight +// - https://substrate.dev/docs/en/knowledgebase/runtime/fees#default-weight-annotations +// +// Manually configuring weight is an advanced operation and what you really need may well be +// fulfilled by running the benchmarking toolchain. Refer to `benchmarking.rs` file. struct WeightForSetDummy(BalanceOf); impl WeighData<(&BalanceOf,)> for WeightForSetDummy @@ -354,6 +360,8 @@ pub mod pallet { /// The overarching event type. type Event: From> + IsType<::Event>; + + /// Type representing the weight of this pallet type WeightInfo: WeightInfo; }