diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index bee8278b46..8f9d7f531c 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -4201,6 +4201,7 @@ dependencies = [ name = "pallet-indices" version = "2.0.0-rc2" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "pallet-balances", diff --git a/substrate/bin/node/runtime/Cargo.toml b/substrate/bin/node/runtime/Cargo.toml index 4f304e6ace..be01b267fb 100644 --- a/substrate/bin/node/runtime/Cargo.toml +++ b/substrate/bin/node/runtime/Cargo.toml @@ -153,6 +153,7 @@ runtime-benchmarks = [ "pallet-elections-phragmen/runtime-benchmarks", "pallet-identity/runtime-benchmarks", "pallet-im-online/runtime-benchmarks", + "pallet-indices/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index a1cff7df91..5a56ca4a7b 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1081,6 +1081,7 @@ impl_runtime_apis! { add_benchmark!(params, batches, b"elections", Elections); add_benchmark!(params, batches, b"identity", Identity); add_benchmark!(params, batches, b"im-online", ImOnline); + add_benchmark!(params, batches, b"indices", Indices); add_benchmark!(params, batches, b"multisig", Multisig); add_benchmark!(params, batches, b"offences", OffencesBench::); add_benchmark!(params, batches, b"proxy", Proxy); diff --git a/substrate/frame/indices/Cargo.toml b/substrate/frame/indices/Cargo.toml index d4217ca49c..3d01d0f15b 100644 --- a/substrate/frame/indices/Cargo.toml +++ b/substrate/frame/indices/Cargo.toml @@ -22,6 +22,8 @@ sp-core = { version = "2.0.0-rc2", default-features = false, path = "../../primi frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } +frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } + [dev-dependencies] pallet-balances = { version = "2.0.0-rc2", path = "../balances" } @@ -38,3 +40,7 @@ std = [ "sp-runtime/std", "frame-system/std", ] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", +] diff --git a/substrate/frame/indices/src/benchmarking.rs b/substrate/frame/indices/src/benchmarking.rs new file mode 100644 index 0000000000..843e4e2faa --- /dev/null +++ b/substrate/frame/indices/src/benchmarking.rs @@ -0,0 +1,109 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2020 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. + +// Benchmarks for Indices Pallet + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; +use frame_system::RawOrigin; +use frame_benchmarking::{benchmarks, account}; +use sp_runtime::traits::Bounded; + +use crate::Module as Indices; + +const SEED: u32 = 0; + +benchmarks! { + _ { } + + claim { + // Index being claimed + let i in 0 .. 1000; + let account_index = T::AccountIndex::from(i); + let caller: T::AccountId = account("caller", 0, SEED); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + }: _(RawOrigin::Signed(caller.clone()), account_index) + verify { + assert_eq!(Accounts::::get(account_index).unwrap().0, caller); + } + + transfer { + // Index being claimed + let i in 0 .. 1000; + let account_index = T::AccountIndex::from(i); + // Setup accounts + let caller: T::AccountId = account("caller", 0, SEED); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + let recipient: T::AccountId = account("recipient", i, SEED); + T::Currency::make_free_balance_be(&recipient, BalanceOf::::max_value()); + // Claim the index + Indices::::claim(RawOrigin::Signed(caller.clone()).into(), account_index)?; + }: _(RawOrigin::Signed(caller.clone()), recipient.clone(), account_index) + verify { + assert_eq!(Accounts::::get(account_index).unwrap().0, recipient); + } + + free { + // Index being claimed + let i in 0 .. 1000; + let account_index = T::AccountIndex::from(i); + // Setup accounts + let caller: T::AccountId = account("caller", 0, SEED); + T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + // Claim the index + Indices::::claim(RawOrigin::Signed(caller.clone()).into(), account_index)?; + }: _(RawOrigin::Signed(caller.clone()), account_index) + verify { + assert_eq!(Accounts::::get(account_index), None); + } + + force_transfer { + // Index being claimed + let i in 0 .. 1000; + let account_index = T::AccountIndex::from(i); + // Setup accounts + let original: T::AccountId = account("original", 0, SEED); + T::Currency::make_free_balance_be(&original, BalanceOf::::max_value()); + let recipient: T::AccountId = account("recipient", i, SEED); + T::Currency::make_free_balance_be(&recipient, BalanceOf::::max_value()); + // Claim the index + Indices::::claim(RawOrigin::Signed(original).into(), account_index)?; + }: _(RawOrigin::Root, recipient.clone(), account_index) + verify { + assert_eq!(Accounts::::get(account_index).unwrap().0, recipient); + } + + // TODO in another PR: lookup and unlookup trait weights (not critical) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{new_test_ext, Test}; + use frame_support::assert_ok; + + #[test] + fn test_benchmarks() { + new_test_ext().execute_with(|| { + assert_ok!(test_benchmark_claim::()); + assert_ok!(test_benchmark_transfer::()); + assert_ok!(test_benchmark_free::()); + assert_ok!(test_benchmark_force_transfer::()); + }); + } +} diff --git a/substrate/frame/indices/src/lib.rs b/substrate/frame/indices/src/lib.rs index 77a73a21ac..ef4e0082f4 100644 --- a/substrate/frame/indices/src/lib.rs +++ b/substrate/frame/indices/src/lib.rs @@ -28,12 +28,14 @@ use sp_runtime::traits::{ use frame_support::{Parameter, decl_module, decl_error, decl_event, decl_storage, ensure}; use frame_support::dispatch::DispatchResult; use frame_support::traits::{Currency, ReservableCurrency, Get, BalanceStatus::Reserved}; +use frame_support::weights::constants::WEIGHT_PER_MICROS; use frame_system::{ensure_signed, ensure_root}; use self::address::Address as RawAddress; mod mock; pub mod address; mod tests; +mod benchmarking; pub type Address = RawAddress<::AccountId, ::AccountIndex>; type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; @@ -113,8 +115,11 @@ decl_module! { /// - One storage mutation (codec `O(1)`). /// - One reserve operation. /// - One event. + /// ------------------- + /// - Base Weight: 28.69 µs + /// - DB Weight: 1 Read/Write (Accounts) /// # - #[weight = 0] + #[weight = T::DbWeight::get().reads_writes(1, 1) + 30 * WEIGHT_PER_MICROS] fn claim(origin, index: T::AccountIndex) { let who = ensure_signed(origin)?; @@ -141,8 +146,13 @@ decl_module! { /// - One storage mutation (codec `O(1)`). /// - One transfer operation. /// - One event. + /// ------------------- + /// - Base Weight: 33.74 µs + /// - DB Weight: + /// - Reads: Indices Accounts, System Account (recipient) + /// - Writes: Indices Accounts, System Account (recipient) /// # - #[weight = 0] + #[weight = T::DbWeight::get().reads_writes(2, 2) + 35 * WEIGHT_PER_MICROS] fn transfer(origin, new: T::AccountId, index: T::AccountIndex) { let who = ensure_signed(origin)?; ensure!(who != new, Error::::NotTransfer); @@ -172,8 +182,11 @@ decl_module! { /// - One storage mutation (codec `O(1)`). /// - One reserve operation. /// - One event. + /// ------------------- + /// - Base Weight: 25.53 µs + /// - DB Weight: 1 Read/Write (Accounts) /// # - #[weight = 0] + #[weight = T::DbWeight::get().reads_writes(1, 1) + 25 * WEIGHT_PER_MICROS] fn free(origin, index: T::AccountIndex) { let who = ensure_signed(origin)?; @@ -201,8 +214,13 @@ decl_module! { /// - One storage mutation (codec `O(1)`). /// - Up to one reserve operation. /// - One event. + /// ------------------- + /// - Base Weight: 26.83 µs + /// - DB Weight: + /// - Reads: Indices Accounts, System Account (original owner) + /// - Writes: Indices Accounts, System Account (original owner) /// # - #[weight = 0] + #[weight = T::DbWeight::get().reads_writes(2, 2) + 25 * WEIGHT_PER_MICROS] fn force_transfer(origin, new: T::AccountId, index: T::AccountIndex) { ensure_root(origin)?; diff --git a/substrate/frame/multisig/src/benchmarking.rs b/substrate/frame/multisig/src/benchmarking.rs index 0c603be916..fa2ec52e6b 100644 --- a/substrate/frame/multisig/src/benchmarking.rs +++ b/substrate/frame/multisig/src/benchmarking.rs @@ -24,7 +24,7 @@ use frame_system::RawOrigin; use frame_benchmarking::{benchmarks, account}; use sp_runtime::traits::Saturating; -use crate::Module as Utility; +use crate::Module as Multisig; const SEED: u32 = 0; @@ -66,9 +66,9 @@ benchmarks! { let mut signatories2 = signatories.clone(); let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; // before the call, get the timepoint - let timepoint = Utility::::timepoint(); + let timepoint = Multisig::::timepoint(); // Create the multi - Utility::::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone())?; + Multisig::::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone())?; let caller2 = signatories2.remove(0); }: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call) @@ -81,15 +81,15 @@ benchmarks! { let mut signatories2 = signatories.clone(); let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; // before the call, get the timepoint - let timepoint = Utility::::timepoint(); + let timepoint = Multisig::::timepoint(); // Create the multi - Utility::::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone())?; + Multisig::::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone())?; // Everyone except the first person approves for i in 1 .. s - 1 { let mut signatories_loop = signatories2.clone(); let caller_loop = signatories_loop.remove(i as usize); let o = RawOrigin::Signed(caller_loop).into(); - Utility::::as_multi(o, s as u16, signatories_loop, Some(timepoint), call.clone())?; + Multisig::::as_multi(o, s as u16, signatories_loop, Some(timepoint), call.clone())?; } let caller2 = signatories2.remove(0); }: as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call) @@ -115,9 +115,9 @@ benchmarks! { let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; let call_hash = call.using_encoded(blake2_256); // before the call, get the timepoint - let timepoint = Utility::::timepoint(); + let timepoint = Multisig::::timepoint(); // Create the multi - Utility::::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone())?; + Multisig::::as_multi(RawOrigin::Signed(caller).into(), s as u16, signatories, None, call.clone())?; let caller2 = signatories2.remove(0); }: approve_as_multi(RawOrigin::Signed(caller2), s as u16, signatories2, Some(timepoint), call_hash) @@ -129,10 +129,10 @@ benchmarks! { let (mut signatories, call) = setup_multi::(s, z)?; let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; let call_hash = call.using_encoded(blake2_256); - let timepoint = Utility::::timepoint(); + let timepoint = Multisig::::timepoint(); // Create the multi let o = RawOrigin::Signed(caller.clone()).into(); - Utility::::as_multi(o, s as u16, signatories.clone(), None, call.clone())?; + Multisig::::as_multi(o, s as u16, signatories.clone(), None, call.clone())?; }: _(RawOrigin::Signed(caller), s as u16, signatories, timepoint, call_hash) } diff --git a/substrate/frame/multisig/src/tests.rs b/substrate/frame/multisig/src/tests.rs index 77855c6482..067ef4cf98 100644 --- a/substrate/frame/multisig/src/tests.rs +++ b/substrate/frame/multisig/src/tests.rs @@ -104,6 +104,8 @@ impl Filter for TestIsCallable { fn filter(c: &Call) -> bool { match *c { Call::Balances(_) => true, + // Needed for benchmarking + Call::System(frame_system::Call::remark(_)) => true, _ => false, } } @@ -399,7 +401,7 @@ fn multisig_1_of_3_works() { #[test] fn multisig_filters() { new_test_ext().execute_with(|| { - let call = Box::new(Call::System(frame_system::Call::remark(vec![]))); + let call = Box::new(Call::System(frame_system::Call::set_code(vec![]))); assert_noop!( Multisig::as_multi(Origin::signed(1), 1, vec![], None, call.clone()), Error::::Uncallable, diff --git a/substrate/frame/utility/src/benchmarking.rs b/substrate/frame/utility/src/benchmarking.rs index 474009d11d..27696404bf 100644 --- a/substrate/frame/utility/src/benchmarking.rs +++ b/substrate/frame/utility/src/benchmarking.rs @@ -22,8 +22,6 @@ use super::*; use frame_system::RawOrigin; use frame_benchmarking::{benchmarks, account}; -use sp_runtime::traits::Saturating; -use crate::Module as Utility; const SEED: u32 = 0;