From 7b334921c49968c49698de7ca91abc2e9ae99171 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 16 Jan 2020 20:32:52 +0100 Subject: [PATCH 01/50] Starting --- frame/identity/src/lib.rs | 35 ++++++++++++++++++++++++++++++-- primitives/runtime/src/traits.rs | 8 ++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index b23407406b6a4..01c2b49122a50 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -70,7 +70,7 @@ use sp_std::{fmt::Debug, ops::Add, iter::once}; use enumflags2::BitFlags; use codec::{Encode, Decode}; use sp_runtime::{DispatchResult, RuntimeDebug}; -use sp_runtime::traits::{StaticLookup, EnsureOrigin, Zero, AppendZerosInput}; +use sp_runtime::traits::{StaticLookup, EnsureOrigin, Zero, AppendZerosInput, Benchmarking}; use frame_support::{ decl_module, decl_event, decl_storage, ensure, decl_error, traits::{Currency, ReservableCurrency, OnUnbalanced, Get}, @@ -862,8 +862,39 @@ decl_module! { } } +mod benchmarking { + mod set_identity { + fn components() -> Vec<(&'static str, u32, u32)> { + vec![ + // Registrar Count + ("R", 1, 16), + // Additional Field Count + ("X", 1, 20) + ] + } + + /// Assumes externalities are set up with a mutable state. + /// + /// Panics if `component_name` isn't from `set_identity::components` or `component_value` is out of + /// the range of `set_identity::components`. + /// + /// Sets up state randomly and returns a randomly generated `set_identity` with sensible (fixed) + /// values for all complexity components except those mentioned in the identity. + fn instance(components: &[(&'static str, u32)]) -> Call { + Call::set_identity::default() + } + } +} + +impl Benchmarking for Module { + type BenchmarkResults = bool; + fn run_benchmarks() -> Vec { + return vec![true] + } +} + #[cfg(test)] -mod tests { +pub mod tests { use super::*; use sp_runtime::traits::BadOrigin; diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index c02856d20d917..5c876de79acb6 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1263,6 +1263,14 @@ pub trait BlockIdTo { ) -> Result>, Self::Error>; } +/// The module benchmarking trait. +pub trait Benchmarking { + /// Type for the results of benchmarks. + type BenchmarkResults; + /// Run the benchmarks for this module. + fn run_benchmarks() -> Vec; +} + #[cfg(test)] mod tests { use super::*; From 3b12740a15e7ce364745fe0cbfd9a6fc8de4bd06 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 21 Jan 2020 02:41:11 +0100 Subject: [PATCH 02/50] closer --- frame/identity/src/lib.rs | 87 ++++++++++++++++++++++++++++---- primitives/runtime/src/traits.rs | 4 ++ 2 files changed, 82 insertions(+), 9 deletions(-) diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 01c2b49122a50..15093557e13f5 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -862,9 +862,17 @@ decl_module! { } } -mod benchmarking { - mod set_identity { - fn components() -> Vec<(&'static str, u32, u32)> { +#[cfg(test)] +pub mod benchmarking { + + pub mod set_identity { + use crate::*; + use crate::tests::*; + use frame_support::{ + assert_ok + }; + + pub fn components() -> Vec<(&'static str, u32, u32)> { vec![ // Registrar Count ("R", 1, 16), @@ -880,16 +888,69 @@ mod benchmarking { /// /// Sets up state randomly and returns a randomly generated `set_identity` with sensible (fixed) /// values for all complexity components except those mentioned in the identity. - fn instance(components: &[(&'static str, u32)]) -> Call { - Call::set_identity::default() + fn instance(components: &[(&'static str, u32)]) -> Call + { + // Add r registrars + let r = components.iter().find(|&c| c.0 == "R").unwrap(); + for i in 0..r.1 { + assert_ok!(Identity::add_registrar(Origin::signed(1), i.into())); + assert_ok!(Identity::set_fee(Origin::signed(i.into()), 0, 10)); + let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); + assert_ok!(Identity::set_fields(Origin::signed(i.into()), 0, fields)); + } + + // Create identity info with x additional fields + let x = components.iter().find(|&c| c.0 == "R").unwrap(); + let data = Data::Raw(vec![0; x.1 as usize]); + let info = IdentityInfo { + additional: vec![(data.clone(), data.clone()); 3], + display: data.clone(), + legal: data.clone(), + web: data.clone(), + riot: data.clone(), + email: data.clone(), + pgp_fingerprint: Some([0; 20]), + image: data.clone(), + twitter: data.clone(), + }; + + // Return the `set_identity` call + return Call::set_identity(info) } } } +#[cfg(test)] impl Benchmarking for Module { type BenchmarkResults = bool; + const STEPS: usize = 100; + const REPEATS: usize = 10; + fn run_benchmarks() -> Vec { - return vec![true] + // first one is set_identity. + let components = benchmarking::set_identity::components(); + for (i, (name, low, high)) in components.iter().enumerate() { + for j in 0..STEPS { + let step = j * (high - low) / 100 + low; + + + let c = components.iter().enumerate() + .map(|(j, (n, low, high))| + (n, if x == y { step } else { (high - low) / 2 + low }) + ).collect(); + + + // for x in 0..REPEATS { + // let instance = set_identity::instance(&c); + // timer.begin(); + // assert_ok!(instance.dispatch()); + // let t = timer.elapsed(); + // BenchmarkResults.calls["set_identity"].push((c, t)); + // } + // } + // } + // } + return vec![true]; } } @@ -900,7 +961,7 @@ pub mod tests { use sp_runtime::traits::BadOrigin; use frame_support::{ assert_ok, assert_noop, impl_outer_origin, parameter_types, weights::Weight, - ord_parameter_types + ord_parameter_types, impl_outer_dispatch, }; use sp_core::H256; use frame_system::EnsureSignedBy; @@ -914,6 +975,14 @@ pub mod tests { pub enum Origin for Test where system = frame_system {} } + impl_outer_dispatch! { + pub enum Call for Test where origin: Origin { + frame_system::System, + pallet_balances::Balances, + pallet_identity::Identity, + } + } + // For testing the module, we construct most of a mock runtime. This means // first constructing a configuration type (`Test`) which `impl`s each of the // configuration traits of modules we want to use. @@ -930,7 +999,7 @@ pub mod tests { type Index = u64; type BlockNumber = u64; type Hash = H256; - type Call = (); + type Call = Call; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; @@ -983,7 +1052,7 @@ pub mod tests { } type System = frame_system::Module; type Balances = pallet_balances::Module; - type Identity = Module; + pub type Identity = Module; // This function basically just builds a genesis storage key/value store according to // our desired mockup. diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 5c876de79acb6..47782997e96b2 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1267,6 +1267,10 @@ pub trait BlockIdTo { pub trait Benchmarking { /// Type for the results of benchmarks. type BenchmarkResults; + /// Number of steps to take between variable ranges. + const STEPS: usize; + /// Number of benchmarking repetitions. + const REPEATS: usize; /// Run the benchmarks for this module. fn run_benchmarks() -> Vec; } From 55cf8b6a570c0db6850b457f094f2974a88a8c47 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 21 Jan 2020 11:36:41 +0100 Subject: [PATCH 03/50] Compiles! --- frame/identity/src/lib.rs | 46 +++++++++++++++++--------------- primitives/runtime/src/traits.rs | 4 +-- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 15093557e13f5..da5e76ae78546 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -70,7 +70,7 @@ use sp_std::{fmt::Debug, ops::Add, iter::once}; use enumflags2::BitFlags; use codec::{Encode, Decode}; use sp_runtime::{DispatchResult, RuntimeDebug}; -use sp_runtime::traits::{StaticLookup, EnsureOrigin, Zero, AppendZerosInput, Benchmarking}; +use sp_runtime::traits::{StaticLookup, EnsureOrigin, Zero, AppendZerosInput, Benchmarking, Dispatchable}; use frame_support::{ decl_module, decl_event, decl_storage, ensure, decl_error, traits::{Currency, ReservableCurrency, OnUnbalanced, Get}, @@ -888,7 +888,7 @@ pub mod benchmarking { /// /// Sets up state randomly and returns a randomly generated `set_identity` with sensible (fixed) /// values for all complexity components except those mentioned in the identity. - fn instance(components: &[(&'static str, u32)]) -> Call + pub fn instance(components: &[(&'static str, u32)]) -> Call { // Add r registrars let r = components.iter().find(|&c| c.0 == "R").unwrap(); @@ -923,33 +923,35 @@ pub mod benchmarking { #[cfg(test)] impl Benchmarking for Module { type BenchmarkResults = bool; - const STEPS: usize = 100; - const REPEATS: usize = 10; + const STEPS: u32 = 100; + const REPEATS: u32 = 10; fn run_benchmarks() -> Vec { // first one is set_identity. let components = benchmarking::set_identity::components(); - for (i, (name, low, high)) in components.iter().enumerate() { - for j in 0..STEPS { - let step = j * (high - low) / 100 + low; - - - let c = components.iter().enumerate() - .map(|(j, (n, low, high))| - (n, if x == y { step } else { (high - low) / 2 + low }) + // Select the component we will be benchmarking. Each component will be benchmarked. + for (name, low, high) in components.iter() { + // Select create up to `STEPS` steps for that component between high and low. + let step_size = ((high - low) / Self::STEPS).min(1); + let num_of_steps = Self::STEPS / step_size; + for s in 0..num_of_steps { + let component_value = step_size * s; + + let c: Vec<(&'static str, u32)> = components.iter() + .map(|(n, l, h)| + (*n, if n == name { component_value } else { (h - l) / 2 + l }) ).collect(); - // for x in 0..REPEATS { - // let instance = set_identity::instance(&c); - // timer.begin(); - // assert_ok!(instance.dispatch()); - // let t = timer.elapsed(); - // BenchmarkResults.calls["set_identity"].push((c, t)); - // } - // } - // } - // } + for _r in 0..Self::REPEATS { + let instance = benchmarking::set_identity::instance(&c); + //timer.begin(); + frame_support::assert_ok!(instance.dispatch(Some(0).into())); + //let t = timer.elapsed(); + //BenchmarkResults.calls["set_identity"].push((c, t)); + } + } + } return vec![true]; } } diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 47782997e96b2..9cc10b8e6bc8f 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1268,9 +1268,9 @@ pub trait Benchmarking { /// Type for the results of benchmarks. type BenchmarkResults; /// Number of steps to take between variable ranges. - const STEPS: usize; + const STEPS: u32; /// Number of benchmarking repetitions. - const REPEATS: usize; + const REPEATS: u32; /// Run the benchmarks for this module. fn run_benchmarks() -> Vec; } From 9da52bb9348b5d81a7199ba6ce48d678d42ab91d Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 21 Jan 2020 11:38:32 +0100 Subject: [PATCH 04/50] comments --- frame/identity/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index da5e76ae78546..96b55fa9a5033 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -931,12 +931,14 @@ impl Benchmarking for Module { let components = benchmarking::set_identity::components(); // Select the component we will be benchmarking. Each component will be benchmarked. for (name, low, high) in components.iter() { - // Select create up to `STEPS` steps for that component between high and low. + // Create up to `STEPS` steps for that component between high and low. let step_size = ((high - low) / Self::STEPS).min(1); let num_of_steps = Self::STEPS / step_size; for s in 0..num_of_steps { + // This is the value we will be testing for component `name` let component_value = step_size * s; + // Select the mid value for all the other components. let c: Vec<(&'static str, u32)> = components.iter() .map(|(n, l, h)| (*n, if n == name { component_value } else { (h - l) / 2 + l }) From 27127c0f4caeac9ac6a748b994ce9bcdf78f93ea Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 21 Jan 2020 12:04:58 +0100 Subject: [PATCH 05/50] Create seperate mock --- frame/identity/Cargo.toml | 2 - frame/identity/src/benchmarking.rs | 150 +++++++++++++++++++++++++++++ frame/identity/src/lib.rs | 61 +----------- 3 files changed, 152 insertions(+), 61 deletions(-) create mode 100644 frame/identity/src/benchmarking.rs diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 7962c2a1c62bf..12feab0cd1a24 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -13,8 +13,6 @@ sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/ sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "2.0.0", default-features = false, path = "../support" } frame-system = { version = "2.0.0", default-features = false, path = "../system" } - -[dev-dependencies] sp-core = { version = "2.0.0", path = "../../primitives/core" } pallet-balances = { version = "2.0.0", path = "../balances" } diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs new file mode 100644 index 0000000000000..f1393ee2e520c --- /dev/null +++ b/frame/identity/src/benchmarking.rs @@ -0,0 +1,150 @@ +use super::*; + +use frame_support::{ + assert_ok, impl_outer_origin, parameter_types, weights::Weight, + ord_parameter_types, impl_outer_dispatch, +}; +use sp_core::H256; +use frame_system::EnsureSignedBy; +// 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::{ + Perbill, testing::Header, traits::{BlakeTwo256, IdentityLookup}, +}; + +impl_outer_origin! { + pub enum Origin for Benchmark where system = frame_system {} +} + +impl_outer_dispatch! { + pub enum Call for Benchmark where origin: Origin { + frame_system::System, + pallet_balances::Balances, + pallet_identity::Identity, + } +} + +// For testing the module, we construct most of a mock runtime. This means +// first constructing a configuration type (`Benchmark`) which `impl`s each of the +// configuration traits of modules we want to use. +#[derive(Clone, Eq, PartialEq)] +pub struct Benchmark; +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl frame_system::Trait for Benchmark { + 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 = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); +} +parameter_types! { + pub const ExistentialDeposit: u64 = 0; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; +} +impl pallet_balances::Trait for Benchmark { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnReapAccount = System; + type OnNewAccount = (); + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; +} +parameter_types! { + pub const BasicDeposit: u64 = 10; + pub const FieldDeposit: u64 = 10; + pub const SubAccountDeposit: u64 = 10; + pub const MaximumSubAccounts: u32 = 2; +} +ord_parameter_types! { + pub const One: u64 = 1; + pub const Two: u64 = 2; +} +impl Trait for Benchmark { + type Event = (); + type Currency = Balances; + type Slashed = (); + type BasicDeposit = BasicDeposit; + type FieldDeposit = FieldDeposit; + type SubAccountDeposit = SubAccountDeposit; + type MaximumSubAccounts = MaximumSubAccounts; + type RegistrarOrigin = EnsureSignedBy; + type ForceOrigin = EnsureSignedBy; +} +type System = frame_system::Module; +type Balances = pallet_balances::Module; +pub type Identity = Module; + +pub type BalancesCall = pallet_balances::Call; +pub type IdentityCall = crate::Call; + + +pub mod set_identity { + use super::*; + + pub fn components() -> Vec<(&'static str, u32, u32)> { + vec![ + // Registrar Count + ("R", 1, 16), + // Additional Field Count + ("X", 1, 20) + ] + } + + /// Assumes externalities are set up with a mutable state. + /// + /// Panics if `component_name` isn't from `set_identity::components` or `component_value` is out of + /// the range of `set_identity::components`. + /// + /// Sets up state randomly and returns a randomly generated `set_identity` with sensible (fixed) + /// values for all complexity components except those mentioned in the identity. + pub fn instance(components: &[(&'static str, u32)]) -> Call + { + // Add r registrars + let r = components.iter().find(|&c| c.0 == "R").unwrap(); + for i in 0..r.1 { + assert_ok!(Identity::add_registrar(Origin::signed(1), i.into())); + assert_ok!(Identity::set_fee(Origin::signed(i.into()), 0, 10)); + let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); + assert_ok!(Identity::set_fields(Origin::signed(i.into()), 0, fields)); + } + + // Create identity info with x additional fields + let x = components.iter().find(|&c| c.0 == "R").unwrap(); + let data = Data::Raw(vec![0; x.1 as usize]); + let info = IdentityInfo { + additional: vec![(data.clone(), data.clone()); 3], + display: data.clone(), + legal: data.clone(), + web: data.clone(), + riot: data.clone(), + email: data.clone(), + pgp_fingerprint: Some([0; 20]), + image: data.clone(), + twitter: data.clone(), + }; + + // Return the `set_identity` call + return Call::Identity(IdentityCall::set_identity(info)) + } +} \ No newline at end of file diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 96b55fa9a5033..6de5bca59b901 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -78,6 +78,8 @@ use frame_support::{ }; use frame_system::{self as system, ensure_signed, ensure_root}; +mod benchmarking; + type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; @@ -862,65 +864,6 @@ decl_module! { } } -#[cfg(test)] -pub mod benchmarking { - - pub mod set_identity { - use crate::*; - use crate::tests::*; - use frame_support::{ - assert_ok - }; - - pub fn components() -> Vec<(&'static str, u32, u32)> { - vec![ - // Registrar Count - ("R", 1, 16), - // Additional Field Count - ("X", 1, 20) - ] - } - - /// Assumes externalities are set up with a mutable state. - /// - /// Panics if `component_name` isn't from `set_identity::components` or `component_value` is out of - /// the range of `set_identity::components`. - /// - /// Sets up state randomly and returns a randomly generated `set_identity` with sensible (fixed) - /// values for all complexity components except those mentioned in the identity. - pub fn instance(components: &[(&'static str, u32)]) -> Call - { - // Add r registrars - let r = components.iter().find(|&c| c.0 == "R").unwrap(); - for i in 0..r.1 { - assert_ok!(Identity::add_registrar(Origin::signed(1), i.into())); - assert_ok!(Identity::set_fee(Origin::signed(i.into()), 0, 10)); - let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); - assert_ok!(Identity::set_fields(Origin::signed(i.into()), 0, fields)); - } - - // Create identity info with x additional fields - let x = components.iter().find(|&c| c.0 == "R").unwrap(); - let data = Data::Raw(vec![0; x.1 as usize]); - let info = IdentityInfo { - additional: vec![(data.clone(), data.clone()); 3], - display: data.clone(), - legal: data.clone(), - web: data.clone(), - riot: data.clone(), - email: data.clone(), - pgp_fingerprint: Some([0; 20]), - image: data.clone(), - twitter: data.clone(), - }; - - // Return the `set_identity` call - return Call::set_identity(info) - } - } -} - -#[cfg(test)] impl Benchmarking for Module { type BenchmarkResults = bool; const STEPS: u32 = 100; From ae84e9fb4b276e640ef4e8e88e648d05853cbb4b Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 21 Jan 2020 12:11:32 +0100 Subject: [PATCH 06/50] Remove changes to test env --- frame/identity/src/benchmarking.rs | 11 +++++------ frame/identity/src/lib.rs | 16 ++++------------ 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index f1393ee2e520c..fbe19310792ce 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -93,12 +93,10 @@ impl Trait for Benchmark { } type System = frame_system::Module; type Balances = pallet_balances::Module; -pub type Identity = Module; +type Identity = Module; -pub type BalancesCall = pallet_balances::Call; pub type IdentityCall = crate::Call; - pub mod set_identity { use super::*; @@ -118,7 +116,7 @@ pub mod set_identity { /// /// Sets up state randomly and returns a randomly generated `set_identity` with sensible (fixed) /// values for all complexity components except those mentioned in the identity. - pub fn instance(components: &[(&'static str, u32)]) -> Call + pub fn instance(components: &[(&'static str, u32)]) -> Call { // Add r registrars let r = components.iter().find(|&c| c.0 == "R").unwrap(); @@ -131,9 +129,10 @@ pub mod set_identity { // Create identity info with x additional fields let x = components.iter().find(|&c| c.0 == "R").unwrap(); - let data = Data::Raw(vec![0; x.1 as usize]); + // 32 byte data that we reuse below + let data = Data::Raw(vec![0; 32]); let info = IdentityInfo { - additional: vec![(data.clone(), data.clone()); 3], + additional: vec![(data.clone(), data.clone()); x.1 as usize], display: data.clone(), legal: data.clone(), web: data.clone(), diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 6de5bca59b901..da7e0e83489fa 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -902,13 +902,13 @@ impl Benchmarking for Module { } #[cfg(test)] -pub mod tests { +mod tests { use super::*; use sp_runtime::traits::BadOrigin; use frame_support::{ assert_ok, assert_noop, impl_outer_origin, parameter_types, weights::Weight, - ord_parameter_types, impl_outer_dispatch, + ord_parameter_types, }; use sp_core::H256; use frame_system::EnsureSignedBy; @@ -922,14 +922,6 @@ pub mod tests { pub enum Origin for Test where system = frame_system {} } - impl_outer_dispatch! { - pub enum Call for Test where origin: Origin { - frame_system::System, - pallet_balances::Balances, - pallet_identity::Identity, - } - } - // For testing the module, we construct most of a mock runtime. This means // first constructing a configuration type (`Test`) which `impl`s each of the // configuration traits of modules we want to use. @@ -946,7 +938,7 @@ pub mod tests { type Index = u64; type BlockNumber = u64; type Hash = H256; - type Call = Call; + type Call = (); type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; @@ -999,7 +991,7 @@ pub mod tests { } type System = frame_system::Module; type Balances = pallet_balances::Module; - pub type Identity = Module; + type Identity = Module; // This function basically just builds a genesis storage key/value store according to // our desired mockup. From 06d1173cfa4879b95c377b0055088ba64d7208bc Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 21 Jan 2020 12:58:30 +0100 Subject: [PATCH 07/50] Fix step calculation --- frame/identity/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index da7e0e83489fa..27482b360ced4 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -876,7 +876,7 @@ impl Benchmarking for Module { for (name, low, high) in components.iter() { // Create up to `STEPS` steps for that component between high and low. let step_size = ((high - low) / Self::STEPS).min(1); - let num_of_steps = Self::STEPS / step_size; + let num_of_steps = (high - low) / step_size; for s in 0..num_of_steps { // This is the value we will be testing for component `name` let component_value = step_size * s; From 9f25cf5e9f78255ee4ee183ddc43c99b472c9cc7 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 22 Jan 2020 12:29:25 +0100 Subject: [PATCH 08/50] Add host function --- frame/identity/src/lib.rs | 14 +++++++++----- primitives/io/src/lib.rs | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 27482b360ced4..c38ec1914e52f 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -865,13 +865,15 @@ decl_module! { } impl Benchmarking for Module { - type BenchmarkResults = bool; + type BenchmarkResults = (Vec<(&'static str, u32)>, u128); const STEPS: u32 = 100; const REPEATS: u32 = 10; fn run_benchmarks() -> Vec { // first one is set_identity. let components = benchmarking::set_identity::components(); + // results go here + let mut results: Vec = Vec::new(); // Select the component we will be benchmarking. Each component will be benchmarked. for (name, low, high) in components.iter() { // Create up to `STEPS` steps for that component between high and low. @@ -888,16 +890,18 @@ impl Benchmarking for Module { ).collect(); + for _r in 0..Self::REPEATS { let instance = benchmarking::set_identity::instance(&c); - //timer.begin(); + let start = sp_io::benchmark::now(); frame_support::assert_ok!(instance.dispatch(Some(0).into())); - //let t = timer.elapsed(); - //BenchmarkResults.calls["set_identity"].push((c, t)); + let finish = sp_io::benchmark::now(); + let elapsed = finish - start; + results.push((c.clone(), elapsed)); } } } - return vec![true]; + return results; } } diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index 704477b1fb2bc..e91d96e32b39f 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -58,6 +58,9 @@ use codec::{Encode, Decode}; #[cfg(feature = "std")] use sp_externalities::{ExternalitiesExt, Externalities}; +#[cfg(feature = "std")] +use std::time; + /// Error verifying ECDSA signature #[derive(Encode, Decode)] pub enum EcdsaVerifyError { @@ -372,6 +375,17 @@ pub trait Misc { } } +/// Interface provides functionality to fetch the system time for benchmarking. +#[runtime_interface] +pub trait Benchmark { + /// Get the current system time in nanoseconds. + fn now() -> u128 { + time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH) + .expect("Unix time doesn't go backwards; qed") + .as_nanos() + } +} + /// Interfaces for working with crypto related types from within the runtime. #[runtime_interface] pub trait Crypto { @@ -916,6 +930,7 @@ pub type SubstrateHostFunctions = ( logging::HostFunctions, sandbox::HostFunctions, crate::trie::HostFunctions, + benchmark::HostFunctions, ); #[cfg(test)] From ddff02608caee832422b465ea962490004a588c2 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 22 Jan 2020 17:28:37 +0100 Subject: [PATCH 09/50] Add runtime api --- Cargo.lock | 1 + bin/node/runtime/src/lib.rs | 6 ++++++ frame/identity/Cargo.toml | 1 + frame/identity/src/benchmarking.rs | 12 ++++++------ frame/identity/src/lib.rs | 22 +++++++++++++--------- primitives/runtime/src/lib.rs | 13 +++++++++++++ primitives/runtime/src/traits.rs | 6 ++---- 7 files changed, 42 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8030a4cd13ad2..9e2b655146104 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3791,6 +3791,7 @@ dependencies = [ "pallet-balances 2.0.0", "parity-scale-codec 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", "sp-core 2.0.0", "sp-io 2.0.0", "sp-runtime 2.0.0", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index e158cbe2cbb88..dd627d5fab8a7 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -799,6 +799,12 @@ impl_runtime_apis! { SessionKeys::generate(seed) } } + + impl pallet_identity::IdentityBenchmarks for Runtime { + fn run_benchmarks() -> BenchmarkResults { + Identity::run_benchmarks() + } + } } #[cfg(test)] diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 12feab0cd1a24..001398da3b65a 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -14,6 +14,7 @@ sp-runtime = { version = "2.0.0", default-features = false, path = "../../primit frame-support = { version = "2.0.0", default-features = false, path = "../support" } frame-system = { version = "2.0.0", default-features = false, path = "../system" } sp-core = { version = "2.0.0", path = "../../primitives/core" } +sp-api = { version = "2.0.0", path = "../../primitives/api" } pallet-balances = { version = "2.0.0", path = "../balances" } [features] diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index fbe19310792ce..21daafa9e5914 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -100,12 +100,12 @@ pub type IdentityCall = crate::Call; pub mod set_identity { use super::*; - pub fn components() -> Vec<(&'static str, u32, u32)> { + pub fn components() -> Vec<(BenchmarkParameter, u32, u32)> { vec![ // Registrar Count - ("R", 1, 16), + (BenchmarkParameter::R, 1, 16), // Additional Field Count - ("X", 1, 20) + (BenchmarkParameter::X, 1, 20) ] } @@ -116,10 +116,10 @@ pub mod set_identity { /// /// Sets up state randomly and returns a randomly generated `set_identity` with sensible (fixed) /// values for all complexity components except those mentioned in the identity. - pub fn instance(components: &[(&'static str, u32)]) -> Call + pub fn instance(components: &[(BenchmarkParameter, u32)]) -> Call { // Add r registrars - let r = components.iter().find(|&c| c.0 == "R").unwrap(); + let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap(); for i in 0..r.1 { assert_ok!(Identity::add_registrar(Origin::signed(1), i.into())); assert_ok!(Identity::set_fee(Origin::signed(i.into()), 0, 10)); @@ -128,7 +128,7 @@ pub mod set_identity { } // Create identity info with x additional fields - let x = components.iter().find(|&c| c.0 == "R").unwrap(); + let x = components.iter().find(|&c| c.0 == BenchmarkParameter::X).unwrap(); // 32 byte data that we reuse below let data = Data::Raw(vec![0; 32]); let info = IdentityInfo { diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index c38ec1914e52f..380dc3861d4f1 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -69,8 +69,8 @@ use sp_std::prelude::*; use sp_std::{fmt::Debug, ops::Add, iter::once}; use enumflags2::BitFlags; use codec::{Encode, Decode}; -use sp_runtime::{DispatchResult, RuntimeDebug}; -use sp_runtime::traits::{StaticLookup, EnsureOrigin, Zero, AppendZerosInput, Benchmarking, Dispatchable}; +use sp_runtime::{DispatchResult, RuntimeDebug, BenchmarkResults, BenchmarkParameter}; +use sp_runtime::traits::{StaticLookup, EnsureOrigin, Zero, AppendZerosInput, Dispatchable, Benchmarking}; use frame_support::{ decl_module, decl_event, decl_storage, ensure, decl_error, traits::{Currency, ReservableCurrency, OnUnbalanced, Get}, @@ -864,16 +864,15 @@ decl_module! { } } -impl Benchmarking for Module { - type BenchmarkResults = (Vec<(&'static str, u32)>, u128); +impl Benchmarking for Module { const STEPS: u32 = 100; const REPEATS: u32 = 10; - fn run_benchmarks() -> Vec { + fn run_benchmarks() -> Vec { // first one is set_identity. let components = benchmarking::set_identity::components(); // results go here - let mut results: Vec = Vec::new(); + let mut results: Vec = Vec::new(); // Select the component we will be benchmarking. Each component will be benchmarked. for (name, low, high) in components.iter() { // Create up to `STEPS` steps for that component between high and low. @@ -884,12 +883,10 @@ impl Benchmarking for Module { let component_value = step_size * s; // Select the mid value for all the other components. - let c: Vec<(&'static str, u32)> = components.iter() + let c: Vec<(BenchmarkParameter, u32)> = components.iter() .map(|(n, l, h)| (*n, if n == name { component_value } else { (h - l) / 2 + l }) ).collect(); - - for _r in 0..Self::REPEATS { let instance = benchmarking::set_identity::instance(&c); @@ -905,6 +902,13 @@ impl Benchmarking for Module { } } +sp_api::decl_runtime_apis! { + pub trait IdentityBenchmarks + { + fn run_benchmarks() -> BenchmarkResults; + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 46930c35e8e8d..3ea79174dbc85 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -678,6 +678,19 @@ pub fn print(print: impl traits::Printable) { print.print(); } +/// Parameters for this module. +#[derive(Encode, Decode, Clone, Copy, PartialEq)] +pub enum BenchmarkParameter { + /// Registrar Count + R, + /// Additional Field Count + X, +} + +/// Results from running benchmarks on a FRAME pallet. +/// Contains the parameters used when running the benchmark, and the duration of the function call in nanoseconds. +pub type BenchmarkResults = (Vec<(BenchmarkParameter, u32)>, u128); + #[cfg(test)] mod tests { use super::*; diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index cfd5faf12ffc7..e67b9d8cd9e29 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1264,15 +1264,13 @@ pub trait BlockIdTo { } /// The module benchmarking trait. -pub trait Benchmarking { - /// Type for the results of benchmarks. - type BenchmarkResults; +pub trait Benchmarking { /// Number of steps to take between variable ranges. const STEPS: u32; /// Number of benchmarking repetitions. const REPEATS: u32; /// Run the benchmarks for this module. - fn run_benchmarks() -> Vec; + fn run_benchmarks() -> Vec; } #[cfg(test)] From 890ad0d641b321c19e1d043413774339cd11d29b Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 22 Jan 2020 22:26:04 +0100 Subject: [PATCH 10/50] compiles --- bin/node/runtime/src/lib.rs | 9 +++++---- frame/identity/Cargo.toml | 9 ++++++--- frame/identity/src/benchmarking.rs | 12 ++++++------ frame/identity/src/lib.rs | 4 ++-- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index dd627d5fab8a7..1cc8554101034 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -30,13 +30,14 @@ use sp_core::u32_trait::{_1, _2, _3, _4}; use node_primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, Moment, Signature}; use sp_api::impl_runtime_apis; use sp_runtime::{ - Permill, Perbill, Percent, ApplyExtrinsicResult, impl_opaque_keys, generic, create_runtime_str + Permill, Perbill, Percent, ApplyExtrinsicResult, impl_opaque_keys, generic, create_runtime_str, + BenchmarkResults, }; use sp_runtime::curve::PiecewiseLinear; use sp_runtime::transaction_validity::TransactionValidity; use sp_runtime::traits::{ self, BlakeTwo256, Block as BlockT, StaticLookup, SaturatedConversion, - OpaqueKeys, + OpaqueKeys, Benchmarking, }; use sp_version::RuntimeVersion; #[cfg(any(feature = "std", test))] @@ -800,8 +801,8 @@ impl_runtime_apis! { } } - impl pallet_identity::IdentityBenchmarks for Runtime { - fn run_benchmarks() -> BenchmarkResults { + impl pallet_identity::IdentityBenchmarks for Runtime { + fn run_benchmarks() -> Vec { Identity::run_benchmarks() } } diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 001398da3b65a..0dfddd3675e06 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -13,9 +13,9 @@ sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/ sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "2.0.0", default-features = false, path = "../support" } frame-system = { version = "2.0.0", default-features = false, path = "../system" } -sp-core = { version = "2.0.0", path = "../../primitives/core" } -sp-api = { version = "2.0.0", path = "../../primitives/api" } -pallet-balances = { version = "2.0.0", path = "../balances" } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-api = { version = "2.0.0", default-features = false, path = "../../primitives/api" } +pallet-balances = { version = "2.0.0", default-features = false, path = "../balances" } [features] default = ["std"] @@ -24,7 +24,10 @@ std = [ "codec/std", "sp-std/std", "sp-io/std", + "sp-core/std", + "sp-api/std", "sp-runtime/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", ] diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 21daafa9e5914..e17c71bb84b83 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -1,7 +1,7 @@ use super::*; use frame_support::{ - assert_ok, impl_outer_origin, parameter_types, weights::Weight, + impl_outer_origin, parameter_types, weights::Weight, ord_parameter_types, impl_outer_dispatch, }; use sp_core::H256; @@ -9,7 +9,7 @@ use frame_system::EnsureSignedBy; // 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::{ - Perbill, testing::Header, traits::{BlakeTwo256, IdentityLookup}, + Perbill, generic::Header, traits::{BlakeTwo256, IdentityLookup}, }; impl_outer_origin! { @@ -44,7 +44,7 @@ impl frame_system::Trait for Benchmark { type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; - type Header = Header; + type Header = Header; type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; @@ -121,10 +121,10 @@ pub mod set_identity { // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap(); for i in 0..r.1 { - assert_ok!(Identity::add_registrar(Origin::signed(1), i.into())); - assert_ok!(Identity::set_fee(Origin::signed(i.into()), 0, 10)); + assert_eq!(Identity::add_registrar(Origin::signed(1), i.into()), Ok(())); + assert_eq!(Identity::set_fee(Origin::signed(i.into()), 0, 10), Ok(())); let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); - assert_ok!(Identity::set_fields(Origin::signed(i.into()), 0, fields)); + assert_eq!(Identity::set_fields(Origin::signed(i.into()), 0, fields), Ok(())); } // Create identity info with x additional fields diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 380dc3861d4f1..6369181c2c2b2 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -891,7 +891,7 @@ impl Benchmarking for Module { for _r in 0..Self::REPEATS { let instance = benchmarking::set_identity::instance(&c); let start = sp_io::benchmark::now(); - frame_support::assert_ok!(instance.dispatch(Some(0).into())); + assert_eq!(instance.dispatch(Some(0).into()), Ok(())); let finish = sp_io::benchmark::now(); let elapsed = finish - start; results.push((c.clone(), elapsed)); @@ -905,7 +905,7 @@ impl Benchmarking for Module { sp_api::decl_runtime_apis! { pub trait IdentityBenchmarks { - fn run_benchmarks() -> BenchmarkResults; + fn run_benchmarks() -> Vec; } } From 0a1bcfc50b02a6bcfe5729a2e6661187ec9a7f51 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 23 Jan 2020 15:45:56 +0100 Subject: [PATCH 11/50] Update to use offchain timestamp --- client/cli/src/lib.rs | 9 ++++++++- client/cli/src/params.rs | 12 ++++++++++++ frame/identity/src/lib.rs | 10 +++++----- primitives/core/src/offchain/mod.rs | 2 +- primitives/io/src/lib.rs | 15 --------------- primitives/runtime/src/lib.rs | 2 +- 6 files changed, 27 insertions(+), 23 deletions(-) diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index fc5025952860b..d8fbb289efac6 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -57,7 +57,7 @@ use params::{ NetworkConfigurationParams, MergeParameters, TransactionPoolParams, NodeKeyParams, NodeKeyType, Cors, CheckBlockCmd, }; -pub use params::{NoCustom, CoreParams, SharedParams, ImportParams, ExecutionStrategy}; +pub use params::{NoCustom, CoreParams, SharedParams, ImportParams, ExecutionStrategy, BenchmarkRuntimeParams}; pub use traits::GetSharedParams; use app_dirs::{AppInfo, AppDataType}; use log::info; @@ -806,6 +806,11 @@ fn fill_transaction_pool_configuration( Ok(()) } +/// Run the runtime benchmarks. +fn run_benchmark(params: BenchmarkRuntimeParams) -> error::Result<()> { + Ok(()) +} + /// Fill the given `NetworkConfiguration` by looking at the cli parameters. fn fill_network_configuration( cli: NetworkConfigurationParams, @@ -1054,6 +1059,8 @@ where fill_transaction_pool_configuration(&mut config, cli.pool_config)?; + run_benchmark(cli.benchmark_config)?; + config.dev_key_seed = cli.keyring.account .map(|a| format!("//{}", a)).or_else(|| { if is_dev { diff --git a/client/cli/src/params.rs b/client/cli/src/params.rs index 57b90c2e73d5c..38c61098b5075 100644 --- a/client/cli/src/params.rs +++ b/client/cli/src/params.rs @@ -293,6 +293,14 @@ pub struct TransactionPoolParams { pub pool_kbytes: usize, } +/// Parameters used to benchmark the runtime. +#[derive(Debug, StructOpt, Clone)] +pub struct BenchmarkRuntimeParams { + /// Enable benchmarking of the runtime. + #[structopt(long = "benchmark")] + pub benchmark: bool, +} + arg_enum! { #[allow(missing_docs)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -529,6 +537,10 @@ pub struct RunCmd { #[structopt(flatten)] pub pool_config: TransactionPoolParams, + #[allow(missing_docs)] + #[structopt(flatten)] + pub benchmark_config: BenchmarkRuntimeParams, + #[allow(missing_docs)] #[structopt(flatten)] pub keyring: Keyring, diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 6369181c2c2b2..b38ec84e59b04 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -876,7 +876,7 @@ impl Benchmarking for Module { // Select the component we will be benchmarking. Each component will be benchmarked. for (name, low, high) in components.iter() { // Create up to `STEPS` steps for that component between high and low. - let step_size = ((high - low) / Self::STEPS).min(1); + let step_size = ((high - low) / Self::STEPS).max(1); let num_of_steps = (high - low) / step_size; for s in 0..num_of_steps { // This is the value we will be testing for component `name` @@ -890,10 +890,10 @@ impl Benchmarking for Module { for _r in 0..Self::REPEATS { let instance = benchmarking::set_identity::instance(&c); - let start = sp_io::benchmark::now(); - assert_eq!(instance.dispatch(Some(0).into()), Ok(())); - let finish = sp_io::benchmark::now(); - let elapsed = finish - start; + let start = sp_io::offchain::timestamp(); + instance.dispatch(Some(0).into()); + let finish = sp_io::offchain::timestamp(); + let elapsed = finish.0 - start.0; results.push((c.clone(), elapsed)); } } diff --git a/primitives/core/src/offchain/mod.rs b/primitives/core/src/offchain/mod.rs index e2e00c36e0769..373319f1b6609 100644 --- a/primitives/core/src/offchain/mod.rs +++ b/primitives/core/src/offchain/mod.rs @@ -206,7 +206,7 @@ impl OpaqueMultiaddr { /// Opaque timestamp type #[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Default, RuntimeDebug, PassByInner, Encode, Decode)] -pub struct Timestamp(u64); +pub struct Timestamp(pub u64); /// Duration type #[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Default, RuntimeDebug, PassByInner, Encode, Decode)] diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index e91d96e32b39f..704477b1fb2bc 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -58,9 +58,6 @@ use codec::{Encode, Decode}; #[cfg(feature = "std")] use sp_externalities::{ExternalitiesExt, Externalities}; -#[cfg(feature = "std")] -use std::time; - /// Error verifying ECDSA signature #[derive(Encode, Decode)] pub enum EcdsaVerifyError { @@ -375,17 +372,6 @@ pub trait Misc { } } -/// Interface provides functionality to fetch the system time for benchmarking. -#[runtime_interface] -pub trait Benchmark { - /// Get the current system time in nanoseconds. - fn now() -> u128 { - time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH) - .expect("Unix time doesn't go backwards; qed") - .as_nanos() - } -} - /// Interfaces for working with crypto related types from within the runtime. #[runtime_interface] pub trait Crypto { @@ -930,7 +916,6 @@ pub type SubstrateHostFunctions = ( logging::HostFunctions, sandbox::HostFunctions, crate::trie::HostFunctions, - benchmark::HostFunctions, ); #[cfg(test)] diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 3ea79174dbc85..323fd91482372 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -689,7 +689,7 @@ pub enum BenchmarkParameter { /// Results from running benchmarks on a FRAME pallet. /// Contains the parameters used when running the benchmark, and the duration of the function call in nanoseconds. -pub type BenchmarkResults = (Vec<(BenchmarkParameter, u32)>, u128); +pub type BenchmarkResults = (Vec<(BenchmarkParameter, u32)>, u64); #[cfg(test)] mod tests { From 931702b99295afc7510aeb1652f9f47df46de45c Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Mon, 27 Jan 2020 11:57:57 +0100 Subject: [PATCH 12/50] Gives a result --- frame/balances/src/lib.rs | 2 +- frame/identity/src/benchmarking.rs | 8 +++++--- frame/identity/src/lib.rs | 6 +++--- primitives/io/src/lib.rs | 15 +++++++++++++++ primitives/runtime/src/lib.rs | 2 +- 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index b488b96701cf1..98c73c2503f71 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -487,7 +487,7 @@ decl_module! { /// - Contains a limited number of reads and writes. /// # #[weight = SimpleDispatchInfo::FixedOperational(50_000)] - fn set_balance( + pub fn set_balance( origin, who: ::Source, #[compact] new_free: T::Balance, diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index e17c71bb84b83..16b9372d09fb0 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -120,11 +120,13 @@ pub mod set_identity { { // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap(); + assert_eq!(Balances::set_balance(Origin::ROOT, 1u64.into(), 1_000_000_000_000, 0), Ok(())); for i in 0..r.1 { + assert_eq!(Balances::set_balance(Origin::ROOT, i.into(), 1_000_000_000_000, 0), Ok(())); assert_eq!(Identity::add_registrar(Origin::signed(1), i.into()), Ok(())); - assert_eq!(Identity::set_fee(Origin::signed(i.into()), 0, 10), Ok(())); - let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); - assert_eq!(Identity::set_fields(Origin::signed(i.into()), 0, fields), Ok(())); +// assert_eq!(Identity::set_fee(Origin::signed(i.into()), i, 10), Ok(())); +// let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); +// assert_eq!(Identity::set_fields(Origin::signed(i.into()), 0, fields), Ok(())); } // Create identity info with x additional fields diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index b38ec84e59b04..619eefc16c596 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -890,10 +890,10 @@ impl Benchmarking for Module { for _r in 0..Self::REPEATS { let instance = benchmarking::set_identity::instance(&c); - let start = sp_io::offchain::timestamp(); + let start = sp_io::benchmarking::current_time(); instance.dispatch(Some(0).into()); - let finish = sp_io::offchain::timestamp(); - let elapsed = finish.0 - start.0; + let finish = sp_io::benchmarking::current_time(); + let elapsed = finish - start; results.push((c.clone(), elapsed)); } } diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index 704477b1fb2bc..7b62bd4ceacd9 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -772,6 +772,20 @@ pub trait Logging { } } +/// Interface that provides functions for benchmarking the runtime. +#[runtime_interface] +pub trait Benchmarking { + /// Get the number of nanoseconds passed since the UNIX epoch + /// + /// WARNING! This is a non-deterministic call. Do not use this within + /// consensus critical logic. + fn current_time() -> u128 { + std::time::SystemTime::now().duration_since(std::time::SystemTime::UNIX_EPOCH) + .expect("Unix time doesn't go backwards; qed") + .as_nanos() + } +} + /// Wasm-only interface that provides functions for interacting with the sandbox. #[runtime_interface(wasm_only)] pub trait Sandbox { @@ -916,6 +930,7 @@ pub type SubstrateHostFunctions = ( logging::HostFunctions, sandbox::HostFunctions, crate::trie::HostFunctions, + benchmarking::HostFunctions, ); #[cfg(test)] diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 323fd91482372..3ea79174dbc85 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -689,7 +689,7 @@ pub enum BenchmarkParameter { /// Results from running benchmarks on a FRAME pallet. /// Contains the parameters used when running the benchmark, and the duration of the function call in nanoseconds. -pub type BenchmarkResults = (Vec<(BenchmarkParameter, u32)>, u64); +pub type BenchmarkResults = (Vec<(BenchmarkParameter, u32)>, u128); #[cfg(test)] mod tests { From e8c499240abdef913491f1754caf40a6023b7f5a Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 28 Jan 2020 13:14:56 +0100 Subject: [PATCH 13/50] added some CLI wip --- Cargo.lock | 1 + bin/node-template/src/cli.rs | 1 + bin/node/cli/src/cli.rs | 1 + client/cli/Cargo.toml | 1 + client/cli/src/lib.rs | 67 +++++++++++++++++++++++++++++++----- client/cli/src/params.rs | 33 +++++++++++------- 6 files changed, 83 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 739bbdc91a1b1..06791e45afb3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5125,6 +5125,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-identity 2.0.0", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rpassword 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "sc-client-api 2.0.0", diff --git a/bin/node-template/src/cli.rs b/bin/node-template/src/cli.rs index fcfd330816cd1..6c51a34725781 100644 --- a/bin/node-template/src/cli.rs +++ b/bin/node-template/src/cli.rs @@ -51,6 +51,7 @@ pub fn run(args: I, exit: E, version: VersionInfo) -> error::Result<()> ParseAndPrepare::CheckBlock(cmd) => cmd.run_with_builder(|config: Config<_>| Ok(new_full_start!(config).0), load_spec, exit), ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec), + ParseAndPrepare::Benchmark(cmd) => cmd.run(load_spec), ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_>| Ok(new_full_start!(config).0), load_spec), ParseAndPrepare::CustomCommand(_) => Ok(()) diff --git a/bin/node/cli/src/cli.rs b/bin/node/cli/src/cli.rs index 5ade700513e53..d0686ae46fab5 100644 --- a/bin/node/cli/src/cli.rs +++ b/bin/node/cli/src/cli.rs @@ -136,6 +136,7 @@ pub fn run(args: I, exit: E, version: sc_cli::VersionInfo) -> error::Re ParseAndPrepare::CheckBlock(cmd) => cmd.run_with_builder(|config: Config<_, _>| Ok(new_full_start!(config).0), load_spec, exit), ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec), + ParseAndPrepare::Benchmark(cmd) => cmd.run(load_spec), ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_, _>| Ok(new_full_start!(config).0), load_spec), ParseAndPrepare::CustomCommand(CustomSubcommands::Factory(cli_args)) => { diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index b46e3992b2e9f..948d0295ac4e9 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -30,6 +30,7 @@ sc-service = { version = "0.8", default-features = false, path = "../service" } sp-state-machine = { version = "0.8", path = "../../primitives/state-machine" } sc-telemetry = { version = "2.0.0", path = "../telemetry" } sp-keyring = { version = "2.0.0", path = "../../primitives/keyring" } +pallet-identity = { version = "2.0.0", path = "../../frame/identity" } names = "0.11.0" structopt = "=0.3.7" sc-tracing = { version = "2.0.0", path = "../tracing" } diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index d8fbb289efac6..f412be86743b9 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -55,9 +55,9 @@ pub use structopt::clap::App; use params::{ RunCmd, PurgeChainCmd, RevertCmd, ImportBlocksCmd, ExportBlocksCmd, BuildSpecCmd, NetworkConfigurationParams, MergeParameters, TransactionPoolParams, - NodeKeyParams, NodeKeyType, Cors, CheckBlockCmd, + NodeKeyParams, NodeKeyType, Cors, CheckBlockCmd, BenchmarkCmd, }; -pub use params::{NoCustom, CoreParams, SharedParams, ImportParams, ExecutionStrategy, BenchmarkRuntimeParams}; +pub use params::{NoCustom, CoreParams, SharedParams, ImportParams, ExecutionStrategy}; pub use traits::GetSharedParams; use app_dirs::{AppInfo, AppDataType}; use log::info; @@ -244,6 +244,9 @@ where params::CoreParams::PurgeChain(params) => ParseAndPrepare::PurgeChain( ParseAndPreparePurge { params, version } ), + params::CoreParams::Benchmark(params) => ParseAndPrepare::Benchmark( + ParseAndPrepareBenchmark { params, version } + ), params::CoreParams::Revert(params) => ParseAndPrepare::RevertChain( ParseAndPrepareRevert { params, version } ), @@ -279,6 +282,8 @@ pub enum ParseAndPrepare<'a, CC, RP> { CheckBlock(CheckBlock<'a>), /// Command ready to purge the chain. PurgeChain(ParseAndPreparePurge<'a>), + /// Command ready to benchmark the chain. + Benchmark(ParseAndPrepareBenchmark<'a>), /// Command ready to revert the chain. RevertChain(ParseAndPrepareRevert<'a>), /// An additional custom command passed to `parse_and_prepare`. @@ -295,6 +300,7 @@ impl<'a, CC, RP> ParseAndPrepare<'a, CC, RP> where CC: GetSharedParams { ParseAndPrepare::ImportBlocks(c) => Some(&c.params.shared_params), ParseAndPrepare::CheckBlock(c) => Some(&c.params.shared_params), ParseAndPrepare::PurgeChain(c) => Some(&c.params.shared_params), + ParseAndPrepare::Benchmark(c) => Some(&c.params.shared_params), ParseAndPrepare::RevertChain(c) => Some(&c.params.shared_params), ParseAndPrepare::CustomCommand(c) => c.shared_params(), } @@ -361,6 +367,13 @@ impl<'a, CC, RP> ParseAndPrepare<'a, CC, RP> { c.version, default_base_path, )).transpose(), + ParseAndPrepare::Benchmark(c) => + Some(create_config_with_db_path( + spec_factory, + &c.params.shared_params, + c.version, + default_base_path, + )).transpose(), ParseAndPrepare::RevertChain(c) => Some(create_config_with_db_path( spec_factory, @@ -715,6 +728,49 @@ impl<'a> ParseAndPreparePurge<'a> { } } +/// Command ready to benchmark the runtime. +pub struct ParseAndPrepareBenchmark<'a> { + params: BenchmarkCmd, + version: &'a VersionInfo, +} + +impl<'a> ParseAndPrepareBenchmark<'a> { + /// Runs the command and benchmarks the chain. + pub fn run( + self, + spec_factory: S + ) -> error::Result<()> where + S: FnOnce(&str) -> Result>, String>, + G: RuntimeGenesis, + E: ChainSpecExtension, + { + let mut config = create_config_with_db_path::<(), _, _, _>( + spec_factory, + &self.params.shared_params, + self.version, + None, + )?; + fill_config_keystore_in_memory(&mut config)?; + let db_path = match config.database { + DatabaseConfig::Path { path, .. } => path, + _ => { + eprintln!("Cannot purge custom database implementation"); + return Ok(()); + } + }; + + if self.params.pallet.is_some() { + print!("Input contains: {:?}", self.params.pallet.unwrap()) + } else { + print!("Input is Empty"); + } + + pallet_identity::run_benchmarks(); + + Ok(()) + } +} + /// Command ready to revert the chain. pub struct ParseAndPrepareRevert<'a> { params: RevertCmd, @@ -806,11 +862,6 @@ fn fill_transaction_pool_configuration( Ok(()) } -/// Run the runtime benchmarks. -fn run_benchmark(params: BenchmarkRuntimeParams) -> error::Result<()> { - Ok(()) -} - /// Fill the given `NetworkConfiguration` by looking at the cli parameters. fn fill_network_configuration( cli: NetworkConfigurationParams, @@ -1059,8 +1110,6 @@ where fill_transaction_pool_configuration(&mut config, cli.pool_config)?; - run_benchmark(cli.benchmark_config)?; - config.dev_key_seed = cli.keyring.account .map(|a| format!("//{}", a)).or_else(|| { if is_dev { diff --git a/client/cli/src/params.rs b/client/cli/src/params.rs index 38c61098b5075..1b731c5408867 100644 --- a/client/cli/src/params.rs +++ b/client/cli/src/params.rs @@ -293,14 +293,6 @@ pub struct TransactionPoolParams { pub pool_kbytes: usize, } -/// Parameters used to benchmark the runtime. -#[derive(Debug, StructOpt, Clone)] -pub struct BenchmarkRuntimeParams { - /// Enable benchmarking of the runtime. - #[structopt(long = "benchmark")] - pub benchmark: bool, -} - arg_enum! { #[allow(missing_docs)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -537,10 +529,6 @@ pub struct RunCmd { #[structopt(flatten)] pub pool_config: TransactionPoolParams, - #[allow(missing_docs)] - #[structopt(flatten)] - pub benchmark_config: BenchmarkRuntimeParams, - #[allow(missing_docs)] #[structopt(flatten)] pub keyring: Keyring, @@ -866,6 +854,18 @@ pub struct PurgeChainCmd { pub shared_params: SharedParams, } +/// The `benchmark` command used to benchmark FRAME pallets. +#[derive(Debug, StructOpt, Clone)] +pub struct BenchmarkCmd { + /// Select a FRAME pallet to benchmark. + #[structopt(short, long)] + pub pallet: Option, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub shared_params: SharedParams, +} + /// All core commands that are provided by default. /// /// The core commands are split into multiple subcommands and `Run` is the default subcommand. From @@ -894,6 +894,9 @@ pub enum CoreParams { /// Remove the whole chain data. PurgeChain(PurgeChainCmd), + /// Benchmark the runtime. + Benchmark(BenchmarkCmd), + /// Further custom subcommands. Custom(CC), } @@ -933,6 +936,10 @@ impl StructOpt for CoreParams where PurgeChainCmd::augment_clap(SubCommand::with_name("purge-chain")) .about("Remove the whole chain data.") ) + .subcommand( + BenchmarkCmd::augment_clap(SubCommand::with_name("benchmark")) + .about("Benchmark your FRAME pallets.") + ) } fn from_clap(matches: &::structopt::clap::ArgMatches) -> Self { @@ -948,6 +955,8 @@ impl StructOpt for CoreParams where ("revert", Some(matches)) => CoreParams::Revert(RevertCmd::from_clap(matches)), ("purge-chain", Some(matches)) => CoreParams::PurgeChain(PurgeChainCmd::from_clap(matches)), + ("benchmark", Some(matches)) => + CoreParams::Benchmark(BenchmarkCmd::from_clap(matches)), (_, None) => CoreParams::Run(MergeParameters::from_clap(matches)), _ => CoreParams::Custom(CC::from_clap(matches)), } From e5657e924260a250c17455597d3c5615a502edf2 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 28 Jan 2020 16:25:43 +0100 Subject: [PATCH 14/50] make generic --- client/cli/src/lib.rs | 2 - frame/identity/src/benchmarking.rs | 110 ++++------------------------- frame/identity/src/lib.rs | 4 +- 3 files changed, 14 insertions(+), 102 deletions(-) diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index f412be86743b9..6cc00dde376f1 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -765,8 +765,6 @@ impl<'a> ParseAndPrepareBenchmark<'a> { print!("Input is Empty"); } - pallet_identity::run_benchmarks(); - Ok(()) } } diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 16b9372d09fb0..0d1949505560c 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -1,101 +1,14 @@ use super::*; -use frame_support::{ - impl_outer_origin, parameter_types, weights::Weight, - ord_parameter_types, impl_outer_dispatch, -}; -use sp_core::H256; -use frame_system::EnsureSignedBy; -// 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::{ - Perbill, generic::Header, traits::{BlakeTwo256, IdentityLookup}, -}; +use sp_runtime::traits::SaturatedConversion; -impl_outer_origin! { - pub enum Origin for Benchmark where system = frame_system {} -} - -impl_outer_dispatch! { - pub enum Call for Benchmark where origin: Origin { - frame_system::System, - pallet_balances::Balances, - pallet_identity::Identity, - } -} +use frame_system::RawOrigin; +use sp_io::hashing::blake2_256; -// For testing the module, we construct most of a mock runtime. This means -// first constructing a configuration type (`Benchmark`) which `impl`s each of the -// configuration traits of modules we want to use. -#[derive(Clone, Eq, PartialEq)] -pub struct Benchmark; -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} -impl frame_system::Trait for Benchmark { - 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 = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); - type ModuleToIndex = (); -} -parameter_types! { - pub const ExistentialDeposit: u64 = 0; - pub const TransferFee: u64 = 0; - pub const CreationFee: u64 = 0; +pub fn account(index: u32) -> T::AccountId { + let entropy = (b"benchmark", index).using_encoded(blake2_256); + T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() } -impl pallet_balances::Trait for Benchmark { - type Balance = u64; - type OnFreeBalanceZero = (); - type OnReapAccount = System; - type OnNewAccount = (); - type Event = (); - type TransferPayment = (); - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; -} -parameter_types! { - pub const BasicDeposit: u64 = 10; - pub const FieldDeposit: u64 = 10; - pub const SubAccountDeposit: u64 = 10; - pub const MaximumSubAccounts: u32 = 2; -} -ord_parameter_types! { - pub const One: u64 = 1; - pub const Two: u64 = 2; -} -impl Trait for Benchmark { - type Event = (); - type Currency = Balances; - type Slashed = (); - type BasicDeposit = BasicDeposit; - type FieldDeposit = FieldDeposit; - type SubAccountDeposit = SubAccountDeposit; - type MaximumSubAccounts = MaximumSubAccounts; - type RegistrarOrigin = EnsureSignedBy; - type ForceOrigin = EnsureSignedBy; -} -type System = frame_system::Module; -type Balances = pallet_balances::Module; -type Identity = Module; - -pub type IdentityCall = crate::Call; pub mod set_identity { use super::*; @@ -116,14 +29,15 @@ pub mod set_identity { /// /// Sets up state randomly and returns a randomly generated `set_identity` with sensible (fixed) /// values for all complexity components except those mentioned in the identity. - pub fn instance(components: &[(BenchmarkParameter, u32)]) -> Call + pub fn instance(components: &[(BenchmarkParameter, u32)]) -> crate::Call { + // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap(); - assert_eq!(Balances::set_balance(Origin::ROOT, 1u64.into(), 1_000_000_000_000, 0), Ok(())); + let _ = T::Currency::deposit_creating(&account::(1), 1_000_000_000_000u128.saturated_into()); for i in 0..r.1 { - assert_eq!(Balances::set_balance(Origin::ROOT, i.into(), 1_000_000_000_000, 0), Ok(())); - assert_eq!(Identity::add_registrar(Origin::signed(1), i.into()), Ok(())); + let _ = T::Currency::deposit_creating(&account::(i), 1_000_000_000_000u128.saturated_into()); + //assert_eq!(crate::Module::::add_registrar(RawOrigin::Signed(account::(1)).into(), account::(i)), Ok(())); // assert_eq!(Identity::set_fee(Origin::signed(i.into()), i, 10), Ok(())); // let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); // assert_eq!(Identity::set_fields(Origin::signed(i.into()), 0, fields), Ok(())); @@ -146,6 +60,6 @@ pub mod set_identity { }; // Return the `set_identity` call - return Call::Identity(IdentityCall::set_identity(info)) + crate::Call::::set_identity(info) } } \ No newline at end of file diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 619eefc16c596..b8ac054328977 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -889,9 +889,9 @@ impl Benchmarking for Module { ).collect(); for _r in 0..Self::REPEATS { - let instance = benchmarking::set_identity::instance(&c); + let instance = benchmarking::set_identity::instance::(&c); let start = sp_io::benchmarking::current_time(); - instance.dispatch(Some(0).into()); + instance.dispatch(frame_system::RawOrigin::Signed(benchmarking::account::(0)).into()); let finish = sp_io::benchmarking::current_time(); let elapsed = finish - start; results.push((c.clone(), elapsed)); From 32e9e07c217a94a84bc5969417500fbf5d1e1436 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 28 Jan 2020 18:39:48 +0100 Subject: [PATCH 15/50] Update instance --- frame/identity/Cargo.toml | 4 +++- frame/identity/src/benchmarking.rs | 32 ++++++++++++++++++++++++------ frame/identity/src/lib.rs | 2 +- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 0dfddd3675e06..b71978129fc21 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -13,8 +13,10 @@ sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/ sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "2.0.0", default-features = false, path = "../support" } frame-system = { version = "2.0.0", default-features = false, path = "../system" } -sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } sp-api = { version = "2.0.0", default-features = false, path = "../../primitives/api" } + +[dev-dependencies] +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } pallet-balances = { version = "2.0.0", default-features = false, path = "../balances" } [features] diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 0d1949505560c..df8b7acea3ddb 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -1,3 +1,21 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Identity pallet benchmarking. + use super::*; use sp_runtime::traits::SaturatedConversion; @@ -5,6 +23,8 @@ use sp_runtime::traits::SaturatedConversion; use frame_system::RawOrigin; use sp_io::hashing::blake2_256; +use crate::Module as Identity; + pub fn account(index: u32) -> T::AccountId { let entropy = (b"benchmark", index).using_encoded(blake2_256); T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() @@ -34,13 +54,13 @@ pub mod set_identity { // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap(); - let _ = T::Currency::deposit_creating(&account::(1), 1_000_000_000_000u128.saturated_into()); + let _ = T::Currency::deposit_creating(&account::(0), 1_000_000_000_000_000_000u128.saturated_into()); for i in 0..r.1 { - let _ = T::Currency::deposit_creating(&account::(i), 1_000_000_000_000u128.saturated_into()); - //assert_eq!(crate::Module::::add_registrar(RawOrigin::Signed(account::(1)).into(), account::(i)), Ok(())); -// assert_eq!(Identity::set_fee(Origin::signed(i.into()), i, 10), Ok(())); -// let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); -// assert_eq!(Identity::set_fields(Origin::signed(i.into()), 0, fields), Ok(())); + let _ = T::Currency::deposit_creating(&account::(i), 1_000_000_000_000_000u128.saturated_into()); + assert_eq!(Identity::::add_registrar(RawOrigin::Root.into(), account::(i)), Ok(())); + assert_eq!(Identity::::set_fee(RawOrigin::Signed(account::(i)).into(), i.into(), 10.into()), Ok(())); + let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); + assert_eq!(Identity::::set_fields(RawOrigin::Signed(account::(i)).into(), i.into(), fields), Ok(())); } // Create identity info with x additional fields diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index b8ac054328977..956930aa0189f 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -891,7 +891,7 @@ impl Benchmarking for Module { for _r in 0..Self::REPEATS { let instance = benchmarking::set_identity::instance::(&c); let start = sp_io::benchmarking::current_time(); - instance.dispatch(frame_system::RawOrigin::Signed(benchmarking::account::(0)).into()); + assert_eq!(instance.dispatch(frame_system::RawOrigin::Signed(benchmarking::account::(0)).into()), Ok(())); let finish = sp_io::benchmarking::current_time(); let elapsed = finish - start; results.push((c.clone(), elapsed)); From 1e2630cc1320b45ce6f62a783709f86a8787c74f Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 28 Jan 2020 18:43:51 +0100 Subject: [PATCH 16/50] Remove CLI stuff --- Cargo.lock | 1 - bin/node-template/src/cli.rs | 1 - bin/node/cli/src/cli.rs | 1 - client/cli/Cargo.toml | 1 - client/cli/src/lib.rs | 60 +++--------------------------------- client/cli/src/params.rs | 21 ------------- 6 files changed, 4 insertions(+), 81 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 06791e45afb3e..739bbdc91a1b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5125,7 +5125,6 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pallet-identity 2.0.0", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rpassword 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "sc-client-api 2.0.0", diff --git a/bin/node-template/src/cli.rs b/bin/node-template/src/cli.rs index 6c51a34725781..fcfd330816cd1 100644 --- a/bin/node-template/src/cli.rs +++ b/bin/node-template/src/cli.rs @@ -51,7 +51,6 @@ pub fn run(args: I, exit: E, version: VersionInfo) -> error::Result<()> ParseAndPrepare::CheckBlock(cmd) => cmd.run_with_builder(|config: Config<_>| Ok(new_full_start!(config).0), load_spec, exit), ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec), - ParseAndPrepare::Benchmark(cmd) => cmd.run(load_spec), ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_>| Ok(new_full_start!(config).0), load_spec), ParseAndPrepare::CustomCommand(_) => Ok(()) diff --git a/bin/node/cli/src/cli.rs b/bin/node/cli/src/cli.rs index d0686ae46fab5..5ade700513e53 100644 --- a/bin/node/cli/src/cli.rs +++ b/bin/node/cli/src/cli.rs @@ -136,7 +136,6 @@ pub fn run(args: I, exit: E, version: sc_cli::VersionInfo) -> error::Re ParseAndPrepare::CheckBlock(cmd) => cmd.run_with_builder(|config: Config<_, _>| Ok(new_full_start!(config).0), load_spec, exit), ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec), - ParseAndPrepare::Benchmark(cmd) => cmd.run(load_spec), ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_, _>| Ok(new_full_start!(config).0), load_spec), ParseAndPrepare::CustomCommand(CustomSubcommands::Factory(cli_args)) => { diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 948d0295ac4e9..b46e3992b2e9f 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -30,7 +30,6 @@ sc-service = { version = "0.8", default-features = false, path = "../service" } sp-state-machine = { version = "0.8", path = "../../primitives/state-machine" } sc-telemetry = { version = "2.0.0", path = "../telemetry" } sp-keyring = { version = "2.0.0", path = "../../primitives/keyring" } -pallet-identity = { version = "2.0.0", path = "../../frame/identity" } names = "0.11.0" structopt = "=0.3.7" sc-tracing = { version = "2.0.0", path = "../tracing" } diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 6cc00dde376f1..2b341ff2aeef5 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -55,9 +55,9 @@ pub use structopt::clap::App; use params::{ RunCmd, PurgeChainCmd, RevertCmd, ImportBlocksCmd, ExportBlocksCmd, BuildSpecCmd, NetworkConfigurationParams, MergeParameters, TransactionPoolParams, - NodeKeyParams, NodeKeyType, Cors, CheckBlockCmd, BenchmarkCmd, + NodeKeyParams, NodeKeyType, Cors, CheckBlockCmd, }; -pub use params::{NoCustom, CoreParams, SharedParams, ImportParams, ExecutionStrategy}; +pub use params::{NoCustom, CoreParams, SharedParams, ImportParams, ExecutionStrategy, BenchmarkRuntimeParams}; pub use traits::GetSharedParams; use app_dirs::{AppInfo, AppDataType}; use log::info; @@ -244,9 +244,6 @@ where params::CoreParams::PurgeChain(params) => ParseAndPrepare::PurgeChain( ParseAndPreparePurge { params, version } ), - params::CoreParams::Benchmark(params) => ParseAndPrepare::Benchmark( - ParseAndPrepareBenchmark { params, version } - ), params::CoreParams::Revert(params) => ParseAndPrepare::RevertChain( ParseAndPrepareRevert { params, version } ), @@ -282,8 +279,6 @@ pub enum ParseAndPrepare<'a, CC, RP> { CheckBlock(CheckBlock<'a>), /// Command ready to purge the chain. PurgeChain(ParseAndPreparePurge<'a>), - /// Command ready to benchmark the chain. - Benchmark(ParseAndPrepareBenchmark<'a>), /// Command ready to revert the chain. RevertChain(ParseAndPrepareRevert<'a>), /// An additional custom command passed to `parse_and_prepare`. @@ -300,7 +295,6 @@ impl<'a, CC, RP> ParseAndPrepare<'a, CC, RP> where CC: GetSharedParams { ParseAndPrepare::ImportBlocks(c) => Some(&c.params.shared_params), ParseAndPrepare::CheckBlock(c) => Some(&c.params.shared_params), ParseAndPrepare::PurgeChain(c) => Some(&c.params.shared_params), - ParseAndPrepare::Benchmark(c) => Some(&c.params.shared_params), ParseAndPrepare::RevertChain(c) => Some(&c.params.shared_params), ParseAndPrepare::CustomCommand(c) => c.shared_params(), } @@ -367,13 +361,6 @@ impl<'a, CC, RP> ParseAndPrepare<'a, CC, RP> { c.version, default_base_path, )).transpose(), - ParseAndPrepare::Benchmark(c) => - Some(create_config_with_db_path( - spec_factory, - &c.params.shared_params, - c.version, - default_base_path, - )).transpose(), ParseAndPrepare::RevertChain(c) => Some(create_config_with_db_path( spec_factory, @@ -728,47 +715,6 @@ impl<'a> ParseAndPreparePurge<'a> { } } -/// Command ready to benchmark the runtime. -pub struct ParseAndPrepareBenchmark<'a> { - params: BenchmarkCmd, - version: &'a VersionInfo, -} - -impl<'a> ParseAndPrepareBenchmark<'a> { - /// Runs the command and benchmarks the chain. - pub fn run( - self, - spec_factory: S - ) -> error::Result<()> where - S: FnOnce(&str) -> Result>, String>, - G: RuntimeGenesis, - E: ChainSpecExtension, - { - let mut config = create_config_with_db_path::<(), _, _, _>( - spec_factory, - &self.params.shared_params, - self.version, - None, - )?; - fill_config_keystore_in_memory(&mut config)?; - let db_path = match config.database { - DatabaseConfig::Path { path, .. } => path, - _ => { - eprintln!("Cannot purge custom database implementation"); - return Ok(()); - } - }; - - if self.params.pallet.is_some() { - print!("Input contains: {:?}", self.params.pallet.unwrap()) - } else { - print!("Input is Empty"); - } - - Ok(()) - } -} - /// Command ready to revert the chain. pub struct ParseAndPrepareRevert<'a> { params: RevertCmd, @@ -1108,6 +1054,8 @@ where fill_transaction_pool_configuration(&mut config, cli.pool_config)?; + run_benchmark(cli.benchmark_config)?; + config.dev_key_seed = cli.keyring.account .map(|a| format!("//{}", a)).or_else(|| { if is_dev { diff --git a/client/cli/src/params.rs b/client/cli/src/params.rs index 1b731c5408867..57b90c2e73d5c 100644 --- a/client/cli/src/params.rs +++ b/client/cli/src/params.rs @@ -854,18 +854,6 @@ pub struct PurgeChainCmd { pub shared_params: SharedParams, } -/// The `benchmark` command used to benchmark FRAME pallets. -#[derive(Debug, StructOpt, Clone)] -pub struct BenchmarkCmd { - /// Select a FRAME pallet to benchmark. - #[structopt(short, long)] - pub pallet: Option, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub shared_params: SharedParams, -} - /// All core commands that are provided by default. /// /// The core commands are split into multiple subcommands and `Run` is the default subcommand. From @@ -894,9 +882,6 @@ pub enum CoreParams { /// Remove the whole chain data. PurgeChain(PurgeChainCmd), - /// Benchmark the runtime. - Benchmark(BenchmarkCmd), - /// Further custom subcommands. Custom(CC), } @@ -936,10 +921,6 @@ impl StructOpt for CoreParams where PurgeChainCmd::augment_clap(SubCommand::with_name("purge-chain")) .about("Remove the whole chain data.") ) - .subcommand( - BenchmarkCmd::augment_clap(SubCommand::with_name("benchmark")) - .about("Benchmark your FRAME pallets.") - ) } fn from_clap(matches: &::structopt::clap::ArgMatches) -> Self { @@ -955,8 +936,6 @@ impl StructOpt for CoreParams where ("revert", Some(matches)) => CoreParams::Revert(RevertCmd::from_clap(matches)), ("purge-chain", Some(matches)) => CoreParams::PurgeChain(PurgeChainCmd::from_clap(matches)), - ("benchmark", Some(matches)) => - CoreParams::Benchmark(BenchmarkCmd::from_clap(matches)), (_, None) => CoreParams::Run(MergeParameters::from_clap(matches)), _ => CoreParams::Custom(CC::from_clap(matches)), } From bafbac0bb7d7e9ad91ce10f781292572cf536b40 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 28 Jan 2020 18:48:42 +0100 Subject: [PATCH 17/50] Remove last cli stuff --- client/cli/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 2b341ff2aeef5..fc5025952860b 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -57,7 +57,7 @@ use params::{ NetworkConfigurationParams, MergeParameters, TransactionPoolParams, NodeKeyParams, NodeKeyType, Cors, CheckBlockCmd, }; -pub use params::{NoCustom, CoreParams, SharedParams, ImportParams, ExecutionStrategy, BenchmarkRuntimeParams}; +pub use params::{NoCustom, CoreParams, SharedParams, ImportParams, ExecutionStrategy}; pub use traits::GetSharedParams; use app_dirs::{AppInfo, AppDataType}; use log::info; @@ -1054,8 +1054,6 @@ where fill_transaction_pool_configuration(&mut config, cli.pool_config)?; - run_benchmark(cli.benchmark_config)?; - config.dev_key_seed = cli.keyring.account .map(|a| format!("//{}", a)).or_else(|| { if is_dev { From 86b32efa6800f4e189b7f2375879c801edeebdaa Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 28 Jan 2020 18:54:50 +0100 Subject: [PATCH 18/50] undo more changes --- frame/balances/src/lib.rs | 2 +- frame/identity/Cargo.toml | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 98c73c2503f71..b488b96701cf1 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -487,7 +487,7 @@ decl_module! { /// - Contains a limited number of reads and writes. /// # #[weight = SimpleDispatchInfo::FixedOperational(50_000)] - pub fn set_balance( + fn set_balance( origin, who: ::Source, #[compact] new_free: T::Balance, diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index b71978129fc21..c4bf7b9bc65c1 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -16,8 +16,8 @@ frame-system = { version = "2.0.0", default-features = false, path = "../system" sp-api = { version = "2.0.0", default-features = false, path = "../../primitives/api" } [dev-dependencies] -sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } -pallet-balances = { version = "2.0.0", default-features = false, path = "../balances" } +sp-core = { version = "2.0.0", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0", path = "../balances" } [features] default = ["std"] @@ -26,10 +26,8 @@ std = [ "codec/std", "sp-std/std", "sp-io/std", - "sp-core/std", "sp-api/std", "sp-runtime/std", "frame-support/std", "frame-system/std", - "pallet-balances/std", ] From dd87c93094bf2b3446db530db04600f0dea4aef5 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 29 Jan 2020 15:10:12 +0100 Subject: [PATCH 19/50] Update benchmarks --- frame/identity/src/benchmarking.rs | 27 ++++++++++++++++++++------- frame/identity/src/lib.rs | 22 +++++++++++++++++----- primitives/runtime/src/lib.rs | 2 +- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index df8b7acea3ddb..e560a1d0fa730 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -18,10 +18,9 @@ use super::*; -use sp_runtime::traits::SaturatedConversion; - use frame_system::RawOrigin; use sp_io::hashing::blake2_256; +use sp_runtime::traits::Bounded; use crate::Module as Identity; @@ -49,15 +48,19 @@ pub mod set_identity { /// /// Sets up state randomly and returns a randomly generated `set_identity` with sensible (fixed) /// values for all complexity components except those mentioned in the identity. - pub fn instance(components: &[(BenchmarkParameter, u32)]) -> crate::Call + pub fn instance(components: &[(BenchmarkParameter, u32)]) -> (crate::Call, T::AccountId) { - // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap(); - let _ = T::Currency::deposit_creating(&account::(0), 1_000_000_000_000_000_000u128.saturated_into()); for i in 0..r.1 { - let _ = T::Currency::deposit_creating(&account::(i), 1_000_000_000_000_000u128.saturated_into()); + sp_std::if_std!{ + println!("Components {:?} Index {:?}", components, i); + } + let _ = T::Currency::make_free_balance_be(&account::(i), BalanceOf::::max_value()); assert_eq!(Identity::::add_registrar(RawOrigin::Root.into(), account::(i)), Ok(())); + sp_std::if_std!{ + println!("# Registrars {:?}", Registrars::::get().len()); + } assert_eq!(Identity::::set_fee(RawOrigin::Signed(account::(i)).into(), i.into(), 10.into()), Ok(())); let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); assert_eq!(Identity::::set_fields(RawOrigin::Signed(account::(i)).into(), i.into(), fields), Ok(())); @@ -79,7 +82,17 @@ pub mod set_identity { twitter: data.clone(), }; + let caller = account::(r.1 + 1); + let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + // Return the `set_identity` call - crate::Call::::set_identity(info) + (crate::Call::::set_identity(info), caller) + } + + pub fn clean() { + IdentityOf::::remove_all(); + SuperOf::::remove_all(); + SubsOf::::remove_all(); + Registrars::::kill(); } } \ No newline at end of file diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 956930aa0189f..3ca24d6095cfa 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -865,8 +865,8 @@ decl_module! { } impl Benchmarking for Module { - const STEPS: u32 = 100; - const REPEATS: u32 = 10; + const STEPS: u32 = 10; + const REPEATS: u32 = 100; fn run_benchmarks() -> Vec { // first one is set_identity. @@ -888,12 +888,16 @@ impl Benchmarking for Module { (*n, if n == name { component_value } else { (h - l) / 2 + l }) ).collect(); - for _r in 0..Self::REPEATS { - let instance = benchmarking::set_identity::instance::(&c); + for r in 0..Self::REPEATS { + sp_std::if_std!{ + println!("STEP {:?} REPEAT {:?}", s, r); + } + let (call, caller) = benchmarking::set_identity::instance::(&c); let start = sp_io::benchmarking::current_time(); - assert_eq!(instance.dispatch(frame_system::RawOrigin::Signed(benchmarking::account::(0)).into()), Ok(())); + assert_eq!(call.dispatch(frame_system::RawOrigin::Signed(caller).into()), Ok(())); let finish = sp_io::benchmarking::current_time(); let elapsed = finish - start; + benchmarking::set_identity::clean::(); results.push((c.clone(), elapsed)); } } @@ -1254,4 +1258,12 @@ mod tests { assert_ok!(Identity::set_account_id(Origin::signed(4), 0, 3)); }); } + + #[test] + fn run_benchmarks() { + new_test_ext().execute_with(|| { + let result = Identity::run_benchmarks(); + println!("{:?}", result); + }); + } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 3ea79174dbc85..69a2b0134d5a8 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -679,7 +679,7 @@ pub fn print(print: impl traits::Printable) { } /// Parameters for this module. -#[derive(Encode, Decode, Clone, Copy, PartialEq)] +#[derive(Encode, Decode, Clone, Copy, PartialEq, Debug)] pub enum BenchmarkParameter { /// Registrar Count R, From 7c089f75859333c6456540c56c97f608fc61cf18 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 29 Jan 2020 21:09:25 +0100 Subject: [PATCH 20/50] Update Cargo.lock --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index a39ab673ddb47..b432d0449c392 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3825,7 +3825,7 @@ dependencies = [ "frame-system 2.0.0", "pallet-balances 2.0.0", "parity-scale-codec 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "sp-api 2.0.0", "sp-core 2.0.0", "sp-io 2.0.0", From 7bd0ae11cdff291b805c9633f184e59f49d17e43 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 29 Jan 2020 23:37:43 +0100 Subject: [PATCH 21/50] remove test --- frame/identity/src/lib.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 98ee1816783fa..11816e67212ac 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -1279,12 +1279,4 @@ mod tests { assert_ok!(Identity::set_account_id(Origin::signed(4), 0, 3)); }); } - - #[test] - fn run_benchmarks() { - new_test_ext().execute_with(|| { - let result = Identity::run_benchmarks(); - println!("{:?}", result); - }); - } } From 862dc675b65ab28f17bd13f79b979c78dfaeaad7 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 30 Jan 2020 01:15:43 +0100 Subject: [PATCH 22/50] Move loop out of runtime --- bin/node/runtime/src/lib.rs | 10 ++++-- frame/identity/src/lib.rs | 58 +++++++++++--------------------- primitives/runtime/src/lib.rs | 11 +++--- primitives/runtime/src/traits.rs | 8 ++--- 4 files changed, 32 insertions(+), 55 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 5124ef4513a29..c723a22adecb8 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -31,7 +31,7 @@ use node_primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index use sp_api::impl_runtime_apis; use sp_runtime::{ Permill, Perbill, Percent, ApplyExtrinsicResult, impl_opaque_keys, generic, create_runtime_str, - BenchmarkResults, + BenchmarkResult, BenchmarkParameter, }; use sp_runtime::curve::PiecewiseLinear; use sp_runtime::transaction_validity::TransactionValidity; @@ -810,8 +810,12 @@ impl_runtime_apis! { } impl pallet_identity::IdentityBenchmarks for Runtime { - fn run_benchmarks() -> Vec { - Identity::run_benchmarks() + fn run_benchmark(parameters: Vec<(BenchmarkParameter, u32)>, repeat: u32) -> Vec { + Identity::run_benchmark(parameters, repeat) + } + + fn get_components() -> Vec<(BenchmarkParameter, u32, u32)> { + pallet_identity::benchmarking::set_identity::components() } } } diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 11816e67212ac..96a79146cf541 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -69,7 +69,7 @@ use sp_std::prelude::*; use sp_std::{fmt::Debug, ops::Add, iter::once}; use enumflags2::BitFlags; use codec::{Encode, Decode}; -use sp_runtime::{DispatchResult, RuntimeDebug, BenchmarkResults, BenchmarkParameter}; +use sp_runtime::{DispatchResult, RuntimeDebug, BenchmarkResult, BenchmarkParameter}; use sp_runtime::traits::{StaticLookup, EnsureOrigin, Zero, AppendZerosInput, Dispatchable, Benchmarking}; use frame_support::{ decl_module, decl_event, decl_storage, ensure, decl_error, @@ -78,7 +78,7 @@ use frame_support::{ }; use frame_system::{self as system, ensure_signed, ensure_root}; -mod benchmarking; +pub mod benchmarking; type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; @@ -875,44 +875,22 @@ decl_module! { } } -impl Benchmarking for Module { - const STEPS: u32 = 10; - const REPEATS: u32 = 100; - - fn run_benchmarks() -> Vec { - // first one is set_identity. - let components = benchmarking::set_identity::components(); - // results go here - let mut results: Vec = Vec::new(); - // Select the component we will be benchmarking. Each component will be benchmarked. - for (name, low, high) in components.iter() { - // Create up to `STEPS` steps for that component between high and low. - let step_size = ((high - low) / Self::STEPS).max(1); - let num_of_steps = (high - low) / step_size; - for s in 0..num_of_steps { - // This is the value we will be testing for component `name` - let component_value = step_size * s; - - // Select the mid value for all the other components. - let c: Vec<(BenchmarkParameter, u32)> = components.iter() - .map(|(n, l, h)| - (*n, if n == name { component_value } else { (h - l) / 2 + l }) - ).collect(); - - for r in 0..Self::REPEATS { - sp_std::if_std!{ - println!("STEP {:?} REPEAT {:?}", s, r); - } - let (call, caller) = benchmarking::set_identity::instance::(&c); - let start = sp_io::benchmarking::current_time(); - assert_eq!(call.dispatch(frame_system::RawOrigin::Signed(caller).into()), Ok(())); - let finish = sp_io::benchmarking::current_time(); - let elapsed = finish - start; - benchmarking::set_identity::clean::(); - results.push((c.clone(), elapsed)); - } +impl Benchmarking for Module { + fn run_benchmark(parameters: Vec<(BenchmarkParameter, u32)>, repeat: u32) -> Vec { + let mut results: Vec = Vec::new(); + + for r in 0..repeat { + sp_std::if_std!{ + println!("REPEAT {:?}", r); } + let (call, caller) = benchmarking::set_identity::instance::(¶meters); + let start = sp_io::benchmarking::current_time(); + assert_eq!(call.dispatch(frame_system::RawOrigin::Signed(caller).into()), Ok(())); + let finish = sp_io::benchmarking::current_time(); + results.push(finish - start); + benchmarking::set_identity::clean::(); } + return results; } } @@ -920,7 +898,9 @@ impl Benchmarking for Module { sp_api::decl_runtime_apis! { pub trait IdentityBenchmarks { - fn run_benchmarks() -> Vec; + fn run_benchmark(parameters: Vec<(BenchmarkParameter, u32)>, repeat: u32) -> Vec; + + fn get_components() -> Vec<(BenchmarkParameter, u32, u32)>; } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 69a2b0134d5a8..41ff26d02ace1 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -678,18 +678,15 @@ pub fn print(print: impl traits::Printable) { print.print(); } -/// Parameters for this module. +/// An alphabet of possible parameters to use for benchmarking. #[derive(Encode, Decode, Clone, Copy, PartialEq, Debug)] pub enum BenchmarkParameter { - /// Registrar Count - R, - /// Additional Field Count - X, + A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, } /// Results from running benchmarks on a FRAME pallet. -/// Contains the parameters used when running the benchmark, and the duration of the function call in nanoseconds. -pub type BenchmarkResults = (Vec<(BenchmarkParameter, u32)>, u128); +/// Contains duration of the function call in nanoseconds after executing the same function multiple times. +pub type BenchmarkResult = u128; #[cfg(test)] mod tests { diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 619148abb04ff..6f658e05ea1f1 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1285,13 +1285,9 @@ pub trait BlockIdTo { } /// The module benchmarking trait. -pub trait Benchmarking { - /// Number of steps to take between variable ranges. - const STEPS: u32; - /// Number of benchmarking repetitions. - const REPEATS: u32; +pub trait Benchmarking { /// Run the benchmarks for this module. - fn run_benchmarks() -> Vec; + fn run_benchmark(parameters: Vec<(T, u32)>, repeat: u32) -> Vec; } #[cfg(test)] From 6d0c8b4b073b0d3fbc49b8072a2b73d5f41f42b7 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 3 Feb 2020 13:56:58 +0100 Subject: [PATCH 23/50] Benchmarking externalities --- Cargo.lock | 3 + bin/node-template/src/cli.rs | 3 +- bin/node/cli/src/cli.rs | 3 +- client/cli/src/lib.rs | 56 +++++------- client/cli/src/params.rs | 29 ++++++- client/db/Cargo.toml | 1 + client/db/src/lib.rs | 3 + client/service/src/chain_ops.rs | 28 +++++- client/service/src/lib.rs | 1 + client/src/lib.rs | 2 +- primitives/externalities/src/lib.rs | 9 ++ primitives/io/src/lib.rs | 10 +++ primitives/state-machine/src/backend.rs | 10 +++ primitives/state-machine/src/ext.rs | 18 ++++ .../state-machine/src/overlayed_changes.rs | 86 +++++++++++-------- 15 files changed, 184 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6720e9c658cb3..9a08d1027b082 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3811,6 +3811,7 @@ dependencies = [ "pallet-balances 2.0.0", "parity-scale-codec 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0", "sp-core 2.0.0", "sp-io 2.0.0", "sp-runtime 2.0.0", @@ -5178,6 +5179,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-identity 2.0.0", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rpassword 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "sc-client-api 2.0.0", @@ -5281,6 +5283,7 @@ dependencies = [ "parity-util-mem 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "quickcheck 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "sc-client 0.8.0", "sc-client-api 2.0.0", "sc-executor 0.8.0", diff --git a/bin/node-template/src/cli.rs b/bin/node-template/src/cli.rs index 6c51a34725781..81479fd859943 100644 --- a/bin/node-template/src/cli.rs +++ b/bin/node-template/src/cli.rs @@ -7,6 +7,7 @@ use sc_cli::{display_role, informant, parse_and_prepare, ParseAndPrepare, NoCust use sc_service::{AbstractService, Roles as ServiceRoles, Configuration}; use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair}; use crate::chain_spec; +use node_template_runtime::opaque::Block; use log::info; /// Parse command line arguments into service configuration. @@ -51,7 +52,7 @@ pub fn run(args: I, exit: E, version: VersionInfo) -> error::Result<()> ParseAndPrepare::CheckBlock(cmd) => cmd.run_with_builder(|config: Config<_>| Ok(new_full_start!(config).0), load_spec, exit), ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec), - ParseAndPrepare::Benchmark(cmd) => cmd.run(load_spec), + ParseAndPrepare::Benchmark(cmd) => cmd.run::(load_spec), ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_>| Ok(new_full_start!(config).0), load_spec), ParseAndPrepare::CustomCommand(_) => Ok(()) diff --git a/bin/node/cli/src/cli.rs b/bin/node/cli/src/cli.rs index 5a50b6a47fcf3..366c5cea20c64 100644 --- a/bin/node/cli/src/cli.rs +++ b/bin/node/cli/src/cli.rs @@ -24,6 +24,7 @@ use sc_cli::{display_role, parse_and_prepare, GetSharedParams, ParseAndPrepare}; use crate::{service, ChainSpec, load_spec}; use crate::factory_impl::FactoryState; use node_transaction_factory::RuntimeAdapter; +use node_runtime::Block; use futures::{channel::oneshot, future::{select, Either}}; /// Custom subcommands. @@ -136,7 +137,7 @@ pub fn run(args: I, exit: E, version: sc_cli::VersionInfo) -> error::Re ParseAndPrepare::CheckBlock(cmd) => cmd.run_with_builder(|config: Config<_, _>| Ok(new_full_start!(config).0), load_spec, exit), ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec), - ParseAndPrepare::Benchmark(cmd) => cmd.run(load_spec), + ParseAndPrepare::Benchmark(cmd) => cmd.run::(load_spec), ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_, _>| Ok(new_full_start!(config).0), load_spec), ParseAndPrepare::CustomCommand(CustomSubcommands::Factory(cli_args)) => { diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index f412be86743b9..d8d5b25d52e1d 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -245,7 +245,7 @@ where ParseAndPreparePurge { params, version } ), params::CoreParams::Benchmark(params) => ParseAndPrepare::Benchmark( - ParseAndPrepareBenchmark { params, version } + ParseAndPrepareBenchmark { params } ), params::CoreParams::Revert(params) => ParseAndPrepare::RevertChain( ParseAndPrepareRevert { params, version } @@ -283,7 +283,7 @@ pub enum ParseAndPrepare<'a, CC, RP> { /// Command ready to purge the chain. PurgeChain(ParseAndPreparePurge<'a>), /// Command ready to benchmark the chain. - Benchmark(ParseAndPrepareBenchmark<'a>), + Benchmark(ParseAndPrepareBenchmark), /// Command ready to revert the chain. RevertChain(ParseAndPrepareRevert<'a>), /// An additional custom command passed to `parse_and_prepare`. @@ -300,7 +300,7 @@ impl<'a, CC, RP> ParseAndPrepare<'a, CC, RP> where CC: GetSharedParams { ParseAndPrepare::ImportBlocks(c) => Some(&c.params.shared_params), ParseAndPrepare::CheckBlock(c) => Some(&c.params.shared_params), ParseAndPrepare::PurgeChain(c) => Some(&c.params.shared_params), - ParseAndPrepare::Benchmark(c) => Some(&c.params.shared_params), + ParseAndPrepare::Benchmark(_) => None, ParseAndPrepare::RevertChain(c) => Some(&c.params.shared_params), ParseAndPrepare::CustomCommand(c) => c.shared_params(), } @@ -367,13 +367,8 @@ impl<'a, CC, RP> ParseAndPrepare<'a, CC, RP> { c.version, default_base_path, )).transpose(), - ParseAndPrepare::Benchmark(c) => - Some(create_config_with_db_path( - spec_factory, - &c.params.shared_params, - c.version, - default_base_path, - )).transpose(), + ParseAndPrepare::Benchmark(_) => + Ok(None), ParseAndPrepare::RevertChain(c) => Some(create_config_with_db_path( spec_factory, @@ -729,44 +724,33 @@ impl<'a> ParseAndPreparePurge<'a> { } /// Command ready to benchmark the runtime. -pub struct ParseAndPrepareBenchmark<'a> { +pub struct ParseAndPrepareBenchmark { params: BenchmarkCmd, - version: &'a VersionInfo, } -impl<'a> ParseAndPrepareBenchmark<'a> { +impl ParseAndPrepareBenchmark { /// Runs the command and benchmarks the chain. - pub fn run( + pub fn run( self, spec_factory: S ) -> error::Result<()> where + B: BlockT, + D: sc_service::NativeExecutionDispatch + 'static, S: FnOnce(&str) -> Result>, String>, G: RuntimeGenesis, E: ChainSpecExtension, { - let mut config = create_config_with_db_path::<(), _, _, _>( - spec_factory, - &self.params.shared_params, - self.version, - None, - )?; - fill_config_keystore_in_memory(&mut config)?; - let db_path = match config.database { - DatabaseConfig::Path { path, .. } => path, - _ => { - eprintln!("Cannot purge custom database implementation"); - return Ok(()); - } + let shared_params = SharedParams { + chain: self.params.chain, + dev: false, + base_path: None, + log: self.params.log }; - - if self.params.pallet.is_some() { - print!("Input contains: {:?}", self.params.pallet.unwrap()) - } else { - print!("Input is Empty"); - } - - pallet_identity::run_benchmarks(); - + init_logger(shared_params.log.as_ref().map(|v| v.as_ref()).unwrap_or("")); + let spec = load_spec(&shared_params, spec_factory)?; + let execution_strategy = self.params.execution.unwrap_or(ExecutionStrategy::Native).into(); + let wasm_method = self.params.wasm_method.into(); + sc_service::chain_ops::benchmark_runtime::(execution_strategy, wasm_method)?; Ok(()) } } diff --git a/client/cli/src/params.rs b/client/cli/src/params.rs index 1b731c5408867..00c76d7c1cd3e 100644 --- a/client/cli/src/params.rs +++ b/client/cli/src/params.rs @@ -861,9 +861,32 @@ pub struct BenchmarkCmd { #[structopt(short, long)] pub pallet: Option, - #[allow(missing_docs)] - #[structopt(flatten)] - pub shared_params: SharedParams, + /// The execution strategy that should be used for benchmarks + #[structopt( + long = "execution", + value_name = "STRATEGY", + possible_values = &ExecutionStrategy::variants(), + case_insensitive = true, + )] + pub execution: Option, + + /// Method for executing Wasm runtime code. + #[structopt( + long = "wasm-execution", + value_name = "METHOD", + possible_values = &WasmExecutionMethod::enabled_variants(), + case_insensitive = true, + default_value = "Interpreted" + )] + pub wasm_method: WasmExecutionMethod, + + /// Specify the chain specification (one of dev, local or staging). + #[structopt(long = "chain", value_name = "CHAIN_SPEC")] + pub chain: Option, + + /// Sets a custom logging filter. + #[structopt(short = "l", long = "log", value_name = "LOG_PATTERN")] + pub log: Option, } /// All core commands that are provided by default. diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index dcc7df29ca11c..483af2ee8c63a 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] parking_lot = "0.9.0" log = "0.4.8" +rand = "0.7" kvdb = "0.3.0" kvdb-rocksdb = { version = "0.4", optional = true } kvdb-memorydb = "0.3.0" diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index be569194972cc..789cfc7f8d885 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -28,6 +28,7 @@ pub mod light; pub mod offchain; +pub mod bench; mod children; mod cache; @@ -79,6 +80,7 @@ use crate::storage_cache::{CachingState, SharedCache, new_shared_cache}; use crate::stats::StateUsageStats; use log::{trace, debug, warn}; pub use sc_state_db::PruningMode; +pub use bench::BenchmarkingState; #[cfg(feature = "test-helpers")] use sc_client::in_mem::Backend as InMemoryBackend; @@ -104,6 +106,7 @@ pub use kvdb; pub struct RefTrackingState { state: DbState, storage: Arc>, + parent_hash: Option, } diff --git a/client/service/src/chain_ops.rs b/client/service/src/chain_ops.rs index 0c2fe79718a72..8b9028209d16c 100644 --- a/client/service/src/chain_ops.rs +++ b/client/service/src/chain_ops.rs @@ -27,9 +27,11 @@ use sp_runtime::traits::{ }; use sp_runtime::generic::{BlockId, SignedBlock}; use codec::{Decode, Encode, IoReader}; -use sc_client::Client; +use sc_client::{Client, ExecutionStrategy, StateMachine}; +use sc_client_db::BenchmarkingState; use sp_consensus::import_queue::{IncomingBlock, Link, BlockImportError, BlockImportResult, ImportQueue}; use sp_consensus::BlockOrigin; +use sc_executor::{NativeExecutor, NativeExecutionDispatch, WasmExecutionMethod}; use std::{io::{Read, Write, Seek}, pin::Pin}; @@ -43,6 +45,30 @@ pub fn build_spec(spec: ChainSpec, raw: bool) -> error::Result( + strategy: ExecutionStrategy, + wasm_method: WasmExecutionMethod, +) -> error::Result<()> { + let mut changes = Default::default(); + let state = BenchmarkingState::::new()?; + let executor = NativeExecutor::::new( + wasm_method, + None, // heap pages + ); + let _ = StateMachine::<_, _, NumberFor, _>::new( + &state, + None, + &mut changes, + &executor, + "run_benchmark", + &[], + Default::default(), + ).execute(strategy).map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?; + info!("Done."); + Ok(()) +} + + impl< TBl, TRtApi, TCfg, TGen, TCSExt, TBackend, TExec, TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index c7069ac6e5818..b525b59125c26 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -65,6 +65,7 @@ pub use sp_transaction_pool::{TransactionPool, InPoolTransaction, error::IntoPoo pub use sc_transaction_pool::txpool::Options as TransactionPoolOptions; pub use sc_client::FinalityNotifications; pub use sc_rpc::Metadata as RpcMetadata; +pub use sc_executor::NativeExecutionDispatch; #[doc(hidden)] pub use std::{ops::Deref, result::Result, sync::Arc}; #[doc(hidden)] diff --git a/client/src/lib.rs b/client/src/lib.rs index 4caabfa201fe6..d97246d478c2b 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -104,4 +104,4 @@ pub use crate::{ }, leaves::LeafSet, }; -pub use sp_state_machine::{ExecutionStrategy, StorageProof}; +pub use sp_state_machine::{ExecutionStrategy, StorageProof, StateMachine}; diff --git a/primitives/externalities/src/lib.rs b/primitives/externalities/src/lib.rs index 350b65d190840..e4687f9aea7ec 100644 --- a/primitives/externalities/src/lib.rs +++ b/primitives/externalities/src/lib.rs @@ -202,6 +202,15 @@ pub trait Externalities: ExtensionStore { /// /// Returns the SCALE encoded hash. fn storage_changes_root(&mut self, parent: &[u8]) -> Result>, ()>; + + + fn wipe(&mut self) { + unimplemented!() + } + + fn commit(&mut self) { + unimplemented!() + } } /// Extension for the [`Externalities`] trait. diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index 7b62bd4ceacd9..9b668e0623386 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -784,6 +784,16 @@ pub trait Benchmarking { .expect("Unix time doesn't go backwards; qed") .as_nanos() } + + /// Reset state to empty. + fn wipe_db(&mut self) { + self.wipe() + } + + /// Commit pending storage changes to the trie database. + fn commit_db(&mut self) { + self.commit() + } } /// Wasm-only interface that provides functions for interacting with the sandbox. diff --git a/primitives/state-machine/src/backend.rs b/primitives/state-machine/src/backend.rs index 4ef9b970ae21d..ff412605619aa 100644 --- a/primitives/state-machine/src/backend.rs +++ b/primitives/state-machine/src/backend.rs @@ -213,6 +213,16 @@ pub trait Backend: std::fmt::Debug { fn usage_info(&self) -> UsageInfo { UsageInfo::empty() } + + /// Wipe the state database. + fn wipe(&mut self) -> Result<(), Self::Error> { + unimplemented!() + } + + /// Commit given transaction to storage. + fn commit(&mut self, _storage_root: H::Out, _transaction: Self::Transaction) -> Result<(), Self::Error> { + unimplemented!() + } } impl<'a, T: Backend, H: Hasher> Backend for &'a T { diff --git a/primitives/state-machine/src/ext.rs b/primitives/state-machine/src/ext.rs index f293ae9f51615..ec5ec3ce987f3 100644 --- a/primitives/state-machine/src/ext.rs +++ b/primitives/state-machine/src/ext.rs @@ -582,6 +582,24 @@ where root.map(|r| r.map(|o| o.encode())) } + + fn wipe(&mut self) { + self.overlay.drain_storage_changes(&self.backend, None, Default::default(), self.storage_transaction_cache) + .expect(EXT_NOT_ALLOWED_TO_FAIL); + self.storage_transaction_cache.reset(); + self.backend.wipe().expect(EXT_NOT_ALLOWED_TO_FAIL) + } + + fn commit(&mut self) { + self.overlay.commit_prospective(); + self.overlay.drain_storage_changes(&self.backend, None, Default::default(), self.storage_transaction_cache) + .expect(EXT_NOT_ALLOWED_TO_FAIL); + self.backend.commit( + self.storage_transaction_cache.transaction_storage_root.take().expect(EXT_NOT_ALLOWED_TO_FAIL), + self.storage_transaction_cache.transaction.take().expect(EXT_NOT_ALLOWED_TO_FAIL), + ).expect(EXT_NOT_ALLOWED_TO_FAIL); + self.storage_transaction_cache.reset(); + } } impl<'a, H, B, N> sp_externalities::ExtensionStore for Ext<'a, H, N, B> diff --git a/primitives/state-machine/src/overlayed_changes.rs b/primitives/state-machine/src/overlayed_changes.rs index ed6f30a4f596b..9d5dfd6530412 100644 --- a/primitives/state-machine/src/overlayed_changes.rs +++ b/primitives/state-machine/src/overlayed_changes.rs @@ -428,15 +428,18 @@ impl OverlayedChanges { /// /// Panics: /// Will panic if there are any uncommitted prospective changes. - pub fn into_committed(self) -> ( + fn drain_committed(&mut self) -> ( impl Iterator)>, impl Iterator)>, OwnedChildInfo))>, ){ assert!(self.prospective.is_empty()); ( - self.committed.top.into_iter().map(|(k, v)| (k, v.value)), - self.committed.children.into_iter() - .map(|(sk, (v, ci))| (sk, (v.into_iter().map(|(k, v)| (k, v.value)), ci))) + std::mem::replace(&mut self.committed.top, Default::default()) + .into_iter() + .map(|(k, v)| (k, v.value)), + std::mem::replace(&mut self.committed.children, Default::default()) + .into_iter() + .map(|(sk, (v, ci))| (sk, (v.into_iter().map(|(k, v)| (k, v.value)), ci))), ) } @@ -444,46 +447,59 @@ impl OverlayedChanges { pub fn into_storage_changes< B: Backend, H: Hasher, N: BlockNumber >( - self, + mut self, backend: &B, changes_trie_state: Option<&ChangesTrieState>, parent_hash: H::Out, mut cache: StorageTransactionCache, ) -> Result, String> where H::Out: Ord + Encode + 'static { - // If the transaction does not exist, we generate it. - if cache.transaction.is_none() { - self.storage_root(backend, &mut cache); - } + self.drain_storage_changes(backend, changes_trie_state, parent_hash, &mut cache) + } - let (transaction, transaction_storage_root) = cache.transaction.take() - .and_then(|t| cache.transaction_storage_root.take().map(|tr| (t, tr))) - .expect("Transaction was be generated as part of `storage_root`; qed"); - - // If the transaction does not exist, we generate it. - if cache.changes_trie_transaction.is_none() { - self.changes_trie_root( - backend, - changes_trie_state, - parent_hash, - false, - &mut cache, - ).map_err(|_| "Failed to generate changes trie transaction")?; - } + /// Drain all changes into a [`StorageChanges`] instance. Leave empty overlay in place. + pub fn drain_storage_changes< + B: Backend, H: Hasher, N: BlockNumber + >( + &mut self, + backend: &B, + changes_trie_state: Option<&ChangesTrieState>, + parent_hash: H::Out, + mut cache: &mut StorageTransactionCache, + ) -> Result, String> where H::Out: Ord + Encode + 'static { + // If the transaction does not exist, we generate it. + if cache.transaction.is_none() { + self.storage_root(backend, &mut cache); + } - let changes_trie_transaction = cache.changes_trie_transaction - .take() - .expect("Changes trie transaction was generated by `changes_trie_root`; qed"); + let (transaction, transaction_storage_root) = cache.transaction.take() + .and_then(|t| cache.transaction_storage_root.take().map(|tr| (t, tr))) + .expect("Transaction was be generated as part of `storage_root`; qed"); + + // If the transaction does not exist, we generate it. + if cache.changes_trie_transaction.is_none() { + self.changes_trie_root( + backend, + changes_trie_state, + parent_hash, + false, + &mut cache, + ).map_err(|_| "Failed to generate changes trie transaction")?; + } - let (main_storage_changes, child_storage_changes) = self.into_committed(); + let changes_trie_transaction = cache.changes_trie_transaction + .take() + .expect("Changes trie transaction was generated by `changes_trie_root`; qed"); - Ok(StorageChanges { - main_storage_changes: main_storage_changes.collect(), - child_storage_changes: child_storage_changes.map(|(sk, it)| (sk, it.0.collect())).collect(), - transaction, - transaction_storage_root, - changes_trie_transaction, - }) - } + let (main_storage_changes, child_storage_changes) = self.drain_committed(); + + Ok(StorageChanges { + main_storage_changes: main_storage_changes.collect(), + child_storage_changes: child_storage_changes.map(|(sk, it)| (sk, it.0.collect())).collect(), + transaction, + transaction_storage_root, + changes_trie_transaction, + }) + } /// Inserts storage entry responsible for current extrinsic index. #[cfg(test)] From 3c5dcf79d09b8c3ca80cfcef1be874a4d47cbe08 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 3 Feb 2020 14:09:15 +0100 Subject: [PATCH 24/50] Benchmarking state --- client/db/src/bench.rs | 259 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 259 insertions(+) create mode 100644 client/db/src/bench.rs diff --git a/client/db/src/bench.rs b/client/db/src/bench.rs new file mode 100644 index 0000000000000..172da17c894cd --- /dev/null +++ b/client/db/src/bench.rs @@ -0,0 +1,259 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! State backend that's useful for benchmarking + +use std::sync::Arc; +use std::path::PathBuf; +use std::io; +use rand::Rng; + +use hash_db::Prefix; +use sp_trie::{MemoryDB, prefixed_key}; +use sp_core::storage::ChildInfo; +use sp_runtime::traits::{Block as BlockT, HasherFor}; +use sp_state_machine::{DBValue, backend::Backend as StateBackend}; +use crate::{DatabaseSettings, DatabaseSettingsSrc, columns}; +use crate::utils::DatabaseType; +//use log::{trace, debug, warn}; +pub use sc_state_db::PruningMode; +use kvdb::KeyValueDB; + +type DbState = sp_state_machine::TrieBackend< + Arc>>, HasherFor +>; + +struct StorageDb { + db: Arc, + _block: std::marker::PhantomData, +} + +impl sp_state_machine::Storage> for StorageDb { + fn get(&self, key: &Block::Hash, prefix: Prefix) -> Result, String> { + let key = prefixed_key::>(key, prefix); + self.db.get(columns::STATE, &key) + .map_err(|e| format!("Database backend error: {:?}", e)) + } +} + +impl sc_state_db::NodeDb for StorageDb { + type Error = io::Error; + type Key = [u8]; + + fn get(&self, key: &[u8]) -> Result>, Self::Error> { + self.db.get(columns::STATE, key).map(|r| r.map(|v| v.to_vec())) + } +} + +/// State that manages the backend database reference. Allows runtime to control the database. +pub struct BenchmarkingState { + state: Option>, + path: PathBuf, +} + +impl BenchmarkingState { + /// Create a new instance that creates a database in a temporary dir. + pub fn new() -> Result { + let temp_dir = PathBuf::from(std::env::temp_dir()); + let name: String = rand::thread_rng().sample_iter(&rand::distributions::Alphanumeric).take(10).collect(); + let path = temp_dir.join(&name); + + std::fs::create_dir(&path).map_err(|_| String::from("Error creating temp dir"))?; + let mut state = BenchmarkingState { + state: None, + path, + }; + state.reopen()?; + Ok(state) + } + + fn reopen(&mut self) -> Result<(), String> { + self.state = None; + let config = DatabaseSettings { + state_cache_size: 0, + state_cache_child_ratio: None, + pruning: PruningMode::ArchiveAll, + source: DatabaseSettingsSrc::Path { path: self.path.clone(), cache_size: None }, + }; + + let db = crate::utils::open_database::(&config, DatabaseType::Full) + .map_err(|e| format!("Error opening dadabase: {:?}", e))?; + let mut root = B::Hash::default(); + let mut mdb = MemoryDB::>::default(); + sp_state_machine::TrieDBMut::>::new(&mut mdb, &mut root); + self.state = Some(DbState::::new(Arc::new(StorageDb:: { db, _block: Default::default() }), root)); + Ok(()) + } + + fn kill(&mut self) -> Result<(), String> { + self.state = None; + std::fs::remove_dir_all(&self.path).map_err(|_| "Error removing database dir".into()) + } +} + +impl Drop for BenchmarkingState { + fn drop(&mut self) { + self.state = None; + self.kill().ok(); + } +} + +fn state_err() -> String { + "State is not open".into() +} + +impl StateBackend> for BenchmarkingState { + type Error = as StateBackend>>::Error; + type Transaction = as StateBackend>>::Transaction; + type TrieBackendStorage = as StateBackend>>::TrieBackendStorage; + + fn storage(&self, key: &[u8]) -> Result>, Self::Error> { + self.state.as_ref().ok_or_else(state_err)?.storage(key) + } + + fn storage_hash(&self, key: &[u8]) -> Result, Self::Error> { + self.state.as_ref().ok_or_else(state_err)?.storage_hash(key) + } + + fn child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error> { + self.state.as_ref().ok_or_else(state_err)?.child_storage(storage_key, child_info, key) + } + + fn exists_storage(&self, key: &[u8]) -> Result { + self.state.as_ref().ok_or_else(state_err)?.exists_storage(key) + } + + fn exists_child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result { + self.state.as_ref().ok_or_else(state_err)?.exists_child_storage(storage_key, child_info, key) + } + + fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { + self.state.as_ref().ok_or_else(state_err)?.next_storage_key(key) + } + + fn next_child_storage_key( + &self, + storage_key: &[u8], + child_info: ChildInfo, + key: &[u8], + ) -> Result>, Self::Error> { + self.state.as_ref().ok_or_else(state_err)?.next_child_storage_key(storage_key, child_info, key) + } + + fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { + if let Some(state) = self.state.as_ref() { + state.for_keys_with_prefix(prefix, f) + } + } + + fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { + if let Some(state) = self.state.as_ref() { + state.for_key_values_with_prefix(prefix, f) + } + } + + fn for_keys_in_child_storage( + &self, + storage_key: &[u8], + child_info: ChildInfo, + f: F, + ) { + if let Some(state) = self.state.as_ref() { + state.for_keys_in_child_storage(storage_key, child_info, f) + } + } + + fn for_child_keys_with_prefix( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + f: F, + ) { + if let Some(state) = self.state.as_ref() { + state.for_child_keys_with_prefix(storage_key, child_info, prefix, f) + } + } + + fn storage_root(&self, delta: I) -> (B::Hash, Self::Transaction) + where + I: IntoIterator, Option>)> + { + self.state.as_ref().map_or(Default::default(), |s| s.storage_root(delta)) + } + + fn child_storage_root( + &self, + storage_key: &[u8], + child_info: ChildInfo, + delta: I, + ) -> (B::Hash, bool, Self::Transaction) + where + I: IntoIterator, Option>)>, + { + self.state.as_ref().map_or(Default::default(), |s| s.child_storage_root(storage_key, child_info, delta)) + } + + fn pairs(&self) -> Vec<(Vec, Vec)> { + self.state.as_ref().map_or(Default::default(), |s| s.pairs()) + } + + fn keys(&self, prefix: &[u8]) -> Vec> { + self.state.as_ref().map_or(Default::default(), |s| s.keys(prefix)) + } + + fn child_keys( + &self, + storage_key: &[u8], + child_info: ChildInfo, + prefix: &[u8], + ) -> Vec> { + self.state.as_ref().map_or(Default::default(), |s| s.child_keys(storage_key, child_info, prefix)) + } + + fn as_trie_backend(&mut self) + -> Option<&sp_state_machine::TrieBackend>> + { + self.state.as_mut().map_or(None, |s| s.as_trie_backend()) + } + + fn commit(&mut self, _storage_root: B::Hash, mut transaction: Self::Transaction) -> Result<(), Self::Error> { + println!("Committing: {:?}", transaction.drain()); + self.reopen() + } + + fn wipe(&mut self) -> Result<(), Self::Error> { + self.kill()?; + self.reopen() + } +} + +impl std::fmt::Debug for BenchmarkingState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "DB at {:?}", self.path) + } +} + From d7c0ae88b07aeb397698fccc26d8c86f69c3dbc1 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 3 Feb 2020 15:33:16 +0100 Subject: [PATCH 25/50] Implemented commit --- client/cli/src/lib.rs | 2 +- client/cli/src/params.rs | 2 +- client/db/src/bench.rs | 56 ++++++++++++++++++++++++++------- client/service/src/chain_ops.rs | 19 ++++++++--- 4 files changed, 60 insertions(+), 19 deletions(-) diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 3d48206193500..5e7a194d049da 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -750,7 +750,7 @@ impl ParseAndPrepareBenchmark { let spec = load_spec(&shared_params, spec_factory)?; let execution_strategy = self.params.execution.unwrap_or(ExecutionStrategy::Native).into(); let wasm_method = self.params.wasm_method.into(); - sc_service::chain_ops::benchmark_runtime::(execution_strategy, wasm_method)?; + sc_service::chain_ops::benchmark_runtime::(spec, execution_strategy, wasm_method)?; Ok(()) } } diff --git a/client/cli/src/params.rs b/client/cli/src/params.rs index 8722cec8500a0..9bb56ff56021d 100644 --- a/client/cli/src/params.rs +++ b/client/cli/src/params.rs @@ -981,7 +981,7 @@ impl StructOpt for CoreParams where ("revert", Some(matches)) => CoreParams::Revert(RevertCmd::from_clap(matches)), ("purge-chain", Some(matches)) => CoreParams::PurgeChain(PurgeChainCmd::from_clap(matches)), - ("benchrmark-runtime", Some(matches)) => + ("benchmark-runtime", Some(matches)) => CoreParams::Benchmark(BenchmarkCmd::from_clap(matches)), (_, None) => CoreParams::Run(MergeParameters::from_clap(matches)), _ => CoreParams::Custom(CC::from_clap(matches)), diff --git a/client/db/src/bench.rs b/client/db/src/bench.rs index 172da17c894cd..450a04c462af5 100644 --- a/client/db/src/bench.rs +++ b/client/db/src/bench.rs @@ -25,12 +25,13 @@ use hash_db::Prefix; use sp_trie::{MemoryDB, prefixed_key}; use sp_core::storage::ChildInfo; use sp_runtime::traits::{Block as BlockT, HasherFor}; +use sp_runtime::Storage; use sp_state_machine::{DBValue, backend::Backend as StateBackend}; use crate::{DatabaseSettings, DatabaseSettingsSrc, columns}; use crate::utils::DatabaseType; //use log::{trace, debug, warn}; pub use sc_state_db::PruningMode; -use kvdb::KeyValueDB; +use kvdb::{KeyValueDB, DBTransaction}; type DbState = sp_state_machine::TrieBackend< Arc>>, HasherFor @@ -59,28 +60,47 @@ impl sc_state_db::NodeDb for StorageDb { } /// State that manages the backend database reference. Allows runtime to control the database. -pub struct BenchmarkingState { - state: Option>, +pub struct BenchmarkingState { + state: Option>, + db: Option>, path: PathBuf, + root: B::Hash, } impl BenchmarkingState { /// Create a new instance that creates a database in a temporary dir. - pub fn new() -> Result { + pub fn new(genesis: Storage) -> Result { let temp_dir = PathBuf::from(std::env::temp_dir()); let name: String = rand::thread_rng().sample_iter(&rand::distributions::Alphanumeric).take(10).collect(); let path = temp_dir.join(&name); + let mut root = B::Hash::default(); + let mut mdb = MemoryDB::>::default(); + sp_state_machine::TrieDBMut::>::new(&mut mdb, &mut root); + std::fs::create_dir(&path).map_err(|_| String::from("Error creating temp dir"))?; let mut state = BenchmarkingState { state: None, + db: None, path, + root, }; + state.reopen()?; + let child_delta = genesis.children.into_iter().map(|(storage_key, child_content)| ( + storage_key, + child_content.data.into_iter().map(|(k, v)| (k, Some(v))), child_content.child_info), + ); + let (root, transaction) = state.state.as_ref().unwrap().full_storage_root( + genesis.top.into_iter().map(|(k, v)| (k, Some(v))), + child_delta, + ); + state.commit(root, transaction)?; Ok(state) } fn reopen(&mut self) -> Result<(), String> { + self.db = None; self.state = None; let config = DatabaseSettings { state_cache_size: 0, @@ -91,14 +111,13 @@ impl BenchmarkingState { let db = crate::utils::open_database::(&config, DatabaseType::Full) .map_err(|e| format!("Error opening dadabase: {:?}", e))?; - let mut root = B::Hash::default(); - let mut mdb = MemoryDB::>::default(); - sp_state_machine::TrieDBMut::>::new(&mut mdb, &mut root); - self.state = Some(DbState::::new(Arc::new(StorageDb:: { db, _block: Default::default() }), root)); + self.db = Some(db.clone()); + self.state = Some(DbState::::new(Arc::new(StorageDb:: { db, _block: Default::default() }), self.root)); Ok(()) } fn kill(&mut self) -> Result<(), String> { + self.db = None; self.state = None; std::fs::remove_dir_all(&self.path).map_err(|_| "Error removing database dir".into()) } @@ -106,7 +125,6 @@ impl BenchmarkingState { impl Drop for BenchmarkingState { fn drop(&mut self) { - self.state = None; self.kill().ok(); } } @@ -240,9 +258,23 @@ impl StateBackend> for BenchmarkingState { self.state.as_mut().map_or(None, |s| s.as_trie_backend()) } - fn commit(&mut self, _storage_root: B::Hash, mut transaction: Self::Transaction) -> Result<(), Self::Error> { - println!("Committing: {:?}", transaction.drain()); - self.reopen() + fn commit(&mut self, storage_root: B::Hash, mut transaction: Self::Transaction) -> Result<(), Self::Error> { + if let Some(db) = self.db.as_ref() { + let mut db_transaction = DBTransaction::new(); + + for (key, (val, rc)) in transaction.drain() { + if rc > 0 { + db_transaction.put(columns::STATE, &key, &val); + } else if rc < 0 { + db_transaction.delete(columns::STATE, &key); + } + } + db.write(db_transaction).map_err(|_| String::from("Error committing transaction"))?; + self.root = storage_root; + self.reopen() + } else { + Err("Trying to commit to a closed db".into()) + } } fn wipe(&mut self) -> Result<(), Self::Error> { diff --git a/client/service/src/chain_ops.rs b/client/service/src/chain_ops.rs index 8b9028209d16c..11b4e13921147 100644 --- a/client/service/src/chain_ops.rs +++ b/client/service/src/chain_ops.rs @@ -22,8 +22,9 @@ use crate::error::Error; use sc_chain_spec::{ChainSpec, RuntimeGenesis, Extension}; use log::{warn, info}; use futures::{future, prelude::*}; -use sp_runtime::traits::{ - Block as BlockT, NumberFor, One, Zero, Header, SaturatedConversion +use sp_runtime::{BuildStorage, traits::{ + Block as BlockT, NumberFor, One, Zero, Header, SaturatedConversion + } }; use sp_runtime::generic::{BlockId, SignedBlock}; use codec::{Decode, Encode, IoReader}; @@ -45,12 +46,20 @@ pub fn build_spec(spec: ChainSpec, raw: bool) -> error::Result( +/// Run runtime benchmarks. +pub fn benchmark_runtime ( + spec: ChainSpec, strategy: ExecutionStrategy, wasm_method: WasmExecutionMethod, -) -> error::Result<()> { +) -> error::Result<()> where + TBl: BlockT, + TExecDisp: NativeExecutionDispatch + 'static, + G: RuntimeGenesis, + E: Extension, +{ + let genesis_storage = spec.build_storage()?; let mut changes = Default::default(); - let state = BenchmarkingState::::new()?; + let state = BenchmarkingState::::new(genesis_storage)?; let executor = NativeExecutor::::new( wasm_method, None, // heap pages From 38602b8157e2434363af69a9ed98ac3bb2f315c0 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Tue, 4 Feb 2020 10:58:02 +0100 Subject: [PATCH 26/50] Make CLI work, move loop back into runtime --- bin/node/runtime/src/lib.rs | 10 ++---- client/service/src/chain_ops.rs | 5 +-- frame/identity/src/lib.rs | 57 ++++++++++++++++++++++---------- primitives/runtime/src/lib.rs | 2 +- primitives/runtime/src/traits.rs | 7 ++-- 5 files changed, 51 insertions(+), 30 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index c723a22adecb8..0a7441d4e410b 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -31,7 +31,7 @@ use node_primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index use sp_api::impl_runtime_apis; use sp_runtime::{ Permill, Perbill, Percent, ApplyExtrinsicResult, impl_opaque_keys, generic, create_runtime_str, - BenchmarkResult, BenchmarkParameter, + BenchmarkResults, BenchmarkParameter, }; use sp_runtime::curve::PiecewiseLinear; use sp_runtime::transaction_validity::TransactionValidity; @@ -810,12 +810,8 @@ impl_runtime_apis! { } impl pallet_identity::IdentityBenchmarks for Runtime { - fn run_benchmark(parameters: Vec<(BenchmarkParameter, u32)>, repeat: u32) -> Vec { - Identity::run_benchmark(parameters, repeat) - } - - fn get_components() -> Vec<(BenchmarkParameter, u32, u32)> { - pallet_identity::benchmarking::set_identity::components() + fn run_benchmarks() -> Vec { + Identity::run_benchmarks() } } } diff --git a/client/service/src/chain_ops.rs b/client/service/src/chain_ops.rs index 11b4e13921147..b0fe106534f23 100644 --- a/client/service/src/chain_ops.rs +++ b/client/service/src/chain_ops.rs @@ -64,15 +64,16 @@ pub fn benchmark_runtime ( wasm_method, None, // heap pages ); - let _ = StateMachine::<_, _, NumberFor, _>::new( + let result = StateMachine::<_, _, NumberFor, _>::new( &state, None, &mut changes, &executor, - "run_benchmark", + "IdentityBenchmarks_run_benchmarks", &[], Default::default(), ).execute(strategy).map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?; + println!("{:?}", result); info!("Done."); Ok(()) } diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 96a79146cf541..b163f6ce08ca4 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -69,7 +69,7 @@ use sp_std::prelude::*; use sp_std::{fmt::Debug, ops::Add, iter::once}; use enumflags2::BitFlags; use codec::{Encode, Decode}; -use sp_runtime::{DispatchResult, RuntimeDebug, BenchmarkResult, BenchmarkParameter}; +use sp_runtime::{DispatchResult, RuntimeDebug, BenchmarkResults, BenchmarkParameter}; use sp_runtime::traits::{StaticLookup, EnsureOrigin, Zero, AppendZerosInput, Dispatchable, Benchmarking}; use frame_support::{ decl_module, decl_event, decl_storage, ensure, decl_error, @@ -875,22 +875,45 @@ decl_module! { } } -impl Benchmarking for Module { - fn run_benchmark(parameters: Vec<(BenchmarkParameter, u32)>, repeat: u32) -> Vec { - let mut results: Vec = Vec::new(); - - for r in 0..repeat { - sp_std::if_std!{ - println!("REPEAT {:?}", r); +impl Benchmarking for Module { + const STEPS: u32 = 10; + const REPEATS: u32 = 100; + + fn run_benchmarks() -> Vec { + // first one is set_identity. + let components = benchmarking::set_identity::components(); + // results go here + let mut results: Vec = Vec::new(); + // Select the component we will be benchmarking. Each component will be benchmarked. + for (name, low, high) in components.iter() { + // Create up to `STEPS` steps for that component between high and low. + let step_size = ((high - low) / Self::STEPS).max(1); + let num_of_steps = (high - low) / step_size; + for s in 0..num_of_steps { + // This is the value we will be testing for component `name` + let component_value = step_size * s; + + // Select the mid value for all the other components. + let c: Vec<(BenchmarkParameter, u32)> = components.iter() + .map(|(n, l, h)| + (*n, if n == name { component_value } else { (h - l) / 2 + l }) + ).collect(); + + for r in 0..Self::REPEATS { + sp_std::if_std!{ + println!("STEP {:?} REPEAT {:?}", s, r); + } + let (call, caller) = benchmarking::set_identity::instance::(&c); + sp_io::benchmarking::commit_db(); + let start = sp_io::benchmarking::current_time(); + assert_eq!(call.dispatch(frame_system::RawOrigin::Signed(caller).into()), Ok(())); + let finish = sp_io::benchmarking::current_time(); + let elapsed = finish - start; + sp_io::benchmarking::wipe_db(); + results.push((c.clone(), elapsed)); + } } - let (call, caller) = benchmarking::set_identity::instance::(¶meters); - let start = sp_io::benchmarking::current_time(); - assert_eq!(call.dispatch(frame_system::RawOrigin::Signed(caller).into()), Ok(())); - let finish = sp_io::benchmarking::current_time(); - results.push(finish - start); - benchmarking::set_identity::clean::(); } - return results; } } @@ -898,9 +921,7 @@ impl Benchmarking for Module { sp_api::decl_runtime_apis! { pub trait IdentityBenchmarks { - fn run_benchmark(parameters: Vec<(BenchmarkParameter, u32)>, repeat: u32) -> Vec; - - fn get_components() -> Vec<(BenchmarkParameter, u32, u32)>; + fn run_benchmarks() -> Vec; } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 41ff26d02ace1..a9e9696df690a 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -686,7 +686,7 @@ pub enum BenchmarkParameter { /// Results from running benchmarks on a FRAME pallet. /// Contains duration of the function call in nanoseconds after executing the same function multiple times. -pub type BenchmarkResult = u128; +pub type BenchmarkResults = (Vec<(BenchmarkParameter, u32)>, u128); #[cfg(test)] mod tests { diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 6f658e05ea1f1..9328b6143cb10 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1285,9 +1285,12 @@ pub trait BlockIdTo { } /// The module benchmarking trait. -pub trait Benchmarking { +pub trait Benchmarking { + const STEPS: u32; + const REPEATS: u32; + /// Run the benchmarks for this module. - fn run_benchmark(parameters: Vec<(T, u32)>, repeat: u32) -> Vec; + fn run_benchmarks() -> Vec; } #[cfg(test)] From 5ee888f90664a7bb884dcb296b8f40ed01b81521 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 4 Feb 2020 14:57:03 +0100 Subject: [PATCH 27/50] Wipe resets to genesis --- client/db/src/bench.rs | 92 ++++++++++++++----------- primitives/state-machine/src/backend.rs | 4 +- primitives/state-machine/src/ext.rs | 7 +- 3 files changed, 58 insertions(+), 45 deletions(-) diff --git a/client/db/src/bench.rs b/client/db/src/bench.rs index 450a04c462af5..446b4a6375e08 100644 --- a/client/db/src/bench.rs +++ b/client/db/src/bench.rs @@ -19,9 +19,10 @@ use std::sync::Arc; use std::path::PathBuf; use std::io; +use std::cell::{Cell, RefCell}; use rand::Rng; -use hash_db::Prefix; +use hash_db::{Prefix, Hasher}; use sp_trie::{MemoryDB, prefixed_key}; use sp_core::storage::ChildInfo; use sp_runtime::traits::{Block as BlockT, HasherFor}; @@ -61,10 +62,11 @@ impl sc_state_db::NodeDb for StorageDb { /// State that manages the backend database reference. Allows runtime to control the database. pub struct BenchmarkingState { - state: Option>, - db: Option>, path: PathBuf, - root: B::Hash, + root: Cell, + state: RefCell>>, + db: Cell>>, + genesis: as StateBackend>>::Transaction, } impl BenchmarkingState { @@ -80,10 +82,11 @@ impl BenchmarkingState { std::fs::create_dir(&path).map_err(|_| String::from("Error creating temp dir"))?; let mut state = BenchmarkingState { - state: None, - db: None, + state: RefCell::new(None), + db: Cell::new(None), path, - root, + root: Cell::new(root), + genesis: Default::default(), }; state.reopen()?; @@ -91,17 +94,18 @@ impl BenchmarkingState { storage_key, child_content.data.into_iter().map(|(k, v)| (k, Some(v))), child_content.child_info), ); - let (root, transaction) = state.state.as_ref().unwrap().full_storage_root( + let (root, transaction) = state.state.borrow_mut().as_mut().unwrap().full_storage_root( genesis.top.into_iter().map(|(k, v)| (k, Some(v))), child_delta, ); + state.genesis = transaction.clone(); state.commit(root, transaction)?; Ok(state) } - fn reopen(&mut self) -> Result<(), String> { - self.db = None; - self.state = None; + fn reopen(&self) -> Result<(), String> { + *self.state.borrow_mut() = None; + self.db.set(None); let config = DatabaseSettings { state_cache_size: 0, state_cache_child_ratio: None, @@ -111,14 +115,20 @@ impl BenchmarkingState { let db = crate::utils::open_database::(&config, DatabaseType::Full) .map_err(|e| format!("Error opening dadabase: {:?}", e))?; - self.db = Some(db.clone()); - self.state = Some(DbState::::new(Arc::new(StorageDb:: { db, _block: Default::default() }), self.root)); + self.db.set(Some(db.clone())); + let storage_db = Arc::new(StorageDb:: { db, _block: Default::default() }); + *self.state.borrow_mut() = Some(DbState::::new(storage_db, self.root.get())); Ok(()) } - fn kill(&mut self) -> Result<(), String> { - self.db = None; - self.state = None; + fn kill(&self) -> Result<(), String> { + self.db.set(None); + *self.state.borrow_mut() = None; + let mut root = B::Hash::default(); + let mut mdb = MemoryDB::>::default(); + sp_state_machine::TrieDBMut::>::new(&mut mdb, &mut root); + self.root.set(root); + std::fs::remove_dir_all(&self.path).map_err(|_| "Error removing database dir".into()) } } @@ -139,11 +149,11 @@ impl StateBackend> for BenchmarkingState { type TrieBackendStorage = as StateBackend>>::TrieBackendStorage; fn storage(&self, key: &[u8]) -> Result>, Self::Error> { - self.state.as_ref().ok_or_else(state_err)?.storage(key) + self.state.borrow().as_ref().ok_or_else(state_err)?.storage(key) } fn storage_hash(&self, key: &[u8]) -> Result, Self::Error> { - self.state.as_ref().ok_or_else(state_err)?.storage_hash(key) + self.state.borrow().as_ref().ok_or_else(state_err)?.storage_hash(key) } fn child_storage( @@ -152,11 +162,11 @@ impl StateBackend> for BenchmarkingState { child_info: ChildInfo, key: &[u8], ) -> Result>, Self::Error> { - self.state.as_ref().ok_or_else(state_err)?.child_storage(storage_key, child_info, key) + self.state.borrow().as_ref().ok_or_else(state_err)?.child_storage(storage_key, child_info, key) } fn exists_storage(&self, key: &[u8]) -> Result { - self.state.as_ref().ok_or_else(state_err)?.exists_storage(key) + self.state.borrow().as_ref().ok_or_else(state_err)?.exists_storage(key) } fn exists_child_storage( @@ -165,11 +175,11 @@ impl StateBackend> for BenchmarkingState { child_info: ChildInfo, key: &[u8], ) -> Result { - self.state.as_ref().ok_or_else(state_err)?.exists_child_storage(storage_key, child_info, key) + self.state.borrow().as_ref().ok_or_else(state_err)?.exists_child_storage(storage_key, child_info, key) } fn next_storage_key(&self, key: &[u8]) -> Result>, Self::Error> { - self.state.as_ref().ok_or_else(state_err)?.next_storage_key(key) + self.state.borrow().as_ref().ok_or_else(state_err)?.next_storage_key(key) } fn next_child_storage_key( @@ -178,17 +188,17 @@ impl StateBackend> for BenchmarkingState { child_info: ChildInfo, key: &[u8], ) -> Result>, Self::Error> { - self.state.as_ref().ok_or_else(state_err)?.next_child_storage_key(storage_key, child_info, key) + self.state.borrow().as_ref().ok_or_else(state_err)?.next_child_storage_key(storage_key, child_info, key) } fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { - if let Some(state) = self.state.as_ref() { + if let Some(ref state) = *self.state.borrow() { state.for_keys_with_prefix(prefix, f) } } fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { - if let Some(state) = self.state.as_ref() { + if let Some(ref state) = *self.state.borrow() { state.for_key_values_with_prefix(prefix, f) } } @@ -199,7 +209,7 @@ impl StateBackend> for BenchmarkingState { child_info: ChildInfo, f: F, ) { - if let Some(state) = self.state.as_ref() { + if let Some(ref state) = *self.state.borrow() { state.for_keys_in_child_storage(storage_key, child_info, f) } } @@ -211,7 +221,7 @@ impl StateBackend> for BenchmarkingState { prefix: &[u8], f: F, ) { - if let Some(state) = self.state.as_ref() { + if let Some(ref state) = *self.state.borrow() { state.for_child_keys_with_prefix(storage_key, child_info, prefix, f) } } @@ -220,7 +230,7 @@ impl StateBackend> for BenchmarkingState { where I: IntoIterator, Option>)> { - self.state.as_ref().map_or(Default::default(), |s| s.storage_root(delta)) + self.state.borrow().as_ref().map_or(Default::default(), |s| s.storage_root(delta)) } fn child_storage_root( @@ -232,15 +242,15 @@ impl StateBackend> for BenchmarkingState { where I: IntoIterator, Option>)>, { - self.state.as_ref().map_or(Default::default(), |s| s.child_storage_root(storage_key, child_info, delta)) + self.state.borrow().as_ref().map_or(Default::default(), |s| s.child_storage_root(storage_key, child_info, delta)) } fn pairs(&self) -> Vec<(Vec, Vec)> { - self.state.as_ref().map_or(Default::default(), |s| s.pairs()) + self.state.borrow().as_ref().map_or(Default::default(), |s| s.pairs()) } fn keys(&self, prefix: &[u8]) -> Vec> { - self.state.as_ref().map_or(Default::default(), |s| s.keys(prefix)) + self.state.borrow().as_ref().map_or(Default::default(), |s| s.keys(prefix)) } fn child_keys( @@ -249,17 +259,17 @@ impl StateBackend> for BenchmarkingState { child_info: ChildInfo, prefix: &[u8], ) -> Vec> { - self.state.as_ref().map_or(Default::default(), |s| s.child_keys(storage_key, child_info, prefix)) + self.state.borrow().as_ref().map_or(Default::default(), |s| s.child_keys(storage_key, child_info, prefix)) } fn as_trie_backend(&mut self) -> Option<&sp_state_machine::TrieBackend>> { - self.state.as_mut().map_or(None, |s| s.as_trie_backend()) + None } - fn commit(&mut self, storage_root: B::Hash, mut transaction: Self::Transaction) -> Result<(), Self::Error> { - if let Some(db) = self.db.as_ref() { + fn commit(&self, storage_root: as Hasher>::Out, mut transaction: Self::Transaction) -> Result<(), Self::Error> { + if let Some(db) = self.db.take() { let mut db_transaction = DBTransaction::new(); for (key, (val, rc)) in transaction.drain() { @@ -270,16 +280,18 @@ impl StateBackend> for BenchmarkingState { } } db.write(db_transaction).map_err(|_| String::from("Error committing transaction"))?; - self.root = storage_root; - self.reopen() + self.root.set(storage_root); } else { - Err("Trying to commit to a closed db".into()) + return Err("Trying to commit to a closed db".into()) } + self.reopen() } - fn wipe(&mut self) -> Result<(), Self::Error> { + fn wipe(&self) -> Result<(), Self::Error> { self.kill()?; - self.reopen() + self.reopen()?; + self.commit(self.root.get(), self.genesis.clone())?; + Ok(()) } } diff --git a/primitives/state-machine/src/backend.rs b/primitives/state-machine/src/backend.rs index ff412605619aa..396ef6575af07 100644 --- a/primitives/state-machine/src/backend.rs +++ b/primitives/state-machine/src/backend.rs @@ -215,12 +215,12 @@ pub trait Backend: std::fmt::Debug { } /// Wipe the state database. - fn wipe(&mut self) -> Result<(), Self::Error> { + fn wipe(&self) -> Result<(), Self::Error> { unimplemented!() } /// Commit given transaction to storage. - fn commit(&mut self, _storage_root: H::Out, _transaction: Self::Transaction) -> Result<(), Self::Error> { + fn commit(&self, _storage_root: H::Out, _transaction: Self::Transaction) -> Result<(), Self::Error> { unimplemented!() } } diff --git a/primitives/state-machine/src/ext.rs b/primitives/state-machine/src/ext.rs index ec5ec3ce987f3..c2edb97170d71 100644 --- a/primitives/state-machine/src/ext.rs +++ b/primitives/state-machine/src/ext.rs @@ -584,6 +584,7 @@ where } fn wipe(&mut self) { + self.overlay.discard_prospective(); self.overlay.drain_storage_changes(&self.backend, None, Default::default(), self.storage_transaction_cache) .expect(EXT_NOT_ALLOWED_TO_FAIL); self.storage_transaction_cache.reset(); @@ -592,11 +593,11 @@ where fn commit(&mut self) { self.overlay.commit_prospective(); - self.overlay.drain_storage_changes(&self.backend, None, Default::default(), self.storage_transaction_cache) + let changes = self.overlay.drain_storage_changes(&self.backend, None, Default::default(), self.storage_transaction_cache) .expect(EXT_NOT_ALLOWED_TO_FAIL); self.backend.commit( - self.storage_transaction_cache.transaction_storage_root.take().expect(EXT_NOT_ALLOWED_TO_FAIL), - self.storage_transaction_cache.transaction.take().expect(EXT_NOT_ALLOWED_TO_FAIL), + changes.transaction_storage_root, + changes.transaction, ).expect(EXT_NOT_ALLOWED_TO_FAIL); self.storage_transaction_cache.reset(); } From d73ca25c22e586f1aeeb1cd7c89f3ea7cd890f21 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 5 Feb 2020 11:09:48 +0100 Subject: [PATCH 28/50] Speedup benchmarks --- client/db/src/bench.rs | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/client/db/src/bench.rs b/client/db/src/bench.rs index 446b4a6375e08..592e8623b4fad 100644 --- a/client/db/src/bench.rs +++ b/client/db/src/bench.rs @@ -18,7 +18,6 @@ use std::sync::Arc; use std::path::PathBuf; -use std::io; use std::cell::{Cell, RefCell}; use rand::Rng; @@ -28,11 +27,8 @@ use sp_core::storage::ChildInfo; use sp_runtime::traits::{Block as BlockT, HasherFor}; use sp_runtime::Storage; use sp_state_machine::{DBValue, backend::Backend as StateBackend}; -use crate::{DatabaseSettings, DatabaseSettingsSrc, columns}; -use crate::utils::DatabaseType; -//use log::{trace, debug, warn}; -pub use sc_state_db::PruningMode; use kvdb::{KeyValueDB, DBTransaction}; +use kvdb_rocksdb::{Database, DatabaseConfig}; type DbState = sp_state_machine::TrieBackend< Arc>>, HasherFor @@ -46,20 +42,11 @@ struct StorageDb { impl sp_state_machine::Storage> for StorageDb { fn get(&self, key: &Block::Hash, prefix: Prefix) -> Result, String> { let key = prefixed_key::>(key, prefix); - self.db.get(columns::STATE, &key) + self.db.get(0, &key) .map_err(|e| format!("Database backend error: {:?}", e)) } } -impl sc_state_db::NodeDb for StorageDb { - type Error = io::Error; - type Key = [u8]; - - fn get(&self, key: &[u8]) -> Result>, Self::Error> { - self.db.get(columns::STATE, key).map(|r| r.map(|v| v.to_vec())) - } -} - /// State that manages the backend database reference. Allows runtime to control the database. pub struct BenchmarkingState { path: PathBuf, @@ -106,15 +93,10 @@ impl BenchmarkingState { fn reopen(&self) -> Result<(), String> { *self.state.borrow_mut() = None; self.db.set(None); - let config = DatabaseSettings { - state_cache_size: 0, - state_cache_child_ratio: None, - pruning: PruningMode::ArchiveAll, - source: DatabaseSettingsSrc::Path { path: self.path.clone(), cache_size: None }, - }; - - let db = crate::utils::open_database::(&config, DatabaseType::Full) - .map_err(|e| format!("Error opening dadabase: {:?}", e))?; + let db_config = DatabaseConfig::with_columns(1); + let path = self.path.to_str() + .ok_or_else(|| String::from("Invalid database path"))?; + let db = Arc::new(Database::open(&db_config, &path).map_err(|e| format!("Error opening dadabase: {:?}", e))?); self.db.set(Some(db.clone())); let storage_db = Arc::new(StorageDb:: { db, _block: Default::default() }); *self.state.borrow_mut() = Some(DbState::::new(storage_db, self.root.get())); @@ -274,9 +256,9 @@ impl StateBackend> for BenchmarkingState { for (key, (val, rc)) in transaction.drain() { if rc > 0 { - db_transaction.put(columns::STATE, &key, &val); + db_transaction.put(0, &key, &val); } else if rc < 0 { - db_transaction.delete(columns::STATE, &key); + db_transaction.delete(0, &key); } } db.write(db_transaction).map_err(|_| String::from("Error committing transaction"))?; From 879826ca06312ea1f8731c7c428ec8aac93bcced Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 5 Feb 2020 15:12:33 +0100 Subject: [PATCH 29/50] Use enum to select extrinsic within pallet --- bin/node/runtime/src/lib.rs | 2 +- client/cli/src/params.rs | 6 +- frame/identity/src/benchmarking.rs | 148 +++++++++++++++++++++++++---- frame/identity/src/lib.rs | 54 +---------- 4 files changed, 138 insertions(+), 72 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 7269345254e09..a29d6b1c5f578 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -807,7 +807,7 @@ impl_runtime_apis! { } } - impl pallet_identity::IdentityBenchmarks for Runtime { + impl pallet_identity::benchmarking::IdentityBenchmarks for Runtime { fn run_benchmarks() -> Vec { Identity::run_benchmarks() } diff --git a/client/cli/src/params.rs b/client/cli/src/params.rs index 53733e461b22a..5e5f681ad7b64 100644 --- a/client/cli/src/params.rs +++ b/client/cli/src/params.rs @@ -850,7 +850,11 @@ pub struct PurgeChainCmd { pub struct BenchmarkCmd { /// Select a FRAME pallet to benchmark. #[structopt(short, long)] - pub pallet: Option, + pub pallet: String, + + /// Select a FRAME pallet to benchmark. + #[structopt(short, long)] + pub extrinsic: String, #[allow(missing_docs)] #[structopt(flatten)] diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index e560a1d0fa730..5aafa8c7a3ad4 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -20,7 +20,8 @@ use super::*; use frame_system::RawOrigin; use sp_io::hashing::blake2_256; -use sp_runtime::traits::Bounded; +use sp_runtime::{BenchmarkResults, BenchmarkParameter}; +use sp_runtime::traits::{Bounded, Benchmarking}; use crate::Module as Identity; @@ -29,10 +30,19 @@ pub fn account(index: u32) -> T::AccountId { T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() } -pub mod set_identity { - use super::*; +trait BenchmarkingSetup where + T: Trait, +{ + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)>; - pub fn components() -> Vec<(BenchmarkParameter, u32, u32)> { + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (crate::Call, RawOrigin); + +} + +struct SetIdentity; +impl BenchmarkingSetup for SetIdentity { + + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { vec![ // Registrar Count (BenchmarkParameter::R, 1, 16), @@ -48,23 +58,21 @@ pub mod set_identity { /// /// Sets up state randomly and returns a randomly generated `set_identity` with sensible (fixed) /// values for all complexity components except those mentioned in the identity. - pub fn instance(components: &[(BenchmarkParameter, u32)]) -> (crate::Call, T::AccountId) + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (crate::Call, RawOrigin) { // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap(); for i in 0..r.1 { - sp_std::if_std!{ - println!("Components {:?} Index {:?}", components, i); - } let _ = T::Currency::make_free_balance_be(&account::(i), BalanceOf::::max_value()); assert_eq!(Identity::::add_registrar(RawOrigin::Root.into(), account::(i)), Ok(())); - sp_std::if_std!{ - println!("# Registrars {:?}", Registrars::::get().len()); - } assert_eq!(Identity::::set_fee(RawOrigin::Signed(account::(i)).into(), i.into(), 10.into()), Ok(())); let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); assert_eq!(Identity::::set_fields(RawOrigin::Signed(account::(i)).into(), i.into(), fields), Ok(())); } + + sp_std::if_std!{ + println!("# Registrars {:?}", Registrars::::get().len()); + } // Create identity info with x additional fields let x = components.iter().find(|&c| c.0 == BenchmarkParameter::X).unwrap(); @@ -86,13 +94,117 @@ pub mod set_identity { let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); // Return the `set_identity` call - (crate::Call::::set_identity(info), caller) + (crate::Call::::set_identity(info), RawOrigin::Signed(caller)) } +} - pub fn clean() { - IdentityOf::::remove_all(); - SuperOf::::remove_all(); - SubsOf::::remove_all(); - Registrars::::kill(); +struct AddRegistrar; +impl BenchmarkingSetup for AddRegistrar { + + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { + vec![ + // Registrar Count + (BenchmarkParameter::R, 1, 16), + ] } -} \ No newline at end of file + + /// Assumes externalities are set up with a mutable state. + /// + /// Panics if `component_name` isn't from `set_identity::components` or `component_value` is out of + /// the range of `set_identity::components`. + /// + /// Sets up state randomly and returns a randomly generated `set_identity` with sensible (fixed) + /// values for all complexity components except those mentioned in the identity. + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (crate::Call, RawOrigin) + { + // Add r registrars + let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap(); + for i in 0..r.1 { + sp_std::if_std!{ + println!("Components {:?} Index {:?}", components, i); + } + let _ = T::Currency::make_free_balance_be(&account::(i), BalanceOf::::max_value()); + assert_eq!(Identity::::add_registrar(RawOrigin::Root.into(), account::(i)), Ok(())); + sp_std::if_std!{ + println!("# Registrars {:?}", Registrars::::get().len()); + } + } + // Return the `add_registrar` r + 1 call + (crate::Call::::add_registrar(account::(r.1 + 1)), RawOrigin::Root) + } +} + +enum SelectedBenchmark { + SetIdentity, + AddRegistrar, +} + +impl BenchmarkingSetup for SelectedBenchmark { + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> + { + match self { + Self::SetIdentity => >::components(&SetIdentity), + Self::AddRegistrar => >::components(&AddRegistrar), + } + } + + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (crate::Call, RawOrigin) + { + match self { + Self::SetIdentity => >::instance(&SetIdentity, components), + Self::AddRegistrar => >::instance(&AddRegistrar, components), + } + } +} + +impl Benchmarking for Module { + const STEPS: u32 = 10; + const REPEATS: u32 = 100; + + fn run_benchmarks() -> Vec { + + let selected_benchmark = SelectedBenchmark::SetIdentity; + // first one is set_identity. + let components = >::components(&selected_benchmark); + // results go here + let mut results: Vec = Vec::new(); + // Select the component we will be benchmarking. Each component will be benchmarked. + for (name, low, high) in components.iter() { + // Create up to `STEPS` steps for that component between high and low. + let step_size = ((high - low) / Self::STEPS).max(1); + let num_of_steps = (high - low) / step_size; + for s in *low..num_of_steps { + // This is the value we will be testing for component `name` + let component_value = step_size * s; + + // Select the mid value for all the other components. + let c: Vec<(BenchmarkParameter, u32)> = components.iter() + .map(|(n, l, h)| + (*n, if n == name { component_value } else { (h - l) / 2 + l }) + ).collect(); + + for r in 0..Self::REPEATS { + sp_std::if_std!{ + println!("STEP {:?} REPEAT {:?}", s, r); + } + let (call, caller) = >::instance(&selected_benchmark, &c); + sp_io::benchmarking::commit_db(); + let start = sp_io::benchmarking::current_time(); + assert_eq!(call.dispatch(caller.into()), Ok(())); + let finish = sp_io::benchmarking::current_time(); + let elapsed = finish - start; + sp_io::benchmarking::wipe_db(); + results.push((c.clone(), elapsed)); + } + } + } + return results; + } +} + +sp_api::decl_runtime_apis! { + pub trait IdentityBenchmarks + { + fn run_benchmarks() -> Vec; + } +} diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 87fc153118812..9c4a9d0cfeb37 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -69,8 +69,8 @@ use sp_std::prelude::*; use sp_std::{fmt::Debug, ops::Add, iter::once}; use enumflags2::BitFlags; use codec::{Encode, Decode}; -use sp_runtime::{DispatchResult, RuntimeDebug, BenchmarkResults, BenchmarkParameter}; -use sp_runtime::traits::{StaticLookup, EnsureOrigin, Zero, AppendZerosInput, Dispatchable, Benchmarking}; +use sp_runtime::{DispatchResult, RuntimeDebug}; +use sp_runtime::traits::{StaticLookup, EnsureOrigin, Zero, AppendZerosInput, Dispatchable}; use frame_support::{ decl_module, decl_event, decl_storage, ensure, decl_error, traits::{Currency, ReservableCurrency, OnUnbalanced, Get}, @@ -875,56 +875,6 @@ decl_module! { } } -impl Benchmarking for Module { - const STEPS: u32 = 10; - const REPEATS: u32 = 100; - - fn run_benchmarks() -> Vec { - // first one is set_identity. - let components = benchmarking::set_identity::components(); - // results go here - let mut results: Vec = Vec::new(); - // Select the component we will be benchmarking. Each component will be benchmarked. - for (name, low, high) in components.iter() { - // Create up to `STEPS` steps for that component between high and low. - let step_size = ((high - low) / Self::STEPS).max(1); - let num_of_steps = (high - low) / step_size; - for s in 0..num_of_steps { - // This is the value we will be testing for component `name` - let component_value = step_size * s; - - // Select the mid value for all the other components. - let c: Vec<(BenchmarkParameter, u32)> = components.iter() - .map(|(n, l, h)| - (*n, if n == name { component_value } else { (h - l) / 2 + l }) - ).collect(); - - for r in 0..Self::REPEATS { - sp_std::if_std!{ - println!("STEP {:?} REPEAT {:?}", s, r); - } - let (call, caller) = benchmarking::set_identity::instance::(&c); - sp_io::benchmarking::commit_db(); - let start = sp_io::benchmarking::current_time(); - assert_eq!(call.dispatch(frame_system::RawOrigin::Signed(caller).into()), Ok(())); - let finish = sp_io::benchmarking::current_time(); - let elapsed = finish - start; - sp_io::benchmarking::wipe_db(); - results.push((c.clone(), elapsed)); - } - } - } - return results; - } -} - -sp_api::decl_runtime_apis! { - pub trait IdentityBenchmarks - { - fn run_benchmarks() -> Vec; - } -} - #[cfg(test)] mod tests { use super::*; From e04134771dde6fb4fa67417d45d753d2340f0e20 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 5 Feb 2020 16:20:14 +0100 Subject: [PATCH 30/50] CLI controls which module and extrinsic to call --- bin/node/runtime/src/lib.rs | 4 ++-- client/cli/src/params.rs | 4 +++- client/service/src/chain_ops.rs | 6 ++++-- frame/identity/src/benchmarking.rs | 15 ++++++++++----- primitives/runtime/src/traits.rs | 2 +- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index a29d6b1c5f578..caa7b1a998e3c 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -808,8 +808,8 @@ impl_runtime_apis! { } impl pallet_identity::benchmarking::IdentityBenchmarks for Runtime { - fn run_benchmarks() -> Vec { - Identity::run_benchmarks() + fn run_benchmarks(input: Vec) -> Vec { + Identity::run_benchmarks(input) } } } diff --git a/client/cli/src/params.rs b/client/cli/src/params.rs index 5e5f681ad7b64..68917d7fdc205 100644 --- a/client/cli/src/params.rs +++ b/client/cli/src/params.rs @@ -1249,7 +1249,9 @@ impl BenchmarkCmd { let spec = config.chain_spec.expect("chain_spec is always Some"); let execution_strategy = self.execution.unwrap_or(ExecutionStrategy::Native).into(); let wasm_method = self.wasm_method.into(); - sc_service::chain_ops::benchmark_runtime::(spec, execution_strategy, wasm_method)?; + let pallet = self.pallet; + let extrinsic = self.extrinsic; + sc_service::chain_ops::benchmark_runtime::(spec, execution_strategy, wasm_method, pallet, extrinsic)?; Ok(()) } } diff --git a/client/service/src/chain_ops.rs b/client/service/src/chain_ops.rs index 0cb0bb68848cc..ef527478b1c31 100644 --- a/client/service/src/chain_ops.rs +++ b/client/service/src/chain_ops.rs @@ -51,6 +51,8 @@ pub fn benchmark_runtime ( spec: ChainSpec, strategy: ExecutionStrategy, wasm_method: WasmExecutionMethod, + pallet: String, + extrinsic: String, ) -> error::Result<()> where TBl: BlockT, TExecDisp: NativeExecutionDispatch + 'static, @@ -69,8 +71,8 @@ pub fn benchmark_runtime ( None, &mut changes, &executor, - "IdentityBenchmarks_run_benchmarks", - &[], + &(pallet + "Benchmarks_run_benchmarks"), + &extrinsic.encode(), Default::default(), ).execute(strategy).map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?; println!("{:?}", result); diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 5aafa8c7a3ad4..5f51c7e42212b 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -161,9 +161,14 @@ impl Benchmarking for Module { const STEPS: u32 = 10; const REPEATS: u32 = 100; - fn run_benchmarks() -> Vec { + fn run_benchmarks(input: Vec) -> Vec { + + let selected_benchmark = match input.as_slice() { + b"set_identity" => SelectedBenchmark::SetIdentity, + b"add_registrar" => SelectedBenchmark::AddRegistrar, + _ => return Vec::new(), + }; - let selected_benchmark = SelectedBenchmark::SetIdentity; // first one is set_identity. let components = >::components(&selected_benchmark); // results go here @@ -173,9 +178,9 @@ impl Benchmarking for Module { // Create up to `STEPS` steps for that component between high and low. let step_size = ((high - low) / Self::STEPS).max(1); let num_of_steps = (high - low) / step_size; - for s in *low..num_of_steps { + for s in 0..num_of_steps { // This is the value we will be testing for component `name` - let component_value = step_size * s; + let component_value = low + step_size * s; // Select the mid value for all the other components. let c: Vec<(BenchmarkParameter, u32)> = components.iter() @@ -205,6 +210,6 @@ impl Benchmarking for Module { sp_api::decl_runtime_apis! { pub trait IdentityBenchmarks { - fn run_benchmarks() -> Vec; + fn run_benchmarks(input: Vec) -> Vec; } } diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 0599a6f2f42e5..f7b5842b47982 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1324,7 +1324,7 @@ pub trait Benchmarking { const REPEATS: u32; /// Run the benchmarks for this module. - fn run_benchmarks() -> Vec; + fn run_benchmarks(input: Vec) -> Vec; } #[cfg(test)] From 115290b73df534f8fb38547b162d95c0c7334832 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 5 Feb 2020 17:31:12 +0100 Subject: [PATCH 31/50] Select a pallet with cli --- bin/node/runtime/src/lib.rs | 18 ++++++++++++++---- client/service/src/chain_ops.rs | 4 ++-- frame/identity/src/benchmarking.rs | 9 +-------- primitives/runtime/src/traits.rs | 2 +- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index caa7b1a998e3c..7f3c34e2f5c0f 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -31,7 +31,7 @@ use node_primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index use sp_api::impl_runtime_apis; use sp_runtime::{ Permill, Perbill, Percent, ApplyExtrinsicResult, impl_opaque_keys, generic, create_runtime_str, - BenchmarkResults, BenchmarkParameter, + BenchmarkResults, }; use sp_runtime::curve::PiecewiseLinear; use sp_runtime::transaction_validity::TransactionValidity; @@ -807,13 +807,23 @@ impl_runtime_apis! { } } - impl pallet_identity::benchmarking::IdentityBenchmarks for Runtime { - fn run_benchmarks(input: Vec) -> Vec { - Identity::run_benchmarks(input) + impl crate::Benchmark for Runtime { + fn run_benchmark(module: Vec, extrinsic: Vec) -> Vec { + match module.as_slice() { + b"pallet-identity" | b"identity" => Identity::run_benchmark(extrinsic), + _ => return Vec::new(), + } } } } +sp_api::decl_runtime_apis! { + pub trait Benchmark + { + fn run_benchmark(module: Vec, extrinsic: Vec) -> Vec; + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/client/service/src/chain_ops.rs b/client/service/src/chain_ops.rs index ef527478b1c31..66645700aa412 100644 --- a/client/service/src/chain_ops.rs +++ b/client/service/src/chain_ops.rs @@ -71,8 +71,8 @@ pub fn benchmark_runtime ( None, &mut changes, &executor, - &(pallet + "Benchmarks_run_benchmarks"), - &extrinsic.encode(), + "Benchmark_run_benchmark", + &(pallet, extrinsic).encode(), Default::default(), ).execute(strategy).map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?; println!("{:?}", result); diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 5f51c7e42212b..8ce7369cb4460 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -161,7 +161,7 @@ impl Benchmarking for Module { const STEPS: u32 = 10; const REPEATS: u32 = 100; - fn run_benchmarks(input: Vec) -> Vec { + fn run_benchmark(input: Vec) -> Vec { let selected_benchmark = match input.as_slice() { b"set_identity" => SelectedBenchmark::SetIdentity, @@ -206,10 +206,3 @@ impl Benchmarking for Module { return results; } } - -sp_api::decl_runtime_apis! { - pub trait IdentityBenchmarks - { - fn run_benchmarks(input: Vec) -> Vec; - } -} diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index f7b5842b47982..054c411293b17 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1324,7 +1324,7 @@ pub trait Benchmarking { const REPEATS: u32; /// Run the benchmarks for this module. - fn run_benchmarks(input: Vec) -> Vec; + fn run_benchmark(input: Vec) -> Vec; } #[cfg(test)] From 283860c5ba0b45dae9187c33463eafce52780b9b Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Wed, 5 Feb 2020 19:09:34 +0100 Subject: [PATCH 32/50] Add steps and repeats to cli --- bin/node/runtime/src/lib.rs | 6 +++--- client/cli/src/params.rs | 14 ++++++++++++-- client/service/src/chain_ops.rs | 11 ++++++++--- frame/identity/src/benchmarking.rs | 22 +++++++++------------- primitives/runtime/src/traits.rs | 5 +---- 5 files changed, 33 insertions(+), 25 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 7f3c34e2f5c0f..a0289f94c317c 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -808,9 +808,9 @@ impl_runtime_apis! { } impl crate::Benchmark for Runtime { - fn run_benchmark(module: Vec, extrinsic: Vec) -> Vec { + fn dispatch_benchmark(module: Vec, extrinsic: Vec, steps: u32, repeat: u32) -> Vec { match module.as_slice() { - b"pallet-identity" | b"identity" => Identity::run_benchmark(extrinsic), + b"pallet-identity" | b"identity" => Identity::run_benchmark(extrinsic, steps, repeat), _ => return Vec::new(), } } @@ -820,7 +820,7 @@ impl_runtime_apis! { sp_api::decl_runtime_apis! { pub trait Benchmark { - fn run_benchmark(module: Vec, extrinsic: Vec) -> Vec; + fn dispatch_benchmark(module: Vec, extrinsic: Vec, steps: u32, repeat: u32) -> Vec; } } diff --git a/client/cli/src/params.rs b/client/cli/src/params.rs index 68917d7fdc205..f0902f289608c 100644 --- a/client/cli/src/params.rs +++ b/client/cli/src/params.rs @@ -852,10 +852,18 @@ pub struct BenchmarkCmd { #[structopt(short, long)] pub pallet: String, - /// Select a FRAME pallet to benchmark. + /// Select an extrinsic to benchmark. #[structopt(short, long)] pub extrinsic: String, + /// Select how many steps of the parameters should we test. + #[structopt(short, long, default_value = "1")] + pub steps: u32, + + /// Select how many repetitions of this benchmark should run. + #[structopt(short, long, default_value = "1")] + pub repeat: u32, + #[allow(missing_docs)] #[structopt(flatten)] pub shared_params: SharedParams, @@ -1251,7 +1259,9 @@ impl BenchmarkCmd { let wasm_method = self.wasm_method.into(); let pallet = self.pallet; let extrinsic = self.extrinsic; - sc_service::chain_ops::benchmark_runtime::(spec, execution_strategy, wasm_method, pallet, extrinsic)?; + let steps = self.steps; + let repeat = self.repeat; + sc_service::chain_ops::benchmark_runtime::(spec, execution_strategy, wasm_method, pallet, extrinsic, steps, repeat)?; Ok(()) } } diff --git a/client/service/src/chain_ops.rs b/client/service/src/chain_ops.rs index 66645700aa412..baf4a451c9bfc 100644 --- a/client/service/src/chain_ops.rs +++ b/client/service/src/chain_ops.rs @@ -22,7 +22,9 @@ use crate::error::Error; use sc_chain_spec::{ChainSpec, RuntimeGenesis, Extension}; use log::{warn, info}; use futures::{future, prelude::*}; -use sp_runtime::{BuildStorage, traits::{ +use sp_runtime::{ + BuildStorage, BenchmarkResults, + traits::{ Block as BlockT, NumberFor, One, Zero, Header, SaturatedConversion } }; @@ -53,6 +55,8 @@ pub fn benchmark_runtime ( wasm_method: WasmExecutionMethod, pallet: String, extrinsic: String, + steps: u32, + repeat: u32, ) -> error::Result<()> where TBl: BlockT, TExecDisp: NativeExecutionDispatch + 'static, @@ -71,10 +75,11 @@ pub fn benchmark_runtime ( None, &mut changes, &executor, - "Benchmark_run_benchmark", - &(pallet, extrinsic).encode(), + "Benchmark_dispatch_benchmark", + &(pallet, extrinsic, steps, repeat).encode(), Default::default(), ).execute(strategy).map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?; + let result = as Decode>::decode(&mut &result[..]); println!("{:?}", result); info!("Done."); Ok(()) diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 8ce7369cb4460..47ed7c83f915d 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -120,15 +120,14 @@ impl BenchmarkingSetup for AddRegistrar { // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap(); for i in 0..r.1 { - sp_std::if_std!{ - println!("Components {:?} Index {:?}", components, i); - } let _ = T::Currency::make_free_balance_be(&account::(i), BalanceOf::::max_value()); assert_eq!(Identity::::add_registrar(RawOrigin::Root.into(), account::(i)), Ok(())); - sp_std::if_std!{ - println!("# Registrars {:?}", Registrars::::get().len()); - } } + + sp_std::if_std!{ + println!("# Registrars {:?}", Registrars::::get().len()); + } + // Return the `add_registrar` r + 1 call (crate::Call::::add_registrar(account::(r.1 + 1)), RawOrigin::Root) } @@ -158,12 +157,9 @@ impl BenchmarkingSetup for SelectedBenchmark { } impl Benchmarking for Module { - const STEPS: u32 = 10; - const REPEATS: u32 = 100; - - fn run_benchmark(input: Vec) -> Vec { + fn run_benchmark(extrinsic: Vec, steps: u32, repeat: u32) -> Vec { - let selected_benchmark = match input.as_slice() { + let selected_benchmark = match extrinsic.as_slice() { b"set_identity" => SelectedBenchmark::SetIdentity, b"add_registrar" => SelectedBenchmark::AddRegistrar, _ => return Vec::new(), @@ -176,7 +172,7 @@ impl Benchmarking for Module { // Select the component we will be benchmarking. Each component will be benchmarked. for (name, low, high) in components.iter() { // Create up to `STEPS` steps for that component between high and low. - let step_size = ((high - low) / Self::STEPS).max(1); + let step_size = ((high - low) / steps).max(1); let num_of_steps = (high - low) / step_size; for s in 0..num_of_steps { // This is the value we will be testing for component `name` @@ -188,7 +184,7 @@ impl Benchmarking for Module { (*n, if n == name { component_value } else { (h - l) / 2 + l }) ).collect(); - for r in 0..Self::REPEATS { + for r in 0..repeat { sp_std::if_std!{ println!("STEP {:?} REPEAT {:?}", s, r); } diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 054c411293b17..17de7aa6fee7d 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1320,11 +1320,8 @@ pub trait BlockIdTo { /// The module benchmarking trait. pub trait Benchmarking { - const STEPS: u32; - const REPEATS: u32; - /// Run the benchmarks for this module. - fn run_benchmark(input: Vec) -> Vec; + fn run_benchmark(extrinsic: Vec, steps: u32, repeat: u32) -> Vec; } #[cfg(test)] From ca890f6ce713197db1cffdb4cb5b0fd6b86592bd Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Thu, 6 Feb 2020 19:06:47 +0100 Subject: [PATCH 33/50] Output as CSV format --- client/service/src/chain_ops.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/client/service/src/chain_ops.rs b/client/service/src/chain_ops.rs index baf4a451c9bfc..4fc1166dff227 100644 --- a/client/service/src/chain_ops.rs +++ b/client/service/src/chain_ops.rs @@ -79,9 +79,21 @@ pub fn benchmark_runtime ( &(pallet, extrinsic, steps, repeat).encode(), Default::default(), ).execute(strategy).map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?; - let result = as Decode>::decode(&mut &result[..]); - println!("{:?}", result); - info!("Done."); + let results = as Decode>::decode(&mut &result[..]).unwrap(); + if results.len() == 0 { + info!("No Results."); + } else { + // Print the table header + results[0].0.iter().for_each(|param| print!("{:?},", param.0)); + print!("time,\n"); + // Print the values + results.iter().for_each(|result| { + let parameters = &result.0; + parameters.iter().for_each(|param| print!("{:?},", param.1)); + print!("{:?},\n", result.1); + }); + info!("Done."); + } Ok(()) } From 1cb8529ff17fc4cb636559dc30621b3cb36f4633 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 7 Feb 2020 00:50:45 +0100 Subject: [PATCH 34/50] Introduce benchmark pallet --- Cargo.lock | 18 +++- Cargo.toml | 1 + bin/node/runtime/Cargo.toml | 1 + bin/node/runtime/src/lib.rs | 6 ++ client/service/src/chain_ops.rs | 4 +- frame/benchmark/Cargo.toml | 32 ++++++ frame/benchmark/src/benchmarking.rs | 149 ++++++++++++++++++++++++++++ frame/benchmark/src/lib.rs | 85 ++++++++++++++++ frame/identity/Cargo.toml | 2 - frame/identity/src/benchmarking.rs | 35 +++---- frame/identity/src/lib.rs | 2 +- primitives/runtime/src/traits.rs | 10 ++ 12 files changed, 320 insertions(+), 25 deletions(-) create mode 100644 frame/benchmark/Cargo.toml create mode 100644 frame/benchmark/src/benchmarking.rs create mode 100644 frame/benchmark/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index bc2848c2c9641..f00aa4e524f6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3506,6 +3506,7 @@ dependencies = [ "pallet-authorship", "pallet-babe", "pallet-balances", + "pallet-benchmark", "pallet-collective", "pallet-contracts", "pallet-contracts-primitives", @@ -3940,6 +3941,22 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-benchmark" +version = "2.0.0" +dependencies = [ + "enumflags2", + "frame-support", + "frame-system", + "pallet-balances", + "parity-scale-codec", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-collective" version = "2.0.0" @@ -4165,7 +4182,6 @@ dependencies = [ "pallet-balances", "parity-scale-codec", "serde", - "sp-api", "sp-core", "sp-io", "sp-runtime", diff --git a/Cargo.toml b/Cargo.toml index 47e3fe3f0efce..524170362a6ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,6 +60,7 @@ members = [ "frame/authorship", "frame/babe", "frame/balances", + "frame/benchmark", "frame/collective", "frame/contracts", "frame/contracts/rpc", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 3f8e8b6731477..937ff393365d5 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -40,6 +40,7 @@ pallet-authority-discovery = { version = "2.0.0", default-features = false, path pallet-authorship = { version = "2.0.0", default-features = false, path = "../../../frame/authorship" } pallet-babe = { version = "2.0.0", default-features = false, path = "../../../frame/babe" } pallet-balances = { version = "2.0.0", default-features = false, path = "../../../frame/balances" } +pallet-benchmark = { version = "2.0.0", default-features = false, path = "../../../frame/benchmark" } pallet-collective = { version = "2.0.0", default-features = false, path = "../../../frame/collective" } pallet-contracts = { version = "2.0.0", default-features = false, path = "../../../frame/contracts" } pallet-contracts-primitives = { version = "2.0.0", default-features = false, path = "../../../frame/contracts/common/" } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 29d4e243ef767..b1cf4de7fa160 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -504,6 +504,10 @@ impl pallet_identity::Trait for Runtime { type ForceOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; } +impl pallet_benchmark::Trait for Runtime { + type Event = Event; +} + impl frame_system::offchain::CreateTransaction for Runtime { type Public = ::Signer; type Signature = Signature; @@ -627,6 +631,7 @@ construct_runtime!( Society: pallet_society::{Module, Call, Storage, Event, Config}, Recovery: pallet_recovery::{Module, Call, Storage, Event}, Vesting: pallet_vesting::{Module, Call, Storage, Event, Config}, + Bench: pallet_benchmark::{Module, Call, Storage, Event}, } ); @@ -811,6 +816,7 @@ impl_runtime_apis! { fn dispatch_benchmark(module: Vec, extrinsic: Vec, steps: u32, repeat: u32) -> Vec { match module.as_slice() { b"pallet-identity" | b"identity" => Identity::run_benchmark(extrinsic, steps, repeat), + b"pallet-benchmark" | b"benchmark" => Bench::run_benchmark(extrinsic, steps, repeat), _ => return Vec::new(), } } diff --git a/client/service/src/chain_ops.rs b/client/service/src/chain_ops.rs index 4fc1166dff227..65bd63b0e0df8 100644 --- a/client/service/src/chain_ops.rs +++ b/client/service/src/chain_ops.rs @@ -76,13 +76,15 @@ pub fn benchmark_runtime ( &mut changes, &executor, "Benchmark_dispatch_benchmark", - &(pallet, extrinsic, steps, repeat).encode(), + &(&pallet, &extrinsic, steps, repeat).encode(), Default::default(), ).execute(strategy).map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?; let results = as Decode>::decode(&mut &result[..]).unwrap(); if results.len() == 0 { info!("No Results."); } else { + // Print benchmark metadata + println!("Pallet: {:?}, Extrinsic: {:?}, Steps: {:?}, Repeat: {:?}", pallet, extrinsic, steps, repeat); // Print the table header results[0].0.iter().for_each(|param| print!("{:?},", param.0)); print!("time,\n"); diff --git a/frame/benchmark/Cargo.toml b/frame/benchmark/Cargo.toml new file mode 100644 index 0000000000000..2c6bbe0f3b3b0 --- /dev/null +++ b/frame/benchmark/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "pallet-benchmark" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0" + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +enumflags2 = { version = "0.6.2" } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[dev-dependencies] +sp-core = { version = "2.0.0", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0", path = "../balances" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-std/std", + "sp-io/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", +] diff --git a/frame/benchmark/src/benchmarking.rs b/frame/benchmark/src/benchmarking.rs new file mode 100644 index 0000000000000..3613fb3fb8c4d --- /dev/null +++ b/frame/benchmark/src/benchmarking.rs @@ -0,0 +1,149 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Identity pallet benchmarking. + +use super::*; + +use codec::{Encode, Decode}; +use frame_system::RawOrigin; +use sp_io::hashing::blake2_256; +use sp_runtime::{BenchmarkResults, BenchmarkParameter}; +use sp_runtime::traits::{Benchmarking, BenchmarkingSetup, Dispatchable}; +use sp_std::prelude::*; + +use crate::Module as Benchmark; + +fn account(index: u32) -> T::AccountId { + let entropy = (b"benchmark", index).using_encoded(blake2_256); + T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() +} + +// Custom implementation to handle benchmarking of calling a host function. +fn time_host(steps: u32, repeat: u32) -> Vec { + let mut results: Vec = Vec::new(); + + for _ in 0..steps { + let start = sp_io::benchmarking::current_time(); + for _ in 0..repeat { + let _ = sp_io::benchmarking::current_time(); + } + let finish = sp_io::benchmarking::current_time(); + let elapsed = finish - start; + + results.push((vec![(BenchmarkParameter::L, repeat)], elapsed)); + } + + return results; +} + +struct AddMemberList; +impl BenchmarkingSetup, RawOrigin> for AddMemberList { + + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { + vec![ + // Registrar Count + (BenchmarkParameter::M, 1, 1000), + ] + } + + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (crate::Call, RawOrigin) + { + // Add r registrars + let r = components.iter().find(|&c| c.0 == BenchmarkParameter::M).unwrap(); + for i in 0..r.1 { + let _ = Benchmark::::add_member_list(RawOrigin::Signed(account::(i)).into()); + } + + sp_std::if_std!{ + println!("# Users {:?}", MyList::::get().len()); + } + + // Return the `add_registrar` r + 1 call + (crate::Call::::add_member_list(), RawOrigin::Signed(account::(r.1 + 1))) + } +} + +enum SelectedBenchmark { + AddMemberList, +} + +impl BenchmarkingSetup, RawOrigin> for SelectedBenchmark { + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> + { + match self { + Self::AddMemberList => , RawOrigin>>::components(&AddMemberList), + } + } + + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (crate::Call, RawOrigin) + { + match self { + Self::AddMemberList => , RawOrigin>>::instance(&AddMemberList, components), + } + } +} + +impl Benchmarking for Module { + fn run_benchmark(extrinsic: Vec, steps: u32, repeat: u32) -> Vec { + + let selected_benchmark = match extrinsic.as_slice() { + b"time_host" => return benchmarking::time_host(steps, repeat), + b"add_member_list" => SelectedBenchmark::AddMemberList, + _ => return Vec::new(), + }; + + // Warm up the DB? + sp_io::benchmarking::commit_db(); + sp_io::benchmarking::wipe_db(); + + // first one is set_identity. + let components = , RawOrigin>>::components(&selected_benchmark); + // results go here + let mut results: Vec = Vec::new(); + // Select the component we will be benchmarking. Each component will be benchmarked. + for (name, low, high) in components.iter() { + // Create up to `STEPS` steps for that component between high and low. + let step_size = ((high - low) / steps).max(1); + let num_of_steps = (high - low) / step_size; + for s in 0..num_of_steps { + // This is the value we will be testing for component `name` + let component_value = low + step_size * s; + + // Select the mid value for all the other components. + let c: Vec<(BenchmarkParameter, u32)> = components.iter() + .map(|(n, l, h)| + (*n, if n == name { component_value } else { (h - l) / 2 + l }) + ).collect(); + + for r in 0..repeat { + sp_std::if_std!{ + println!("STEP {:?} REPEAT {:?}", s, r); + } + let (call, caller) = , RawOrigin>>::instance(&selected_benchmark, &c); + sp_io::benchmarking::commit_db(); + let start = sp_io::benchmarking::current_time(); + assert_eq!(call.dispatch(caller.into()), Ok(())); + let finish = sp_io::benchmarking::current_time(); + let elapsed = finish - start; + sp_io::benchmarking::wipe_db(); + results.push((c.clone(), elapsed)); + } + } + } + return results; + } +} diff --git a/frame/benchmark/src/lib.rs b/frame/benchmark/src/lib.rs new file mode 100644 index 0000000000000..79a774ac6b8b5 --- /dev/null +++ b/frame/benchmark/src/lib.rs @@ -0,0 +1,85 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +/// A runtime module template with necessary imports + +/// Feel free to remove or edit this file as needed. +/// If you change the name of this file, make sure to update its references in runtime/src/lib.rs +/// If you remove this file, you can remove those references + +/// For more guidance on Substrate modules, see the example module +/// https://github.com/paritytech/substrate/blob/master/frame/example/src/lib.rs + +use frame_support::{decl_module, decl_storage, decl_event, decl_error}; +use frame_system::{self as system, ensure_signed}; +use sp_std::prelude::Vec; + +pub mod benchmarking; + +/// The pallet's configuration trait. +pub trait Trait: system::Trait { + // Add other types and constants required to configure this pallet. + + /// The overarching event type. + type Event: From> + Into<::Event>; +} + +// This pallet's storage items. +decl_storage! { + trait Store for Module as Benchmark { + MyList: Vec; + MyMap: map hasher(blake2_256) T::AccountId => bool; + } +} + +// The pallet's events +decl_event!( + pub enum Event where AccountId = ::AccountId { + /// Just a dummy event. + /// Event `Something` is declared with a parameter of the type `u32` and `AccountId` + /// To emit this event, we call the deposit funtion, from our runtime funtions + Dummy(u32, AccountId), + } +); + +// The pallet's errors +decl_error! { + pub enum Error for Module { + /// Value was None + NoneValue, + /// Value reached maximum and cannot be incremented further + StorageOverflow, + } +} + +// The pallet's dispatchable functions. +decl_module! { + /// The module declaration. + pub struct Module for enum Call where origin: T::Origin { + // Initializing errors + // this includes information about your errors in the node's metadata. + // it is needed only if you are using errors in your pallet + type Error = Error; + + // Initializing events + // this is needed only if you are using events in your pallet + fn deposit_event() = default; + + + pub fn add_member_list(origin) { + // Check it was signed and get the signer. + let who = ensure_signed(origin)?; + + // Add user to the list. + MyList::::mutate(|x| x.push(who)); + } + + pub fn check_member_list(origin) { + // Check it was signed and get the signer. + let who = ensure_signed(origin)?; + + // Add user to the list. + MyList::::mutate(|x| x.push(who)); + } + + } +} diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index d695cea90e720..59e8f721c8dd2 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -14,7 +14,6 @@ sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/ sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } frame-support = { version = "2.0.0", default-features = false, path = "../support" } frame-system = { version = "2.0.0", default-features = false, path = "../system" } -sp-api = { version = "2.0.0", default-features = false, path = "../../primitives/api" } [dev-dependencies] sp-core = { version = "2.0.0", path = "../../primitives/core" } @@ -27,7 +26,6 @@ std = [ "codec/std", "sp-std/std", "sp-io/std", - "sp-api/std", "sp-runtime/std", "frame-support/std", "frame-system/std", diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 47ed7c83f915d..d6ea8fd324dd6 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -21,26 +21,17 @@ use super::*; use frame_system::RawOrigin; use sp_io::hashing::blake2_256; use sp_runtime::{BenchmarkResults, BenchmarkParameter}; -use sp_runtime::traits::{Bounded, Benchmarking}; +use sp_runtime::traits::{Bounded, Benchmarking, BenchmarkingSetup, Dispatchable}; use crate::Module as Identity; -pub fn account(index: u32) -> T::AccountId { +fn account(index: u32) -> T::AccountId { let entropy = (b"benchmark", index).using_encoded(blake2_256); T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() } -trait BenchmarkingSetup where - T: Trait, -{ - fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)>; - - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (crate::Call, RawOrigin); - -} - struct SetIdentity; -impl BenchmarkingSetup for SetIdentity { +impl BenchmarkingSetup, RawOrigin> for SetIdentity { fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { vec![ @@ -99,7 +90,7 @@ impl BenchmarkingSetup for SetIdentity { } struct AddRegistrar; -impl BenchmarkingSetup for AddRegistrar { +impl BenchmarkingSetup, RawOrigin> for AddRegistrar { fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { vec![ @@ -138,20 +129,20 @@ enum SelectedBenchmark { AddRegistrar, } -impl BenchmarkingSetup for SelectedBenchmark { +impl BenchmarkingSetup, RawOrigin> for SelectedBenchmark { fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { match self { - Self::SetIdentity => >::components(&SetIdentity), - Self::AddRegistrar => >::components(&AddRegistrar), + Self::SetIdentity => , RawOrigin>>::components(&SetIdentity), + Self::AddRegistrar => , RawOrigin>>::components(&AddRegistrar), } } fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (crate::Call, RawOrigin) { match self { - Self::SetIdentity => >::instance(&SetIdentity, components), - Self::AddRegistrar => >::instance(&AddRegistrar, components), + Self::SetIdentity => , RawOrigin>>::instance(&SetIdentity, components), + Self::AddRegistrar => , RawOrigin>>::instance(&AddRegistrar, components), } } } @@ -165,8 +156,12 @@ impl Benchmarking for Module { _ => return Vec::new(), }; + // Warm up the DB? + sp_io::benchmarking::commit_db(); + sp_io::benchmarking::wipe_db(); + // first one is set_identity. - let components = >::components(&selected_benchmark); + let components = , RawOrigin>>::components(&selected_benchmark); // results go here let mut results: Vec = Vec::new(); // Select the component we will be benchmarking. Each component will be benchmarked. @@ -188,7 +183,7 @@ impl Benchmarking for Module { sp_std::if_std!{ println!("STEP {:?} REPEAT {:?}", s, r); } - let (call, caller) = >::instance(&selected_benchmark, &c); + let (call, caller) = , RawOrigin>>::instance(&selected_benchmark, &c); sp_io::benchmarking::commit_db(); let start = sp_io::benchmarking::current_time(); assert_eq!(call.dispatch(caller.into()), Ok(())); diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 9c4a9d0cfeb37..88744db3cd507 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -70,7 +70,7 @@ use sp_std::{fmt::Debug, ops::Add, iter::once}; use enumflags2::BitFlags; use codec::{Encode, Decode}; use sp_runtime::{DispatchResult, RuntimeDebug}; -use sp_runtime::traits::{StaticLookup, EnsureOrigin, Zero, AppendZerosInput, Dispatchable}; +use sp_runtime::traits::{StaticLookup, EnsureOrigin, Zero, AppendZerosInput}; use frame_support::{ decl_module, decl_event, decl_storage, ensure, decl_error, traits::{Currency, ReservableCurrency, OnUnbalanced, Get}, diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 17de7aa6fee7d..0cd150921dd93 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -24,6 +24,7 @@ use std::fmt::Display; #[cfg(feature = "std")] use serde::{Serialize, Deserialize, de::DeserializeOwned}; use sp_core::{self, Hasher, Blake2Hasher, TypeId, RuntimeDebug}; +use crate::BenchmarkParameter; use crate::codec::{Codec, Encode, Decode}; use crate::transaction_validity::{ ValidTransaction, TransactionValidity, TransactionValidityError, UnknownTransaction, @@ -1324,6 +1325,15 @@ pub trait Benchmarking { fn run_benchmark(extrinsic: Vec, steps: u32, repeat: u32) -> Vec; } +/// The required setup for creating a benchmark. +pub trait BenchmarkingSetup { + /// Return the components and their ranges which should be tested in this benchmark. + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)>; + + /// Set up the storage, and prepare a call and caller to test in a single run of the benchmark. + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (Call, RawOrigin); +} + #[cfg(test)] mod tests { use super::*; From 1c97bd96b11065e951d08f0d8622109c4a36f9a6 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 7 Feb 2020 09:41:58 +0100 Subject: [PATCH 35/50] Append bench --- frame/benchmark/src/benchmarking.rs | 31 +++++++++++++++++++++++++++++ frame/benchmark/src/lib.rs | 10 ++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/frame/benchmark/src/benchmarking.rs b/frame/benchmark/src/benchmarking.rs index 3613fb3fb8c4d..371ec75505a53 100644 --- a/frame/benchmark/src/benchmarking.rs +++ b/frame/benchmark/src/benchmarking.rs @@ -77,8 +77,36 @@ impl BenchmarkingSetup, RawOrigin> for } } +struct AddMemberListAppend; +impl BenchmarkingSetup, RawOrigin> for AddMemberListAppend { + + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { + vec![ + // Registrar Count + (BenchmarkParameter::M, 1, 1000), + ] + } + + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (crate::Call, RawOrigin) + { + // Add r registrars + let r = components.iter().find(|&c| c.0 == BenchmarkParameter::M).unwrap(); + for i in 0..r.1 { + let _ = Benchmark::::add_member_list_append(RawOrigin::Signed(account::(i)).into()); + } + + sp_std::if_std!{ + println!("# Users {:?}", MyList::::get().len()); + } + + // Return the `add_registrar` r + 1 call + (crate::Call::::add_member_list_append(), RawOrigin::Signed(account::(r.1 + 1))) + } +} + enum SelectedBenchmark { AddMemberList, + AddMemberListAppend, } impl BenchmarkingSetup, RawOrigin> for SelectedBenchmark { @@ -86,6 +114,7 @@ impl BenchmarkingSetup, RawOrigin> for { match self { Self::AddMemberList => , RawOrigin>>::components(&AddMemberList), + Self::AddMemberListAppend => , RawOrigin>>::components(&AddMemberListAppend), } } @@ -93,6 +122,7 @@ impl BenchmarkingSetup, RawOrigin> for { match self { Self::AddMemberList => , RawOrigin>>::instance(&AddMemberList, components), + Self::AddMemberListAppend => , RawOrigin>>::instance(&AddMemberListAppend, components), } } } @@ -103,6 +133,7 @@ impl Benchmarking for Module { let selected_benchmark = match extrinsic.as_slice() { b"time_host" => return benchmarking::time_host(steps, repeat), b"add_member_list" => SelectedBenchmark::AddMemberList, + b"add_member_list_append" => SelectedBenchmark::AddMemberListAppend, _ => return Vec::new(), }; diff --git a/frame/benchmark/src/lib.rs b/frame/benchmark/src/lib.rs index 79a774ac6b8b5..1be8ac1c791f5 100644 --- a/frame/benchmark/src/lib.rs +++ b/frame/benchmark/src/lib.rs @@ -68,11 +68,17 @@ decl_module! { pub fn add_member_list(origin) { // Check it was signed and get the signer. let who = ensure_signed(origin)?; - - // Add user to the list. + // Push user to the list. MyList::::mutate(|x| x.push(who)); } + pub fn add_member_list_append(origin) { + // Check it was signed and get the signer. + let who = ensure_signed(origin)?; + // Append user to the list. + MyList::::append(&[who])?; + } + pub fn check_member_list(origin) { // Check it was signed and get the signer. let who = ensure_signed(origin)?; From ea5c3e1441438eca70eab93901904245361ba728 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 7 Feb 2020 17:08:23 +0100 Subject: [PATCH 36/50] Use Results --- bin/node/runtime/src/lib.rs | 10 +- client/service/src/chain_ops.rs | 8 +- frame/benchmark/src/benchmarking.rs | 22 +-- frame/identity/src/benchmarking.rs | 259 ++++++++++++++++++++++------ primitives/runtime/src/lib.rs | 15 +- primitives/runtime/src/traits.rs | 4 +- 6 files changed, 232 insertions(+), 86 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index b1cf4de7fa160..e044e6dd77213 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -813,11 +813,11 @@ impl_runtime_apis! { } impl crate::Benchmark for Runtime { - fn dispatch_benchmark(module: Vec, extrinsic: Vec, steps: u32, repeat: u32) -> Vec { + fn dispatch_benchmark(module: Vec, extrinsic: Vec, steps: u32, repeat: u32) -> Option> { match module.as_slice() { - b"pallet-identity" | b"identity" => Identity::run_benchmark(extrinsic, steps, repeat), - b"pallet-benchmark" | b"benchmark" => Bench::run_benchmark(extrinsic, steps, repeat), - _ => return Vec::new(), + b"pallet-identity" | b"identity" => Identity::run_benchmark(extrinsic, steps, repeat).ok(), + b"pallet-benchmark" | b"benchmark" => Bench::run_benchmark(extrinsic, steps, repeat).ok(), + _ => return None, } } } @@ -826,7 +826,7 @@ impl_runtime_apis! { sp_api::decl_runtime_apis! { pub trait Benchmark { - fn dispatch_benchmark(module: Vec, extrinsic: Vec, steps: u32, repeat: u32) -> Vec; + fn dispatch_benchmark(module: Vec, extrinsic: Vec, steps: u32, repeat: u32) -> Option>; } } diff --git a/client/service/src/chain_ops.rs b/client/service/src/chain_ops.rs index 65bd63b0e0df8..1ba6c52c07a04 100644 --- a/client/service/src/chain_ops.rs +++ b/client/service/src/chain_ops.rs @@ -79,10 +79,8 @@ pub fn benchmark_runtime ( &(&pallet, &extrinsic, steps, repeat).encode(), Default::default(), ).execute(strategy).map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?; - let results = as Decode>::decode(&mut &result[..]).unwrap(); - if results.len() == 0 { - info!("No Results."); - } else { + let results = > as Decode>::decode(&mut &result[..]).unwrap_or(None); + if let Some(results) = results { // Print benchmark metadata println!("Pallet: {:?}, Extrinsic: {:?}, Steps: {:?}, Repeat: {:?}", pallet, extrinsic, steps, repeat); // Print the table header @@ -95,6 +93,8 @@ pub fn benchmark_runtime ( print!("{:?},\n", result.1); }); info!("Done."); + } else { + info!("No Results."); } Ok(()) } diff --git a/frame/benchmark/src/benchmarking.rs b/frame/benchmark/src/benchmarking.rs index 371ec75505a53..35d2669632b85 100644 --- a/frame/benchmark/src/benchmarking.rs +++ b/frame/benchmark/src/benchmarking.rs @@ -33,7 +33,7 @@ fn account(index: u32) -> T::AccountId { } // Custom implementation to handle benchmarking of calling a host function. -fn time_host(steps: u32, repeat: u32) -> Vec { +fn time_host(steps: u32, repeat: u32) -> Result, &'static str> { let mut results: Vec = Vec::new(); for _ in 0..steps { @@ -47,7 +47,7 @@ fn time_host(steps: u32, repeat: u32) -> Vec { results.push((vec![(BenchmarkParameter::L, repeat)], elapsed)); } - return results; + return Ok(results); } struct AddMemberList; @@ -60,7 +60,7 @@ impl BenchmarkingSetup, RawOrigin> for ] } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (crate::Call, RawOrigin) + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> { // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::M).unwrap(); @@ -73,7 +73,7 @@ impl BenchmarkingSetup, RawOrigin> for } // Return the `add_registrar` r + 1 call - (crate::Call::::add_member_list(), RawOrigin::Signed(account::(r.1 + 1))) + Ok((crate::Call::::add_member_list(), RawOrigin::Signed(account::(r.1 + 1)))) } } @@ -87,7 +87,7 @@ impl BenchmarkingSetup, RawOrigin> for ] } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (crate::Call, RawOrigin) + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> { // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::M).unwrap(); @@ -100,7 +100,7 @@ impl BenchmarkingSetup, RawOrigin> for } // Return the `add_registrar` r + 1 call - (crate::Call::::add_member_list_append(), RawOrigin::Signed(account::(r.1 + 1))) + Ok((crate::Call::::add_member_list_append(), RawOrigin::Signed(account::(r.1 + 1)))) } } @@ -118,7 +118,7 @@ impl BenchmarkingSetup, RawOrigin> for } } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (crate::Call, RawOrigin) + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> { match self { Self::AddMemberList => , RawOrigin>>::instance(&AddMemberList, components), @@ -128,13 +128,13 @@ impl BenchmarkingSetup, RawOrigin> for } impl Benchmarking for Module { - fn run_benchmark(extrinsic: Vec, steps: u32, repeat: u32) -> Vec { + fn run_benchmark(extrinsic: Vec, steps: u32, repeat: u32) -> Result, &'static str> { let selected_benchmark = match extrinsic.as_slice() { b"time_host" => return benchmarking::time_host(steps, repeat), b"add_member_list" => SelectedBenchmark::AddMemberList, b"add_member_list_append" => SelectedBenchmark::AddMemberListAppend, - _ => return Vec::new(), + _ => return Err("Extrinsic not found."), }; // Warm up the DB? @@ -164,7 +164,7 @@ impl Benchmarking for Module { sp_std::if_std!{ println!("STEP {:?} REPEAT {:?}", s, r); } - let (call, caller) = , RawOrigin>>::instance(&selected_benchmark, &c); + let (call, caller) = , RawOrigin>>::instance(&selected_benchmark, &c)?; sp_io::benchmarking::commit_db(); let start = sp_io::benchmarking::current_time(); assert_eq!(call.dispatch(caller.into()), Ok(())); @@ -175,6 +175,6 @@ impl Benchmarking for Module { } } } - return results; + return Ok(results); } } diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index d6ea8fd324dd6..4674611231a83 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -25,52 +25,115 @@ use sp_runtime::traits::{Bounded, Benchmarking, BenchmarkingSetup, Dispatchable} use crate::Module as Identity; +const MAX_REGISTRARS: u32 = 16; + +// Support Functions fn account(index: u32) -> T::AccountId { let entropy = (b"benchmark", index).using_encoded(blake2_256); T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() } -struct SetIdentity; -impl BenchmarkingSetup, RawOrigin> for SetIdentity { +fn add_n_registrars(r: u32) -> Result<(), &'static str> { + for i in 0..r { + let _ = T::Currency::make_free_balance_be(&account::(i), BalanceOf::::max_value()); + Identity::::add_registrar(RawOrigin::Root.into(), account::(i))?; + Identity::::set_fee(RawOrigin::Signed(account::(i)).into(), i.into(), 10.into())?; + let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); + Identity::::set_fields(RawOrigin::Signed(account::(i)).into(), i.into(), fields)?; + } + + assert_eq!(Registrars::::get().len(), r as usize); + Ok(()) +} + +struct AddRegistrar; +impl BenchmarkingSetup, RawOrigin> for AddRegistrar { fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { vec![ // Registrar Count - (BenchmarkParameter::R, 1, 16), - // Additional Field Count - (BenchmarkParameter::X, 1, 20) + (BenchmarkParameter::R, 1, MAX_REGISTRARS), ] } - /// Assumes externalities are set up with a mutable state. - /// - /// Panics if `component_name` isn't from `set_identity::components` or `component_value` is out of - /// the range of `set_identity::components`. - /// - /// Sets up state randomly and returns a randomly generated `set_identity` with sensible (fixed) - /// values for all complexity components except those mentioned in the identity. - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (crate::Call, RawOrigin) + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> { // Add r registrars - let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap(); - for i in 0..r.1 { + let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; + for i in 0..r { let _ = T::Currency::make_free_balance_be(&account::(i), BalanceOf::::max_value()); - assert_eq!(Identity::::add_registrar(RawOrigin::Root.into(), account::(i)), Ok(())); - assert_eq!(Identity::::set_fee(RawOrigin::Signed(account::(i)).into(), i.into(), 10.into()), Ok(())); - let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); - assert_eq!(Identity::::set_fields(RawOrigin::Signed(account::(i)).into(), i.into(), fields), Ok(())); + Identity::::add_registrar(RawOrigin::Root.into(), account::(i))?; } sp_std::if_std!{ println!("# Registrars {:?}", Registrars::::get().len()); } + + // Return the `add_registrar` r + 1 call + Ok((crate::Call::::add_registrar(account::(r + 1)), RawOrigin::Root)) + } +} + +struct SetIdentity; +impl BenchmarkingSetup, RawOrigin> for SetIdentity { + + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { + vec![ + // Registrar Count + (BenchmarkParameter::R, 1, MAX_REGISTRARS), + // Additional Field Count + (BenchmarkParameter::X, 1, T::MaxAdditionalFields::get()) + ] + } + + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + { + // Add r registrars + let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; + benchmarking::add_n_registrars::(r)?; + + // Generic data to be used. + let data = Data::Raw(vec![0; 32]); + + // The target user + let caller = account::(r + 1); + let caller_lookup: ::Source = T::Lookup::unlookup(caller.clone()); + let caller_origin: ::Origin = RawOrigin::Signed(caller.clone()).into(); + + // Give them some monnnayy + let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + + // Add an initial identity + let initial_info = IdentityInfo { + additional: vec![(data.clone(), data.clone())], + display: data.clone(), + legal: data.clone(), + web: data.clone(), + riot: data.clone(), + email: data.clone(), + pgp_fingerprint: Some([0; 20]), + image: data.clone(), + twitter: data.clone(), + }; + + Identity::::set_identity(caller_origin.clone(), initial_info)?; + + // User requests judgement from all the registrars, and they approve + for i in 0..r { + Identity::::request_judgement(caller_origin.clone(), i, 10.into())?; + Identity::::provide_judgement( + RawOrigin::Signed(account::(i)).into(), + i, + caller_lookup.clone(), + Judgement::Reasonable + )?; + } // Create identity info with x additional fields - let x = components.iter().find(|&c| c.0 == BenchmarkParameter::X).unwrap(); + let x = components.iter().find(|&c| c.0 == BenchmarkParameter::X).unwrap().1; // 32 byte data that we reuse below - let data = Data::Raw(vec![0; 32]); let info = IdentityInfo { - additional: vec![(data.clone(), data.clone()); x.1 as usize], + additional: vec![(data.clone(), data.clone()); x as usize], display: data.clone(), legal: data.clone(), web: data.clone(), @@ -81,79 +144,161 @@ impl BenchmarkingSetup, RawOrigin> for twitter: data.clone(), }; - let caller = account::(r.1 + 1); + // Return the `set_identity` call + Ok((crate::Call::::set_identity(info), RawOrigin::Signed(caller))) + } +} + +struct SetSubs; +impl BenchmarkingSetup, RawOrigin> for SetSubs { + + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { + vec![ + // Subs Count + (BenchmarkParameter::S, 1, T::MaxSubAccounts::get()), + ] + } + + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + { + // Generic data to be used. + let data = Data::Raw(vec![0; 32]); + + // The target user + let caller = account::(0); + let caller_origin: ::Origin = RawOrigin::Signed(caller.clone()).into(); + + // Give them some monnnayy let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); - // Return the `set_identity` call - (crate::Call::::set_identity(info), RawOrigin::Signed(caller)) + let info = IdentityInfo { + additional: vec![(data.clone(), data.clone())], + display: data.clone(), + legal: data.clone(), + web: data.clone(), + riot: data.clone(), + email: data.clone(), + pgp_fingerprint: Some([0; 20]), + image: data.clone(), + twitter: data.clone(), + }; + + // Create their main identity + Identity::::set_identity(caller_origin.clone(), info)?; + + // Give them s many sub accounts + let s = components.iter().find(|&c| c.0 == BenchmarkParameter::S).unwrap().1; + let mut subs = Vec::new(); + for i in 0..s { + let sub_account = account::(i); + subs.push((sub_account, data.clone())); + } + Identity::::set_subs(caller_origin.clone(), subs.clone())?; + + // Create an s+1 sub account to add + subs.push((account::(s), data)); + + // Return the `set_subs` call + Ok((crate::Call::::set_subs(subs), RawOrigin::Signed(caller))) } } -struct AddRegistrar; -impl BenchmarkingSetup, RawOrigin> for AddRegistrar { +struct ClearIdentity; +impl BenchmarkingSetup, RawOrigin> for ClearIdentity { fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { vec![ // Registrar Count - (BenchmarkParameter::R, 1, 16), + (BenchmarkParameter::R, 1, MAX_REGISTRARS), + // Subs Count + (BenchmarkParameter::S, 1, T::MaxSubAccounts::get()), + // Additional Field Count + (BenchmarkParameter::X, 1, T::MaxAdditionalFields::get()), ] } - /// Assumes externalities are set up with a mutable state. - /// - /// Panics if `component_name` isn't from `set_identity::components` or `component_value` is out of - /// the range of `set_identity::components`. - /// - /// Sets up state randomly and returns a randomly generated `set_identity` with sensible (fixed) - /// values for all complexity components except those mentioned in the identity. - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (crate::Call, RawOrigin) - { - // Add r registrars - let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap(); - for i in 0..r.1 { - let _ = T::Currency::make_free_balance_be(&account::(i), BalanceOf::::max_value()); - assert_eq!(Identity::::add_registrar(RawOrigin::Root.into(), account::(i)), Ok(())); - } + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + { + // Generic data to be used. + let data = Data::Raw(vec![0; 32]); - sp_std::if_std!{ - println!("# Registrars {:?}", Registrars::::get().len()); + // The target user + let caller = account::(0); + let caller_origin: ::Origin = RawOrigin::Signed(caller.clone()).into(); + + // Give them some monnnayy + let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + + let info = IdentityInfo { + additional: vec![(data.clone(), data.clone())], + display: data.clone(), + legal: data.clone(), + web: data.clone(), + riot: data.clone(), + email: data.clone(), + pgp_fingerprint: Some([0; 20]), + image: data.clone(), + twitter: data.clone(), + }; + + // Create their main identity + Identity::::set_identity(caller_origin.clone(), info)?; + + // Give them s many sub accounts + let s = components.iter().find(|&c| c.0 == BenchmarkParameter::S).unwrap().1; + let mut subs = Vec::new(); + for i in 0..s { + let sub_account = account::(i); + subs.push((sub_account, data.clone())); } + Identity::::set_subs(caller_origin.clone(), subs.clone())?; - // Return the `add_registrar` r + 1 call - (crate::Call::::add_registrar(account::(r.1 + 1)), RawOrigin::Root) + // Create an s+1 sub account to add + subs.push((account::(s), data)); + + // Return the `set_subs` call + Ok((crate::Call::::set_subs(subs), RawOrigin::Signed(caller))) } } enum SelectedBenchmark { - SetIdentity, AddRegistrar, + SetIdentity, + SetSubs, + ClearIdentity, } impl BenchmarkingSetup, RawOrigin> for SelectedBenchmark { fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { match self { - Self::SetIdentity => , RawOrigin>>::components(&SetIdentity), Self::AddRegistrar => , RawOrigin>>::components(&AddRegistrar), + Self::SetIdentity => , RawOrigin>>::components(&SetIdentity), + Self::SetSubs => , RawOrigin>>::components(&SetSubs), + Self::ClearIdentity => , RawOrigin>>::components(&ClearIdentity), } } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (crate::Call, RawOrigin) + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> { match self { - Self::SetIdentity => , RawOrigin>>::instance(&SetIdentity, components), Self::AddRegistrar => , RawOrigin>>::instance(&AddRegistrar, components), + Self::SetIdentity => , RawOrigin>>::instance(&SetIdentity, components), + Self::SetSubs => , RawOrigin>>::instance(&SetSubs, components), + Self::ClearIdentity => , RawOrigin>>::instance(&ClearIdentity, components), } } } impl Benchmarking for Module { - fn run_benchmark(extrinsic: Vec, steps: u32, repeat: u32) -> Vec { + fn run_benchmark(extrinsic: Vec, steps: u32, repeat: u32) -> Result, &'static str> { let selected_benchmark = match extrinsic.as_slice() { - b"set_identity" => SelectedBenchmark::SetIdentity, b"add_registrar" => SelectedBenchmark::AddRegistrar, - _ => return Vec::new(), + b"set_identity" => SelectedBenchmark::SetIdentity, + b"set_subs" => SelectedBenchmark::SetSubs, + b"clear_identity" => SelectedBenchmark::ClearIdentity, + _ => return Err("Could not find extrinsic."), }; // Warm up the DB? @@ -183,10 +328,10 @@ impl Benchmarking for Module { sp_std::if_std!{ println!("STEP {:?} REPEAT {:?}", s, r); } - let (call, caller) = , RawOrigin>>::instance(&selected_benchmark, &c); + let (call, caller) = , RawOrigin>>::instance(&selected_benchmark, &c)?; sp_io::benchmarking::commit_db(); let start = sp_io::benchmarking::current_time(); - assert_eq!(call.dispatch(caller.into()), Ok(())); + call.dispatch(caller.into())?; let finish = sp_io::benchmarking::current_time(); let elapsed = finish - start; sp_io::benchmarking::wipe_db(); @@ -194,6 +339,6 @@ impl Benchmarking for Module { } } } - return results; + return Ok(results); } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index a9e9696df690a..d48577acefe8f 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -405,13 +405,13 @@ impl From<&'static str> for DispatchError { } } -impl Into<&'static str> for DispatchError { - fn into(self) -> &'static str { - match self { - Self::Other(msg) => msg, - Self::CannotLookup => "Can not lookup", - Self::BadOrigin => "Bad origin", - Self::Module { message, .. } => message.unwrap_or("Unknown module error"), +impl From for &'static str { + fn from(err: DispatchError) -> &'static str { + match err { + DispatchError::Other(msg) => msg, + DispatchError::CannotLookup => "Can not lookup", + DispatchError::BadOrigin => "Bad origin", + DispatchError::Module { message, .. } => message.unwrap_or("Unknown module error"), } } } @@ -680,6 +680,7 @@ pub fn print(print: impl traits::Printable) { /// An alphabet of possible parameters to use for benchmarking. #[derive(Encode, Decode, Clone, Copy, PartialEq, Debug)] +#[allow(missing_docs)] pub enum BenchmarkParameter { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, } diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 0cd150921dd93..9aab34943f7bc 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1322,7 +1322,7 @@ pub trait BlockIdTo { /// The module benchmarking trait. pub trait Benchmarking { /// Run the benchmarks for this module. - fn run_benchmark(extrinsic: Vec, steps: u32, repeat: u32) -> Vec; + fn run_benchmark(extrinsic: Vec, steps: u32, repeat: u32) -> Result, &'static str>; } /// The required setup for creating a benchmark. @@ -1331,7 +1331,7 @@ pub trait BenchmarkingSetup { fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)>; /// Set up the storage, and prepare a call and caller to test in a single run of the benchmark. - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> (Call, RawOrigin); + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(Call, RawOrigin), &'static str>; } #[cfg(test)] From 55a2e8542364d717ee3080f6a2628a505362d5c9 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 7 Feb 2020 17:19:15 +0100 Subject: [PATCH 37/50] fix merge --- client/db/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index d35a554d3f29e..ef418d43efc18 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0" [dependencies] parking_lot = "0.10.0" log = "0.4.8" +rand = "0.7" kvdb = "0.4.0" kvdb-rocksdb = { version = "0.5", optional = true } kvdb-memorydb = "0.4.0" From 6787808b9cd8e6667b4e31585ae2650b28f65b8f Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sat, 8 Feb 2020 00:54:18 +0100 Subject: [PATCH 38/50] Clear Identity benchmark --- frame/identity/src/benchmarking.rs | 162 ++++++++++++----------------- 1 file changed, 65 insertions(+), 97 deletions(-) diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 4674611231a83..0c35f49836d4b 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -28,24 +28,56 @@ use crate::Module as Identity; const MAX_REGISTRARS: u32 = 16; // Support Functions -fn account(index: u32) -> T::AccountId { - let entropy = (b"benchmark", index).using_encoded(blake2_256); +fn account(name: &'static str, index: u32) -> T::AccountId { + let entropy = (name, index).using_encoded(blake2_256); T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() } -fn add_n_registrars(r: u32) -> Result<(), &'static str> { +fn add_registrars(r: u32) -> Result<(), &'static str> { for i in 0..r { - let _ = T::Currency::make_free_balance_be(&account::(i), BalanceOf::::max_value()); - Identity::::add_registrar(RawOrigin::Root.into(), account::(i))?; - Identity::::set_fee(RawOrigin::Signed(account::(i)).into(), i.into(), 10.into())?; + let _ = T::Currency::make_free_balance_be(&account::("registrar", i), BalanceOf::::max_value()); + Identity::::add_registrar(RawOrigin::Root.into(), account::("registrar", i))?; + Identity::::set_fee(RawOrigin::Signed(account::("registrar", i)).into(), i.into(), 10.into())?; let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); - Identity::::set_fields(RawOrigin::Signed(account::(i)).into(), i.into(), fields)?; + Identity::::set_fields(RawOrigin::Signed(account::("registrar", i)).into(), i.into(), fields)?; } assert_eq!(Registrars::::get().len(), r as usize); Ok(()) } +fn add_sub_accounts(who: T::AccountId, s: u32) -> Result, &'static str> { + let mut subs = Vec::new(); + let who_origin = RawOrigin::Signed(who.clone()); + let data = Data::Raw(vec![0; 32]); + + for i in 0..s { + let sub_account = account::("sub", i); + subs.push((sub_account, data.clone())); + } + Identity::::set_subs(who_origin.into(), subs.clone())?; + + return Ok(subs) +} + +fn create_identity_info(num_fields: u32) -> IdentityInfo { + let data = Data::Raw(vec![0; 32]); + + let info = IdentityInfo { + additional: vec![(data.clone(), data.clone()); num_fields as usize], + display: data.clone(), + legal: data.clone(), + web: data.clone(), + riot: data.clone(), + email: data.clone(), + pgp_fingerprint: Some([0; 20]), + image: data.clone(), + twitter: data.clone(), + }; + + return info +} + struct AddRegistrar; impl BenchmarkingSetup, RawOrigin> for AddRegistrar { @@ -60,17 +92,10 @@ impl BenchmarkingSetup, RawOrigin> for { // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; - for i in 0..r { - let _ = T::Currency::make_free_balance_be(&account::(i), BalanceOf::::max_value()); - Identity::::add_registrar(RawOrigin::Root.into(), account::(i))?; - } - - sp_std::if_std!{ - println!("# Registrars {:?}", Registrars::::get().len()); - } + benchmarking::add_registrars::(r)?; // Return the `add_registrar` r + 1 call - Ok((crate::Call::::add_registrar(account::(r + 1)), RawOrigin::Root)) + Ok((crate::Call::::add_registrar(account::("registrar", r + 1)), RawOrigin::Root)) } } @@ -90,39 +115,25 @@ impl BenchmarkingSetup, RawOrigin> for { // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; - benchmarking::add_n_registrars::(r)?; - - // Generic data to be used. - let data = Data::Raw(vec![0; 32]); + benchmarking::add_registrars::(r)?; // The target user - let caller = account::(r + 1); + let caller = account::("caller", r); let caller_lookup: ::Source = T::Lookup::unlookup(caller.clone()); let caller_origin: ::Origin = RawOrigin::Signed(caller.clone()).into(); - // Give them some monnnayy + // Give them some money let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); // Add an initial identity - let initial_info = IdentityInfo { - additional: vec![(data.clone(), data.clone())], - display: data.clone(), - legal: data.clone(), - web: data.clone(), - riot: data.clone(), - email: data.clone(), - pgp_fingerprint: Some([0; 20]), - image: data.clone(), - twitter: data.clone(), - }; - + let initial_info = benchmarking::create_identity_info::(1); Identity::::set_identity(caller_origin.clone(), initial_info)?; // User requests judgement from all the registrars, and they approve for i in 0..r { Identity::::request_judgement(caller_origin.clone(), i, 10.into())?; Identity::::provide_judgement( - RawOrigin::Signed(account::(i)).into(), + RawOrigin::Signed(account::("registrar", i)).into(), i, caller_lookup.clone(), Judgement::Reasonable @@ -132,17 +143,7 @@ impl BenchmarkingSetup, RawOrigin> for // Create identity info with x additional fields let x = components.iter().find(|&c| c.0 == BenchmarkParameter::X).unwrap().1; // 32 byte data that we reuse below - let info = IdentityInfo { - additional: vec![(data.clone(), data.clone()); x as usize], - display: data.clone(), - legal: data.clone(), - web: data.clone(), - riot: data.clone(), - email: data.clone(), - pgp_fingerprint: Some([0; 20]), - image: data.clone(), - twitter: data.clone(), - }; + let info = benchmarking::create_identity_info::(x); // Return the `set_identity` call Ok((crate::Call::::set_identity(info), RawOrigin::Signed(caller))) @@ -165,38 +166,22 @@ impl BenchmarkingSetup, RawOrigin> for let data = Data::Raw(vec![0; 32]); // The target user - let caller = account::(0); + let caller = account::("caller", 0); let caller_origin: ::Origin = RawOrigin::Signed(caller.clone()).into(); - // Give them some monnnayy + // Give them some money let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); - let info = IdentityInfo { - additional: vec![(data.clone(), data.clone())], - display: data.clone(), - legal: data.clone(), - web: data.clone(), - riot: data.clone(), - email: data.clone(), - pgp_fingerprint: Some([0; 20]), - image: data.clone(), - twitter: data.clone(), - }; - // Create their main identity + let info = benchmarking::create_identity_info::(1); Identity::::set_identity(caller_origin.clone(), info)?; // Give them s many sub accounts let s = components.iter().find(|&c| c.0 == BenchmarkParameter::S).unwrap().1; - let mut subs = Vec::new(); - for i in 0..s { - let sub_account = account::(i); - subs.push((sub_account, data.clone())); - } - Identity::::set_subs(caller_origin.clone(), subs.clone())?; + let mut subs = add_sub_accounts::(caller.clone(), s)?; // Create an s+1 sub account to add - subs.push((account::(s), data)); + subs.push((account::("sub", s+1), data)); // Return the `set_subs` call Ok((crate::Call::::set_subs(subs), RawOrigin::Signed(caller))) @@ -219,45 +204,28 @@ impl BenchmarkingSetup, RawOrigin> for fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> { - // Generic data to be used. - let data = Data::Raw(vec![0; 32]); - // The target user - let caller = account::(0); + let caller = account::("caller", 0); let caller_origin: ::Origin = RawOrigin::Signed(caller.clone()).into(); - // Give them some monnnayy - let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + // Register r registrars + let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; + benchmarking::add_registrars::(r)?; - let info = IdentityInfo { - additional: vec![(data.clone(), data.clone())], - display: data.clone(), - legal: data.clone(), - web: data.clone(), - riot: data.clone(), - email: data.clone(), - pgp_fingerprint: Some([0; 20]), - image: data.clone(), - twitter: data.clone(), - }; + // Give them some money + let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); - // Create their main identity + // Create their main identity with x additional fields + let x = components.iter().find(|&c| c.0 == BenchmarkParameter::X).unwrap().1; + let info = benchmarking::create_identity_info::(x); Identity::::set_identity(caller_origin.clone(), info)?; // Give them s many sub accounts let s = components.iter().find(|&c| c.0 == BenchmarkParameter::S).unwrap().1; - let mut subs = Vec::new(); - for i in 0..s { - let sub_account = account::(i); - subs.push((sub_account, data.clone())); - } - Identity::::set_subs(caller_origin.clone(), subs.clone())?; + let _ = benchmarking::add_sub_accounts::(caller.clone(), s)?; - // Create an s+1 sub account to add - subs.push((account::(s), data)); - - // Return the `set_subs` call - Ok((crate::Call::::set_subs(subs), RawOrigin::Signed(caller))) + // Return the `clear_identity` call + Ok((crate::Call::::clear_identity(), RawOrigin::Signed(caller))) } } @@ -329,7 +297,7 @@ impl Benchmarking for Module { println!("STEP {:?} REPEAT {:?}", s, r); } let (call, caller) = , RawOrigin>>::instance(&selected_benchmark, &c)?; - sp_io::benchmarking::commit_db(); + //sp_io::benchmarking::commit_db(); let start = sp_io::benchmarking::current_time(); call.dispatch(caller.into())?; let finish = sp_io::benchmarking::current_time(); From 4c2b2180e969ec7b1f23b4e15644810ef9700d66 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sat, 8 Feb 2020 01:31:05 +0100 Subject: [PATCH 39/50] Bench request judgment and cancel request --- frame/identity/src/benchmarking.rs | 89 +++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 8 deletions(-) diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 0c35f49836d4b..4d8695247473c 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -38,7 +38,10 @@ fn add_registrars(r: u32) -> Result<(), &'static str> { let _ = T::Currency::make_free_balance_be(&account::("registrar", i), BalanceOf::::max_value()); Identity::::add_registrar(RawOrigin::Root.into(), account::("registrar", i))?; Identity::::set_fee(RawOrigin::Signed(account::("registrar", i)).into(), i.into(), 10.into())?; - let fields = IdentityFields(IdentityField::Display | IdentityField::Legal); + let fields = IdentityFields( + IdentityField::Display | IdentityField::Legal | IdentityField::Web | IdentityField::Riot + | IdentityField::Email | IdentityField::PgpFingerprint | IdentityField::Image | IdentityField::Twitter + ); Identity::::set_fields(RawOrigin::Signed(account::("registrar", i)).into(), i.into(), fields)?; } @@ -121,8 +124,6 @@ impl BenchmarkingSetup, RawOrigin> for let caller = account::("caller", r); let caller_lookup: ::Source = T::Lookup::unlookup(caller.clone()); let caller_origin: ::Origin = RawOrigin::Signed(caller.clone()).into(); - - // Give them some money let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); // Add an initial identity @@ -168,8 +169,6 @@ impl BenchmarkingSetup, RawOrigin> for // The target user let caller = account::("caller", 0); let caller_origin: ::Origin = RawOrigin::Signed(caller.clone()).into(); - - // Give them some money let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); // Create their main identity @@ -207,14 +206,12 @@ impl BenchmarkingSetup, RawOrigin> for // The target user let caller = account::("caller", 0); let caller_origin: ::Origin = RawOrigin::Signed(caller.clone()).into(); + let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); // Register r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; benchmarking::add_registrars::(r)?; - // Give them some money - let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); - // Create their main identity with x additional fields let x = components.iter().find(|&c| c.0 == BenchmarkParameter::X).unwrap().1; let info = benchmarking::create_identity_info::(x); @@ -229,11 +226,81 @@ impl BenchmarkingSetup, RawOrigin> for } } +struct RequestJudgement; +impl BenchmarkingSetup, RawOrigin> for RequestJudgement { + + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { + vec![ + // Registrar Count + (BenchmarkParameter::R, 1, MAX_REGISTRARS), + // Additional Field Count + (BenchmarkParameter::X, 1, T::MaxAdditionalFields::get()), + ] + } + + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + { + // The target user + let caller = account::("caller", 0); + let caller_origin: ::Origin = RawOrigin::Signed(caller.clone()).into(); + let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + + // Register r registrars + let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; + benchmarking::add_registrars::(r)?; + + // Create their main identity with x additional fields + let x = components.iter().find(|&c| c.0 == BenchmarkParameter::X).unwrap().1; + let info = benchmarking::create_identity_info::(x); + Identity::::set_identity(caller_origin.clone(), info)?; + + // Return the `request_judgement` call + Ok((crate::Call::::request_judgement(r-1, 10.into()), RawOrigin::Signed(caller))) + } +} + +struct CancelRequest; +impl BenchmarkingSetup, RawOrigin> for CancelRequest { + + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { + vec![ + // Registrar Count + (BenchmarkParameter::R, 1, MAX_REGISTRARS), + // Additional Field Count + (BenchmarkParameter::X, 1, T::MaxAdditionalFields::get()), + ] + } + + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + { + // The target user + let caller = account::("caller", 0); + let caller_origin: ::Origin = RawOrigin::Signed(caller.clone()).into(); + let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + + // Register r registrars + let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; + benchmarking::add_registrars::(r)?; + + // Create their main identity with x additional fields + let x = components.iter().find(|&c| c.0 == BenchmarkParameter::X).unwrap().1; + let info = benchmarking::create_identity_info::(x); + Identity::::set_identity(caller_origin.clone(), info)?; + + // Request judgement + Identity::::request_judgement(caller_origin.clone(), r-1, 10.into())?; + + Ok((crate::Call::::cancel_request(r-1), RawOrigin::Signed(caller))) + } +} + enum SelectedBenchmark { AddRegistrar, SetIdentity, SetSubs, ClearIdentity, + RequestJudgement, + CancelRequest, } impl BenchmarkingSetup, RawOrigin> for SelectedBenchmark { @@ -244,6 +311,8 @@ impl BenchmarkingSetup, RawOrigin> for Self::SetIdentity => , RawOrigin>>::components(&SetIdentity), Self::SetSubs => , RawOrigin>>::components(&SetSubs), Self::ClearIdentity => , RawOrigin>>::components(&ClearIdentity), + Self::RequestJudgement => , RawOrigin>>::components(&RequestJudgement), + Self::CancelRequest => , RawOrigin>>::components(&CancelRequest), } } @@ -254,6 +323,8 @@ impl BenchmarkingSetup, RawOrigin> for Self::SetIdentity => , RawOrigin>>::instance(&SetIdentity, components), Self::SetSubs => , RawOrigin>>::instance(&SetSubs, components), Self::ClearIdentity => , RawOrigin>>::instance(&ClearIdentity, components), + Self::RequestJudgement => , RawOrigin>>::instance(&RequestJudgement, components), + Self::CancelRequest => , RawOrigin>>::instance(&CancelRequest, components), } } } @@ -266,6 +337,8 @@ impl Benchmarking for Module { b"set_identity" => SelectedBenchmark::SetIdentity, b"set_subs" => SelectedBenchmark::SetSubs, b"clear_identity" => SelectedBenchmark::ClearIdentity, + b"request_judgement" => SelectedBenchmark::RequestJudgement, + b"cancel_request" => SelectedBenchmark::CancelRequest, _ => return Err("Could not find extrinsic."), }; From 833c37776aa1e42c16759f60d39e278faa998d4e Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sat, 8 Feb 2020 02:34:05 +0100 Subject: [PATCH 40/50] Add final benchmarks --- frame/identity/src/benchmarking.rs | 222 ++++++++++++++++++++++++++++- 1 file changed, 221 insertions(+), 1 deletion(-) diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 4d8695247473c..bab613162577c 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -206,6 +206,7 @@ impl BenchmarkingSetup, RawOrigin> for // The target user let caller = account::("caller", 0); let caller_origin: ::Origin = RawOrigin::Signed(caller.clone()).into(); + let caller_lookup: ::Source = T::Lookup::unlookup(caller.clone()); let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); // Register r registrars @@ -221,6 +222,17 @@ impl BenchmarkingSetup, RawOrigin> for let s = components.iter().find(|&c| c.0 == BenchmarkParameter::S).unwrap().1; let _ = benchmarking::add_sub_accounts::(caller.clone(), s)?; + // User requests judgement from all the registrars, and they approve + for i in 0..r { + Identity::::request_judgement(caller_origin.clone(), i, 10.into())?; + Identity::::provide_judgement( + RawOrigin::Signed(account::("registrar", i)).into(), + i, + caller_lookup.clone(), + Judgement::Reasonable + )?; + } + // Return the `clear_identity` call Ok((crate::Call::::clear_identity(), RawOrigin::Signed(caller))) } @@ -294,6 +306,194 @@ impl BenchmarkingSetup, RawOrigin> for } } +struct SetFee; +impl BenchmarkingSetup, RawOrigin> for SetFee { + + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { + vec![ + // Registrar Count + (BenchmarkParameter::R, 1, MAX_REGISTRARS), + ] + } + + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + { + // The target user + let caller = account::("caller", 0); + let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + + // Register r registrars + let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; + benchmarking::add_registrars::(r)?; + + // Add caller as registrar + Identity::::add_registrar(RawOrigin::Root.into(), caller.clone())?; + + // Return `set_fee` call + Ok((crate::Call::::set_fee(r, 10.into()), RawOrigin::Signed(caller))) + } +} + +struct SetAccountId; +impl BenchmarkingSetup, RawOrigin> for SetAccountId { + + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { + vec![ + // Registrar Count + (BenchmarkParameter::R, 1, MAX_REGISTRARS), + ] + } + + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + { + // The target user + let caller = account::("caller", 0); + let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + + // Register r registrars + let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; + benchmarking::add_registrars::(r)?; + + // Add caller as registrar + Identity::::add_registrar(RawOrigin::Root.into(), caller.clone())?; + + // Return `set_account_id` call + Ok((crate::Call::::set_account_id(r, account::("new", 0)), RawOrigin::Signed(caller))) + } +} + +struct SetFields; +impl BenchmarkingSetup, RawOrigin> for SetFields { + + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { + vec![ + // Registrar Count + (BenchmarkParameter::R, 1, MAX_REGISTRARS), + ] + } + + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + { + // The target user + let caller = account::("caller", 0); + let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + + // Register r registrars + let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; + benchmarking::add_registrars::(r)?; + + // Add caller as registrar + Identity::::add_registrar(RawOrigin::Root.into(), caller.clone())?; + + let fields = IdentityFields( + IdentityField::Display | IdentityField::Legal | IdentityField::Web | IdentityField::Riot + | IdentityField::Email | IdentityField::PgpFingerprint | IdentityField::Image | IdentityField::Twitter + ); + + // Return `set_account_id` call + Ok((crate::Call::::set_fields(r, fields), RawOrigin::Signed(caller))) + } +} + +struct ProvideJudgement; +impl BenchmarkingSetup, RawOrigin> for ProvideJudgement { + + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { + vec![ + // Registrar Count + (BenchmarkParameter::R, 1, MAX_REGISTRARS), + // Additional Field Count + (BenchmarkParameter::X, 1, T::MaxAdditionalFields::get()), + ] + } + + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + { + // Add r registrars + let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; + benchmarking::add_registrars::(r)?; + + // The user + let user = account::("user", r); + let user_origin: ::Origin = RawOrigin::Signed(user.clone()).into(); + let user_lookup: ::Source = T::Lookup::unlookup(user.clone()); + let _ = T::Currency::make_free_balance_be(&user, BalanceOf::::max_value()); + + // Create their main identity with x additional fields + let x = components.iter().find(|&c| c.0 == BenchmarkParameter::X).unwrap().1; + let info = benchmarking::create_identity_info::(x); + Identity::::set_identity(user_origin.clone(), info)?; + + // The caller registrar + let caller = account::("caller", r); + let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + + // Add caller as registrar + Identity::::add_registrar(RawOrigin::Root.into(), caller.clone())?; + + // User requests judgement from caller registrar + Identity::::request_judgement(user_origin.clone(), r, 10.into())?; + + // Return `provide_judgement` call + Ok((crate::Call::::provide_judgement( + r, + user_lookup.clone(), + Judgement::Reasonable + ), RawOrigin::Signed(caller))) + } +} + +struct KillIdentity; +impl BenchmarkingSetup, RawOrigin> for KillIdentity { + + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { + vec![ + // Registrar Count + (BenchmarkParameter::R, 1, MAX_REGISTRARS), + // Subs Count + (BenchmarkParameter::S, 1, T::MaxSubAccounts::get()), + // Additional Field Count + (BenchmarkParameter::X, 1, T::MaxAdditionalFields::get()), + ] + } + + fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + { + // The target user + let caller = account::("caller", 0); + let caller_origin: ::Origin = RawOrigin::Signed(caller.clone()).into(); + let caller_lookup: ::Source = T::Lookup::unlookup(caller.clone()); + let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); + + // Register r registrars + let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; + benchmarking::add_registrars::(r)?; + + // Create their main identity with x additional fields + let x = components.iter().find(|&c| c.0 == BenchmarkParameter::X).unwrap().1; + let info = benchmarking::create_identity_info::(x); + Identity::::set_identity(caller_origin.clone(), info)?; + + // Give them s many sub accounts + let s = components.iter().find(|&c| c.0 == BenchmarkParameter::S).unwrap().1; + let _ = benchmarking::add_sub_accounts::(caller.clone(), s)?; + + // User requests judgement from all the registrars, and they approve + for i in 0..r { + Identity::::request_judgement(caller_origin.clone(), i, 10.into())?; + Identity::::provide_judgement( + RawOrigin::Signed(account::("registrar", i)).into(), + i, + caller_lookup.clone(), + Judgement::Reasonable + )?; + } + + // Return the `kill_identity` call + Ok((crate::Call::::kill_identity(caller_lookup), RawOrigin::Root)) + } +} + enum SelectedBenchmark { AddRegistrar, SetIdentity, @@ -301,6 +501,11 @@ enum SelectedBenchmark { ClearIdentity, RequestJudgement, CancelRequest, + SetFee, + SetAccountId, + SetFields, + ProvideJudgement, + KillIdentity, } impl BenchmarkingSetup, RawOrigin> for SelectedBenchmark { @@ -313,6 +518,11 @@ impl BenchmarkingSetup, RawOrigin> for Self::ClearIdentity => , RawOrigin>>::components(&ClearIdentity), Self::RequestJudgement => , RawOrigin>>::components(&RequestJudgement), Self::CancelRequest => , RawOrigin>>::components(&CancelRequest), + Self::SetFee => , RawOrigin>>::components(&SetFee), + Self::SetAccountId => , RawOrigin>>::components(&SetAccountId), + Self::SetFields => , RawOrigin>>::components(&SetFields), + Self::ProvideJudgement => , RawOrigin>>::components(&ProvideJudgement), + Self::KillIdentity => , RawOrigin>>::components(&KillIdentity), } } @@ -325,6 +535,11 @@ impl BenchmarkingSetup, RawOrigin> for Self::ClearIdentity => , RawOrigin>>::instance(&ClearIdentity, components), Self::RequestJudgement => , RawOrigin>>::instance(&RequestJudgement, components), Self::CancelRequest => , RawOrigin>>::instance(&CancelRequest, components), + Self::SetFee => , RawOrigin>>::instance(&SetFee, components), + Self::SetAccountId => , RawOrigin>>::instance(&SetAccountId, components), + Self::SetFields => , RawOrigin>>::instance(&SetFields, components), + Self::ProvideJudgement => , RawOrigin>>::instance(&ProvideJudgement, components), + Self::KillIdentity => , RawOrigin>>::instance(&KillIdentity, components), } } } @@ -339,6 +554,11 @@ impl Benchmarking for Module { b"clear_identity" => SelectedBenchmark::ClearIdentity, b"request_judgement" => SelectedBenchmark::RequestJudgement, b"cancel_request" => SelectedBenchmark::CancelRequest, + b"set_fee" => SelectedBenchmark::SetFee, + b"set_account_id" => SelectedBenchmark::SetAccountId, + b"set_fields" => SelectedBenchmark::SetFields, + b"provide_judgement" => SelectedBenchmark::ProvideJudgement, + b"kill_identity" => SelectedBenchmark::KillIdentity, _ => return Err("Could not find extrinsic."), }; @@ -370,7 +590,7 @@ impl Benchmarking for Module { println!("STEP {:?} REPEAT {:?}", s, r); } let (call, caller) = , RawOrigin>>::instance(&selected_benchmark, &c)?; - //sp_io::benchmarking::commit_db(); + sp_io::benchmarking::commit_db(); let start = sp_io::benchmarking::current_time(); call.dispatch(caller.into())?; let finish = sp_io::benchmarking::current_time(); From 3e27b428e6e9b81f123093872d1a8e9f63828bd8 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sat, 8 Feb 2020 15:08:30 +0100 Subject: [PATCH 41/50] Fix CSV output --- client/service/src/chain_ops.rs | 4 ++-- frame/identity/src/benchmarking.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/service/src/chain_ops.rs b/client/service/src/chain_ops.rs index 1ba6c52c07a04..110497d5b60b6 100644 --- a/client/service/src/chain_ops.rs +++ b/client/service/src/chain_ops.rs @@ -85,12 +85,12 @@ pub fn benchmark_runtime ( println!("Pallet: {:?}, Extrinsic: {:?}, Steps: {:?}, Repeat: {:?}", pallet, extrinsic, steps, repeat); // Print the table header results[0].0.iter().for_each(|param| print!("{:?},", param.0)); - print!("time,\n"); + print!("time\n"); // Print the values results.iter().for_each(|result| { let parameters = &result.0; parameters.iter().for_each(|param| print!("{:?},", param.1)); - print!("{:?},\n", result.1); + print!("{:?}\n", result.1); }); info!("Done."); } else { diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index bab613162577c..df97ae159e3ed 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -25,7 +25,7 @@ use sp_runtime::traits::{Bounded, Benchmarking, BenchmarkingSetup, Dispatchable} use crate::Module as Identity; -const MAX_REGISTRARS: u32 = 16; +const MAX_REGISTRARS: u32 = 50; // Support Functions fn account(name: &'static str, index: u32) -> T::AccountId { From 34838f6051c151c8abce32fdd1c9f6d379d53afb Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sat, 8 Feb 2020 17:02:24 +0100 Subject: [PATCH 42/50] Start cleaning up for PR --- Cargo.lock | 17 --- Cargo.toml | 1 - bin/node/runtime/Cargo.toml | 1 - bin/node/runtime/src/lib.rs | 6 - frame/benchmark/Cargo.toml | 32 ----- frame/benchmark/src/benchmarking.rs | 180 ---------------------------- frame/benchmark/src/lib.rs | 91 -------------- frame/identity/src/benchmarking.rs | 34 +++++- primitives/runtime/src/traits.rs | 4 +- 9 files changed, 31 insertions(+), 335 deletions(-) delete mode 100644 frame/benchmark/Cargo.toml delete mode 100644 frame/benchmark/src/benchmarking.rs delete mode 100644 frame/benchmark/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 7f1598e76134e..a03c0e8c7864e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3503,7 +3503,6 @@ dependencies = [ "pallet-authorship", "pallet-babe", "pallet-balances", - "pallet-benchmark", "pallet-collective", "pallet-contracts", "pallet-contracts-primitives", @@ -3938,22 +3937,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-benchmark" -version = "2.0.0" -dependencies = [ - "enumflags2", - "frame-support", - "frame-system", - "pallet-balances", - "parity-scale-codec", - "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-collective" version = "2.0.0" diff --git a/Cargo.toml b/Cargo.toml index 524170362a6ad..47e3fe3f0efce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,7 +60,6 @@ members = [ "frame/authorship", "frame/babe", "frame/balances", - "frame/benchmark", "frame/collective", "frame/contracts", "frame/contracts/rpc", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 937ff393365d5..3f8e8b6731477 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -40,7 +40,6 @@ pallet-authority-discovery = { version = "2.0.0", default-features = false, path pallet-authorship = { version = "2.0.0", default-features = false, path = "../../../frame/authorship" } pallet-babe = { version = "2.0.0", default-features = false, path = "../../../frame/babe" } pallet-balances = { version = "2.0.0", default-features = false, path = "../../../frame/balances" } -pallet-benchmark = { version = "2.0.0", default-features = false, path = "../../../frame/benchmark" } pallet-collective = { version = "2.0.0", default-features = false, path = "../../../frame/collective" } pallet-contracts = { version = "2.0.0", default-features = false, path = "../../../frame/contracts" } pallet-contracts-primitives = { version = "2.0.0", default-features = false, path = "../../../frame/contracts/common/" } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index e044e6dd77213..ee872b3bb67e6 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -504,10 +504,6 @@ impl pallet_identity::Trait for Runtime { type ForceOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; } -impl pallet_benchmark::Trait for Runtime { - type Event = Event; -} - impl frame_system::offchain::CreateTransaction for Runtime { type Public = ::Signer; type Signature = Signature; @@ -631,7 +627,6 @@ construct_runtime!( Society: pallet_society::{Module, Call, Storage, Event, Config}, Recovery: pallet_recovery::{Module, Call, Storage, Event}, Vesting: pallet_vesting::{Module, Call, Storage, Event, Config}, - Bench: pallet_benchmark::{Module, Call, Storage, Event}, } ); @@ -816,7 +811,6 @@ impl_runtime_apis! { fn dispatch_benchmark(module: Vec, extrinsic: Vec, steps: u32, repeat: u32) -> Option> { match module.as_slice() { b"pallet-identity" | b"identity" => Identity::run_benchmark(extrinsic, steps, repeat).ok(), - b"pallet-benchmark" | b"benchmark" => Bench::run_benchmark(extrinsic, steps, repeat).ok(), _ => return None, } } diff --git a/frame/benchmark/Cargo.toml b/frame/benchmark/Cargo.toml deleted file mode 100644 index 2c6bbe0f3b3b0..0000000000000 --- a/frame/benchmark/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "pallet-benchmark" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0" - -[dependencies] -serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -enumflags2 = { version = "0.6.2" } -sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0", default-features = false, path = "../support" } -frame-system = { version = "2.0.0", default-features = false, path = "../system" } - -[dev-dependencies] -sp-core = { version = "2.0.0", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0", path = "../balances" } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "sp-std/std", - "sp-io/std", - "sp-runtime/std", - "frame-support/std", - "frame-system/std", -] diff --git a/frame/benchmark/src/benchmarking.rs b/frame/benchmark/src/benchmarking.rs deleted file mode 100644 index 35d2669632b85..0000000000000 --- a/frame/benchmark/src/benchmarking.rs +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Identity pallet benchmarking. - -use super::*; - -use codec::{Encode, Decode}; -use frame_system::RawOrigin; -use sp_io::hashing::blake2_256; -use sp_runtime::{BenchmarkResults, BenchmarkParameter}; -use sp_runtime::traits::{Benchmarking, BenchmarkingSetup, Dispatchable}; -use sp_std::prelude::*; - -use crate::Module as Benchmark; - -fn account(index: u32) -> T::AccountId { - let entropy = (b"benchmark", index).using_encoded(blake2_256); - T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() -} - -// Custom implementation to handle benchmarking of calling a host function. -fn time_host(steps: u32, repeat: u32) -> Result, &'static str> { - let mut results: Vec = Vec::new(); - - for _ in 0..steps { - let start = sp_io::benchmarking::current_time(); - for _ in 0..repeat { - let _ = sp_io::benchmarking::current_time(); - } - let finish = sp_io::benchmarking::current_time(); - let elapsed = finish - start; - - results.push((vec![(BenchmarkParameter::L, repeat)], elapsed)); - } - - return Ok(results); -} - -struct AddMemberList; -impl BenchmarkingSetup, RawOrigin> for AddMemberList { - - fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { - vec![ - // Registrar Count - (BenchmarkParameter::M, 1, 1000), - ] - } - - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> - { - // Add r registrars - let r = components.iter().find(|&c| c.0 == BenchmarkParameter::M).unwrap(); - for i in 0..r.1 { - let _ = Benchmark::::add_member_list(RawOrigin::Signed(account::(i)).into()); - } - - sp_std::if_std!{ - println!("# Users {:?}", MyList::::get().len()); - } - - // Return the `add_registrar` r + 1 call - Ok((crate::Call::::add_member_list(), RawOrigin::Signed(account::(r.1 + 1)))) - } -} - -struct AddMemberListAppend; -impl BenchmarkingSetup, RawOrigin> for AddMemberListAppend { - - fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { - vec![ - // Registrar Count - (BenchmarkParameter::M, 1, 1000), - ] - } - - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> - { - // Add r registrars - let r = components.iter().find(|&c| c.0 == BenchmarkParameter::M).unwrap(); - for i in 0..r.1 { - let _ = Benchmark::::add_member_list_append(RawOrigin::Signed(account::(i)).into()); - } - - sp_std::if_std!{ - println!("# Users {:?}", MyList::::get().len()); - } - - // Return the `add_registrar` r + 1 call - Ok((crate::Call::::add_member_list_append(), RawOrigin::Signed(account::(r.1 + 1)))) - } -} - -enum SelectedBenchmark { - AddMemberList, - AddMemberListAppend, -} - -impl BenchmarkingSetup, RawOrigin> for SelectedBenchmark { - fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> - { - match self { - Self::AddMemberList => , RawOrigin>>::components(&AddMemberList), - Self::AddMemberListAppend => , RawOrigin>>::components(&AddMemberListAppend), - } - } - - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> - { - match self { - Self::AddMemberList => , RawOrigin>>::instance(&AddMemberList, components), - Self::AddMemberListAppend => , RawOrigin>>::instance(&AddMemberListAppend, components), - } - } -} - -impl Benchmarking for Module { - fn run_benchmark(extrinsic: Vec, steps: u32, repeat: u32) -> Result, &'static str> { - - let selected_benchmark = match extrinsic.as_slice() { - b"time_host" => return benchmarking::time_host(steps, repeat), - b"add_member_list" => SelectedBenchmark::AddMemberList, - b"add_member_list_append" => SelectedBenchmark::AddMemberListAppend, - _ => return Err("Extrinsic not found."), - }; - - // Warm up the DB? - sp_io::benchmarking::commit_db(); - sp_io::benchmarking::wipe_db(); - - // first one is set_identity. - let components = , RawOrigin>>::components(&selected_benchmark); - // results go here - let mut results: Vec = Vec::new(); - // Select the component we will be benchmarking. Each component will be benchmarked. - for (name, low, high) in components.iter() { - // Create up to `STEPS` steps for that component between high and low. - let step_size = ((high - low) / steps).max(1); - let num_of_steps = (high - low) / step_size; - for s in 0..num_of_steps { - // This is the value we will be testing for component `name` - let component_value = low + step_size * s; - - // Select the mid value for all the other components. - let c: Vec<(BenchmarkParameter, u32)> = components.iter() - .map(|(n, l, h)| - (*n, if n == name { component_value } else { (h - l) / 2 + l }) - ).collect(); - - for r in 0..repeat { - sp_std::if_std!{ - println!("STEP {:?} REPEAT {:?}", s, r); - } - let (call, caller) = , RawOrigin>>::instance(&selected_benchmark, &c)?; - sp_io::benchmarking::commit_db(); - let start = sp_io::benchmarking::current_time(); - assert_eq!(call.dispatch(caller.into()), Ok(())); - let finish = sp_io::benchmarking::current_time(); - let elapsed = finish - start; - sp_io::benchmarking::wipe_db(); - results.push((c.clone(), elapsed)); - } - } - } - return Ok(results); - } -} diff --git a/frame/benchmark/src/lib.rs b/frame/benchmark/src/lib.rs deleted file mode 100644 index 1be8ac1c791f5..0000000000000 --- a/frame/benchmark/src/lib.rs +++ /dev/null @@ -1,91 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -/// A runtime module template with necessary imports - -/// Feel free to remove or edit this file as needed. -/// If you change the name of this file, make sure to update its references in runtime/src/lib.rs -/// If you remove this file, you can remove those references - -/// For more guidance on Substrate modules, see the example module -/// https://github.com/paritytech/substrate/blob/master/frame/example/src/lib.rs - -use frame_support::{decl_module, decl_storage, decl_event, decl_error}; -use frame_system::{self as system, ensure_signed}; -use sp_std::prelude::Vec; - -pub mod benchmarking; - -/// The pallet's configuration trait. -pub trait Trait: system::Trait { - // Add other types and constants required to configure this pallet. - - /// The overarching event type. - type Event: From> + Into<::Event>; -} - -// This pallet's storage items. -decl_storage! { - trait Store for Module as Benchmark { - MyList: Vec; - MyMap: map hasher(blake2_256) T::AccountId => bool; - } -} - -// The pallet's events -decl_event!( - pub enum Event where AccountId = ::AccountId { - /// Just a dummy event. - /// Event `Something` is declared with a parameter of the type `u32` and `AccountId` - /// To emit this event, we call the deposit funtion, from our runtime funtions - Dummy(u32, AccountId), - } -); - -// The pallet's errors -decl_error! { - pub enum Error for Module { - /// Value was None - NoneValue, - /// Value reached maximum and cannot be incremented further - StorageOverflow, - } -} - -// The pallet's dispatchable functions. -decl_module! { - /// The module declaration. - pub struct Module for enum Call where origin: T::Origin { - // Initializing errors - // this includes information about your errors in the node's metadata. - // it is needed only if you are using errors in your pallet - type Error = Error; - - // Initializing events - // this is needed only if you are using events in your pallet - fn deposit_event() = default; - - - pub fn add_member_list(origin) { - // Check it was signed and get the signer. - let who = ensure_signed(origin)?; - // Push user to the list. - MyList::::mutate(|x| x.push(who)); - } - - pub fn add_member_list_append(origin) { - // Check it was signed and get the signer. - let who = ensure_signed(origin)?; - // Append user to the list. - MyList::::append(&[who])?; - } - - pub fn check_member_list(origin) { - // Check it was signed and get the signer. - let who = ensure_signed(origin)?; - - // Add user to the list. - MyList::::mutate(|x| x.push(who)); - } - - } -} diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index df97ae159e3ed..98fe146a71ca3 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -25,6 +25,7 @@ use sp_runtime::traits::{Bounded, Benchmarking, BenchmarkingSetup, Dispatchable} use crate::Module as Identity; +// The maximum number of identity registrars we will test. const MAX_REGISTRARS: u32 = 50; // Support Functions @@ -33,6 +34,7 @@ fn account(name: &'static str, index: u32) -> T::AccountId { T::AccountId::decode(&mut &entropy[..]).unwrap_or_default() } +// Adds `r` registrars to the Identity Pallet. These registrars will have set fees and fields. fn add_registrars(r: u32) -> Result<(), &'static str> { for i in 0..r { let _ = T::Currency::make_free_balance_be(&account::("registrar", i), BalanceOf::::max_value()); @@ -49,6 +51,8 @@ fn add_registrars(r: u32) -> Result<(), &'static str> { Ok(()) } +// Adds `s` sub-accounts to the identity of `who`. Each wil have 32 bytes of raw data added to it. +// This additionally returns the vector of sub-accounts to it can be modified if needed. fn add_sub_accounts(who: T::AccountId, s: u32) -> Result, &'static str> { let mut subs = Vec::new(); let who_origin = RawOrigin::Signed(who.clone()); @@ -63,6 +67,8 @@ fn add_sub_accounts(who: T::AccountId, s: u32) -> Result(num_fields: u32) -> IdentityInfo { let data = Data::Raw(vec![0; 32]); @@ -81,6 +87,7 @@ fn create_identity_info(num_fields: u32) -> IdentityInfo { return info } +// Benchmark `add_registrar` extrinsic. struct AddRegistrar; impl BenchmarkingSetup, RawOrigin> for AddRegistrar { @@ -102,6 +109,7 @@ impl BenchmarkingSetup, RawOrigin> for } } +// Benchmark `set_identity` extrinsic. struct SetIdentity; impl BenchmarkingSetup, RawOrigin> for SetIdentity { @@ -151,6 +159,7 @@ impl BenchmarkingSetup, RawOrigin> for } } +// Benchmark `set_subs` extrinsic. struct SetSubs; impl BenchmarkingSetup, RawOrigin> for SetSubs { @@ -187,6 +196,7 @@ impl BenchmarkingSetup, RawOrigin> for } } +// Benchmark `clear_identity` extrinsic. struct ClearIdentity; impl BenchmarkingSetup, RawOrigin> for ClearIdentity { @@ -238,6 +248,7 @@ impl BenchmarkingSetup, RawOrigin> for } } +// Benchmark `request_judgement` extrinsic. struct RequestJudgement; impl BenchmarkingSetup, RawOrigin> for RequestJudgement { @@ -271,6 +282,7 @@ impl BenchmarkingSetup, RawOrigin> for } } +// Benchmark `cancel_request` extrinsic. struct CancelRequest; impl BenchmarkingSetup, RawOrigin> for CancelRequest { @@ -306,6 +318,7 @@ impl BenchmarkingSetup, RawOrigin> for } } +// Benchmark `set_fee` extrinsic. struct SetFee; impl BenchmarkingSetup, RawOrigin> for SetFee { @@ -334,6 +347,7 @@ impl BenchmarkingSetup, RawOrigin> for } } +// Benchmark `set_account_id` extrinsic. struct SetAccountId; impl BenchmarkingSetup, RawOrigin> for SetAccountId { @@ -362,6 +376,7 @@ impl BenchmarkingSetup, RawOrigin> for } } +// Benchmark `set_fields` extrinsic. struct SetFields; impl BenchmarkingSetup, RawOrigin> for SetFields { @@ -395,6 +410,7 @@ impl BenchmarkingSetup, RawOrigin> for } } +// Benchmark `provide_judgement` extrinsic. struct ProvideJudgement; impl BenchmarkingSetup, RawOrigin> for ProvideJudgement { @@ -443,6 +459,7 @@ impl BenchmarkingSetup, RawOrigin> for } } +// Benchmark `kill_identity` extrinsic. struct KillIdentity; impl BenchmarkingSetup, RawOrigin> for KillIdentity { @@ -494,6 +511,7 @@ impl BenchmarkingSetup, RawOrigin> for } } +// The list of available benchmarks for this pallet. enum SelectedBenchmark { AddRegistrar, SetIdentity, @@ -508,6 +526,8 @@ enum SelectedBenchmark { KillIdentity, } +// Allow us to select a benchmark from the list of available benchmarks. + impl BenchmarkingSetup, RawOrigin> for SelectedBenchmark { fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { @@ -547,6 +567,7 @@ impl BenchmarkingSetup, RawOrigin> for impl Benchmarking for Module { fn run_benchmark(extrinsic: Vec, steps: u32, repeat: u32) -> Result, &'static str> { + // Map the input to the selected benchmark. let selected_benchmark = match extrinsic.as_slice() { b"add_registrar" => SelectedBenchmark::AddRegistrar, b"set_identity" => SelectedBenchmark::SetIdentity, @@ -562,7 +583,7 @@ impl Benchmarking for Module { _ => return Err("Could not find extrinsic."), }; - // Warm up the DB? + // Warm up the DB sp_io::benchmarking::commit_db(); sp_io::benchmarking::wipe_db(); @@ -585,18 +606,21 @@ impl Benchmarking for Module { (*n, if n == name { component_value } else { (h - l) / 2 + l }) ).collect(); + // Run the benchmark `repeat` times. for r in 0..repeat { - sp_std::if_std!{ - println!("STEP {:?} REPEAT {:?}", s, r); - } + // Set up the externalities environment for the setup we want to benchmark. let (call, caller) = , RawOrigin>>::instance(&selected_benchmark, &c)?; + // Commit the externalities to the database, flushing the DB cache. + // This will enable worst case scenario for reading from the database. sp_io::benchmarking::commit_db(); + // Run the benchmark. let start = sp_io::benchmarking::current_time(); call.dispatch(caller.into())?; let finish = sp_io::benchmarking::current_time(); let elapsed = finish - start; - sp_io::benchmarking::wipe_db(); results.push((c.clone(), elapsed)); + // Wipe the DB back to the genesis state. + sp_io::benchmarking::wipe_db(); } } } diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index df0fac22f26da..05e59de0d9d32 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1329,9 +1329,9 @@ pub trait BlockIdTo { ) -> Result>, Self::Error>; } -/// The module benchmarking trait. +/// The pallet benchmarking trait. pub trait Benchmarking { - /// Run the benchmarks for this module. + /// Run the benchmarks for this pallet. fn run_benchmark(extrinsic: Vec, steps: u32, repeat: u32) -> Result, &'static str>; } From 93422d48119c2580f60dbf5d991d4f54ce547ee5 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sat, 8 Feb 2020 17:32:06 +0100 Subject: [PATCH 43/50] Bump numbers in `wasmtime` integration tests. --- client/executor/src/integration_tests/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 3f3d9f69e13dc..2ac67215a82f0 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -88,7 +88,7 @@ fn call_not_existing_function(wasm_method: WasmExecutionMethod) { #[cfg(feature = "wasmtime")] WasmExecutionMethod::Compiled => assert_eq!( &format!("{:?}", e), - "Other(\"call to undefined external function with index 68\")" + "Other(\"call to undefined external function with index 71\")" ), } } @@ -117,7 +117,7 @@ fn call_yet_another_not_existing_function(wasm_method: WasmExecutionMethod) { #[cfg(feature = "wasmtime")] WasmExecutionMethod::Compiled => assert_eq!( &format!("{:?}", e), - "Other(\"call to undefined external function with index 69\")" + "Other(\"call to undefined external function with index 72\")" ), } } From f73ca4a66751665b3465992a68e7e37dec6810f0 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sat, 8 Feb 2020 17:55:39 +0100 Subject: [PATCH 44/50] More docs --- primitives/runtime/src/traits.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 05e59de0d9d32..e95fc073eb445 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -1332,6 +1332,11 @@ pub trait BlockIdTo { /// The pallet benchmarking trait. pub trait Benchmarking { /// Run the benchmarks for this pallet. + /// + /// Parameters + /// - `extrinsic`: The name of extrinsic function you want to benchmark encoded as bytes. + /// - `steps`: The number of sample points you want to take across the range of parameters. + /// - `repeat`: The number of times you want to repeat a benchmark. fn run_benchmark(extrinsic: Vec, steps: u32, repeat: u32) -> Result, &'static str>; } From eecaac004efac59fbb75113302ad97a1c1808b25 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sat, 8 Feb 2020 18:31:32 +0100 Subject: [PATCH 45/50] Add rockdb feature to bench --- client/db/src/bench.rs | 2 +- client/db/src/lib.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/client/db/src/bench.rs b/client/db/src/bench.rs index 592e8623b4fad..6b73580caf9e9 100644 --- a/client/db/src/bench.rs +++ b/client/db/src/bench.rs @@ -96,7 +96,7 @@ impl BenchmarkingState { let db_config = DatabaseConfig::with_columns(1); let path = self.path.to_str() .ok_or_else(|| String::from("Invalid database path"))?; - let db = Arc::new(Database::open(&db_config, &path).map_err(|e| format!("Error opening dadabase: {:?}", e))?); + let db = Arc::new(Database::open(&db_config, &path).map_err(|e| format!("Error opening database: {:?}", e))?); self.db.set(Some(db.clone())); let storage_db = Arc::new(StorageDb:: { db, _block: Default::default() }); *self.state.borrow_mut() = Some(DbState::::new(storage_db, self.root.get())); diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index 789cfc7f8d885..09668cf45ecdf 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -28,6 +28,8 @@ pub mod light; pub mod offchain; + +#[cfg(feature = "kvdb-rocksdb")] pub mod bench; mod children; @@ -80,6 +82,8 @@ use crate::storage_cache::{CachingState, SharedCache, new_shared_cache}; use crate::stats::StateUsageStats; use log::{trace, debug, warn}; pub use sc_state_db::PruningMode; + +#[cfg(feature = "kvdb-rocksdb")] pub use bench::BenchmarkingState; #[cfg(feature = "test-helpers")] From 62439115aee50f8db1ff274b97bc43172cd02a69 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sun, 9 Feb 2020 00:25:22 +0100 Subject: [PATCH 46/50] Fix formatting issues --- bin/node/runtime/src/lib.rs | 9 ++- client/cli/src/params.rs | 6 +- client/db/src/bench.rs | 16 ++-- client/db/src/lib.rs | 1 - client/service/src/chain_ops.rs | 1 + frame/identity/src/benchmarking.rs | 51 ++++++------ primitives/core/src/offchain/mod.rs | 2 +- primitives/externalities/src/lib.rs | 1 - primitives/io/src/lib.rs | 4 +- primitives/runtime/src/lib.rs | 3 +- .../state-machine/src/overlayed_changes.rs | 78 +++++++++---------- 11 files changed, 87 insertions(+), 85 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index ee872b3bb67e6..b4f33243e7f36 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -82,7 +82,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. spec_version: 214, - impl_version: 1, + impl_version: 2, apis: RUNTIME_API_VERSIONS, }; @@ -808,7 +808,9 @@ impl_runtime_apis! { } impl crate::Benchmark for Runtime { - fn dispatch_benchmark(module: Vec, extrinsic: Vec, steps: u32, repeat: u32) -> Option> { + fn dispatch_benchmark(module: Vec, extrinsic: Vec, steps: u32, repeat: u32) + -> Option> + { match module.as_slice() { b"pallet-identity" | b"identity" => Identity::run_benchmark(extrinsic, steps, repeat).ok(), _ => return None, @@ -820,7 +822,8 @@ impl_runtime_apis! { sp_api::decl_runtime_apis! { pub trait Benchmark { - fn dispatch_benchmark(module: Vec, extrinsic: Vec, steps: u32, repeat: u32) -> Option>; + fn dispatch_benchmark(module: Vec, extrinsic: Vec, steps: u32, repeat: u32) + -> Option>; } } diff --git a/client/cli/src/params.rs b/client/cli/src/params.rs index c70bfe0a7f717..0881247b07d06 100644 --- a/client/cli/src/params.rs +++ b/client/cli/src/params.rs @@ -845,10 +845,10 @@ pub struct PurgeChainCmd { pub shared_params: SharedParams, } -/// The `benchmark` command used to benchmark FRAME pallets. +/// The `benchmark` command used to benchmark FRAME Pallets. #[derive(Debug, StructOpt, Clone)] pub struct BenchmarkCmd { - /// Select a FRAME pallet to benchmark. + /// Select a FRAME Pallet to benchmark. #[structopt(short, long)] pub pallet: String, @@ -856,7 +856,7 @@ pub struct BenchmarkCmd { #[structopt(short, long)] pub extrinsic: String, - /// Select how many steps of the parameters should we test. + /// Select how many samples we should take across the variable components. #[structopt(short, long, default_value = "1")] pub steps: u32, diff --git a/client/db/src/bench.rs b/client/db/src/bench.rs index 6b73580caf9e9..c04c193c8c216 100644 --- a/client/db/src/bench.rs +++ b/client/db/src/bench.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -208,9 +208,8 @@ impl StateBackend> for BenchmarkingState { } } - fn storage_root(&self, delta: I) -> (B::Hash, Self::Transaction) - where - I: IntoIterator, Option>)> + fn storage_root(&self, delta: I) -> (B::Hash, Self::Transaction) where + I: IntoIterator, Option>)> { self.state.borrow().as_ref().map_or(Default::default(), |s| s.storage_root(delta)) } @@ -220,9 +219,8 @@ impl StateBackend> for BenchmarkingState { storage_key: &[u8], child_info: ChildInfo, delta: I, - ) -> (B::Hash, bool, Self::Transaction) - where - I: IntoIterator, Option>)>, + ) -> (B::Hash, bool, Self::Transaction) where + I: IntoIterator, Option>)>, { self.state.borrow().as_ref().map_or(Default::default(), |s| s.child_storage_root(storage_key, child_info, delta)) } @@ -250,7 +248,9 @@ impl StateBackend> for BenchmarkingState { None } - fn commit(&self, storage_root: as Hasher>::Out, mut transaction: Self::Transaction) -> Result<(), Self::Error> { + fn commit(&self, storage_root: as Hasher>::Out, mut transaction: Self::Transaction) + -> Result<(), Self::Error> + { if let Some(db) = self.db.take() { let mut db_transaction = DBTransaction::new(); diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index 09668cf45ecdf..a1d6921440c2d 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -110,7 +110,6 @@ pub use kvdb; pub struct RefTrackingState { state: DbState, storage: Arc>, - parent_hash: Option, } diff --git a/client/service/src/chain_ops.rs b/client/service/src/chain_ops.rs index 110497d5b60b6..592d549cea51b 100644 --- a/client/service/src/chain_ops.rs +++ b/client/service/src/chain_ops.rs @@ -31,6 +31,7 @@ use sp_runtime::{ use sp_runtime::generic::{BlockId, SignedBlock}; use codec::{Decode, Encode, IoReader}; use sc_client::{Client, ExecutionStrategy, StateMachine, LocalCallExecutor}; + use sc_client_db::BenchmarkingState; use sp_consensus::import_queue::{IncomingBlock, Link, BlockImportError, BlockImportResult, ImportQueue}; use sp_consensus::BlockOrigin; diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 98fe146a71ca3..0a4a143ea9dd1 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -90,7 +90,6 @@ fn create_identity_info(num_fields: u32) -> IdentityInfo { // Benchmark `add_registrar` extrinsic. struct AddRegistrar; impl BenchmarkingSetup, RawOrigin> for AddRegistrar { - fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { vec![ // Registrar Count @@ -98,7 +97,8 @@ impl BenchmarkingSetup, RawOrigin> for ] } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + fn instance(&self, components: &[(BenchmarkParameter, u32)]) + -> Result<(crate::Call, RawOrigin), &'static str> { // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; @@ -112,7 +112,6 @@ impl BenchmarkingSetup, RawOrigin> for // Benchmark `set_identity` extrinsic. struct SetIdentity; impl BenchmarkingSetup, RawOrigin> for SetIdentity { - fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { vec![ // Registrar Count @@ -122,7 +121,8 @@ impl BenchmarkingSetup, RawOrigin> for ] } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + fn instance(&self, components: &[(BenchmarkParameter, u32)]) + -> Result<(crate::Call, RawOrigin), &'static str> { // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; @@ -162,7 +162,6 @@ impl BenchmarkingSetup, RawOrigin> for // Benchmark `set_subs` extrinsic. struct SetSubs; impl BenchmarkingSetup, RawOrigin> for SetSubs { - fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { vec![ // Subs Count @@ -170,7 +169,8 @@ impl BenchmarkingSetup, RawOrigin> for ] } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + fn instance(&self, components: &[(BenchmarkParameter, u32)]) + -> Result<(crate::Call, RawOrigin), &'static str> { // Generic data to be used. let data = Data::Raw(vec![0; 32]); @@ -199,7 +199,6 @@ impl BenchmarkingSetup, RawOrigin> for // Benchmark `clear_identity` extrinsic. struct ClearIdentity; impl BenchmarkingSetup, RawOrigin> for ClearIdentity { - fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { vec![ // Registrar Count @@ -211,7 +210,8 @@ impl BenchmarkingSetup, RawOrigin> for ] } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + fn instance(&self, components: &[(BenchmarkParameter, u32)]) + -> Result<(crate::Call, RawOrigin), &'static str> { // The target user let caller = account::("caller", 0); @@ -251,7 +251,6 @@ impl BenchmarkingSetup, RawOrigin> for // Benchmark `request_judgement` extrinsic. struct RequestJudgement; impl BenchmarkingSetup, RawOrigin> for RequestJudgement { - fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { vec![ // Registrar Count @@ -261,7 +260,8 @@ impl BenchmarkingSetup, RawOrigin> for ] } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + fn instance(&self, components: &[(BenchmarkParameter, u32)]) + -> Result<(crate::Call, RawOrigin), &'static str> { // The target user let caller = account::("caller", 0); @@ -285,7 +285,6 @@ impl BenchmarkingSetup, RawOrigin> for // Benchmark `cancel_request` extrinsic. struct CancelRequest; impl BenchmarkingSetup, RawOrigin> for CancelRequest { - fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { vec![ // Registrar Count @@ -295,7 +294,8 @@ impl BenchmarkingSetup, RawOrigin> for ] } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + fn instance(&self, components: &[(BenchmarkParameter, u32)]) + -> Result<(crate::Call, RawOrigin), &'static str> { // The target user let caller = account::("caller", 0); @@ -321,7 +321,6 @@ impl BenchmarkingSetup, RawOrigin> for // Benchmark `set_fee` extrinsic. struct SetFee; impl BenchmarkingSetup, RawOrigin> for SetFee { - fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { vec![ // Registrar Count @@ -329,7 +328,8 @@ impl BenchmarkingSetup, RawOrigin> for ] } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + fn instance(&self, components: &[(BenchmarkParameter, u32)]) + -> Result<(crate::Call, RawOrigin), &'static str> { // The target user let caller = account::("caller", 0); @@ -350,7 +350,6 @@ impl BenchmarkingSetup, RawOrigin> for // Benchmark `set_account_id` extrinsic. struct SetAccountId; impl BenchmarkingSetup, RawOrigin> for SetAccountId { - fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { vec![ // Registrar Count @@ -358,7 +357,8 @@ impl BenchmarkingSetup, RawOrigin> for ] } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + fn instance(&self, components: &[(BenchmarkParameter, u32)]) + -> Result<(crate::Call, RawOrigin), &'static str> { // The target user let caller = account::("caller", 0); @@ -379,7 +379,6 @@ impl BenchmarkingSetup, RawOrigin> for // Benchmark `set_fields` extrinsic. struct SetFields; impl BenchmarkingSetup, RawOrigin> for SetFields { - fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { vec![ // Registrar Count @@ -387,7 +386,8 @@ impl BenchmarkingSetup, RawOrigin> for ] } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + fn instance(&self, components: &[(BenchmarkParameter, u32)]) + -> Result<(crate::Call, RawOrigin), &'static str> { // The target user let caller = account::("caller", 0); @@ -423,7 +423,8 @@ impl BenchmarkingSetup, RawOrigin> for ] } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + fn instance(&self, components: &[(BenchmarkParameter, u32)]) + -> Result<(crate::Call, RawOrigin), &'static str> { // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; @@ -474,7 +475,8 @@ impl BenchmarkingSetup, RawOrigin> for ] } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + fn instance(&self, components: &[(BenchmarkParameter, u32)]) + -> Result<(crate::Call, RawOrigin), &'static str> { // The target user let caller = account::("caller", 0); @@ -529,8 +531,7 @@ enum SelectedBenchmark { // Allow us to select a benchmark from the list of available benchmarks. impl BenchmarkingSetup, RawOrigin> for SelectedBenchmark { - fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> - { + fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { match self { Self::AddRegistrar => , RawOrigin>>::components(&AddRegistrar), Self::SetIdentity => , RawOrigin>>::components(&SetIdentity), @@ -546,7 +547,8 @@ impl BenchmarkingSetup, RawOrigin> for } } - fn instance(&self, components: &[(BenchmarkParameter, u32)]) -> Result<(crate::Call, RawOrigin), &'static str> + fn instance(&self, components: &[(BenchmarkParameter, u32)]) + -> Result<(crate::Call, RawOrigin), &'static str> { match self { Self::AddRegistrar => , RawOrigin>>::instance(&AddRegistrar, components), @@ -566,7 +568,6 @@ impl BenchmarkingSetup, RawOrigin> for impl Benchmarking for Module { fn run_benchmark(extrinsic: Vec, steps: u32, repeat: u32) -> Result, &'static str> { - // Map the input to the selected benchmark. let selected_benchmark = match extrinsic.as_slice() { b"add_registrar" => SelectedBenchmark::AddRegistrar, @@ -607,7 +608,7 @@ impl Benchmarking for Module { ).collect(); // Run the benchmark `repeat` times. - for r in 0..repeat { + for _ in 0..repeat { // Set up the externalities environment for the setup we want to benchmark. let (call, caller) = , RawOrigin>>::instance(&selected_benchmark, &c)?; // Commit the externalities to the database, flushing the DB cache. diff --git a/primitives/core/src/offchain/mod.rs b/primitives/core/src/offchain/mod.rs index 9b1d249d3a0fa..425957a21f67e 100644 --- a/primitives/core/src/offchain/mod.rs +++ b/primitives/core/src/offchain/mod.rs @@ -207,7 +207,7 @@ impl OpaqueMultiaddr { /// Opaque timestamp type #[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Default, RuntimeDebug, PassByInner, Encode, Decode)] -pub struct Timestamp(pub u64); +pub struct Timestamp(u64); /// Duration type #[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Default, RuntimeDebug, PassByInner, Encode, Decode)] diff --git a/primitives/externalities/src/lib.rs b/primitives/externalities/src/lib.rs index e4687f9aea7ec..75193a4b9c392 100644 --- a/primitives/externalities/src/lib.rs +++ b/primitives/externalities/src/lib.rs @@ -203,7 +203,6 @@ pub trait Externalities: ExtensionStore { /// Returns the SCALE encoded hash. fn storage_changes_root(&mut self, parent: &[u8]) -> Result>, ()>; - fn wipe(&mut self) { unimplemented!() } diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index 90a72d0df8cf7..ea45b580ce27c 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -784,12 +784,12 @@ pub trait Benchmarking { .as_nanos() } - /// Reset state to empty. + /// Reset the trie database to the genesis state. fn wipe_db(&mut self) { self.wipe() } - /// Commit pending storage changes to the trie database. + /// Commit pending storage changes to the trie database and clear the database cache. fn commit_db(&mut self) { self.commit() } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index f8b2d5ed66d2f..f525f91ff6a50 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -693,7 +693,8 @@ pub enum BenchmarkParameter { } /// Results from running benchmarks on a FRAME pallet. -/// Contains duration of the function call in nanoseconds after executing the same function multiple times. +/// Contains duration of the function call in nanoseconds along with the benchmark parameters +/// used for that benchmark result. pub type BenchmarkResults = (Vec<(BenchmarkParameter, u32)>, u128); #[cfg(test)] diff --git a/primitives/state-machine/src/overlayed_changes.rs b/primitives/state-machine/src/overlayed_changes.rs index 9d5dfd6530412..37187e163fe1c 100644 --- a/primitives/state-machine/src/overlayed_changes.rs +++ b/primitives/state-machine/src/overlayed_changes.rs @@ -431,7 +431,7 @@ impl OverlayedChanges { fn drain_committed(&mut self) -> ( impl Iterator)>, impl Iterator)>, OwnedChildInfo))>, - ){ + ) { assert!(self.prospective.is_empty()); ( std::mem::replace(&mut self.committed.top, Default::default()) @@ -457,49 +457,47 @@ impl OverlayedChanges { } /// Drain all changes into a [`StorageChanges`] instance. Leave empty overlay in place. - pub fn drain_storage_changes< - B: Backend, H: Hasher, N: BlockNumber - >( - &mut self, - backend: &B, - changes_trie_state: Option<&ChangesTrieState>, - parent_hash: H::Out, - mut cache: &mut StorageTransactionCache, - ) -> Result, String> where H::Out: Ord + Encode + 'static { - // If the transaction does not exist, we generate it. - if cache.transaction.is_none() { - self.storage_root(backend, &mut cache); - } + pub fn drain_storage_changes, H: Hasher, N: BlockNumber>( + &mut self, + backend: &B, + changes_trie_state: Option<&ChangesTrieState>, + parent_hash: H::Out, + mut cache: &mut StorageTransactionCache, + ) -> Result, String> where H::Out: Ord + Encode + 'static { + // If the transaction does not exist, we generate it. + if cache.transaction.is_none() { + self.storage_root(backend, &mut cache); + } - let (transaction, transaction_storage_root) = cache.transaction.take() - .and_then(|t| cache.transaction_storage_root.take().map(|tr| (t, tr))) - .expect("Transaction was be generated as part of `storage_root`; qed"); - - // If the transaction does not exist, we generate it. - if cache.changes_trie_transaction.is_none() { - self.changes_trie_root( - backend, - changes_trie_state, - parent_hash, - false, - &mut cache, - ).map_err(|_| "Failed to generate changes trie transaction")?; - } + let (transaction, transaction_storage_root) = cache.transaction.take() + .and_then(|t| cache.transaction_storage_root.take().map(|tr| (t, tr))) + .expect("Transaction was be generated as part of `storage_root`; qed"); + + // If the transaction does not exist, we generate it. + if cache.changes_trie_transaction.is_none() { + self.changes_trie_root( + backend, + changes_trie_state, + parent_hash, + false, + &mut cache, + ).map_err(|_| "Failed to generate changes trie transaction")?; + } - let changes_trie_transaction = cache.changes_trie_transaction - .take() - .expect("Changes trie transaction was generated by `changes_trie_root`; qed"); + let changes_trie_transaction = cache.changes_trie_transaction + .take() + .expect("Changes trie transaction was generated by `changes_trie_root`; qed"); - let (main_storage_changes, child_storage_changes) = self.drain_committed(); + let (main_storage_changes, child_storage_changes) = self.drain_committed(); - Ok(StorageChanges { - main_storage_changes: main_storage_changes.collect(), - child_storage_changes: child_storage_changes.map(|(sk, it)| (sk, it.0.collect())).collect(), - transaction, - transaction_storage_root, - changes_trie_transaction, - }) - } + Ok(StorageChanges { + main_storage_changes: main_storage_changes.collect(), + child_storage_changes: child_storage_changes.map(|(sk, it)| (sk, it.0.collect())).collect(), + transaction, + transaction_storage_root, + changes_trie_transaction, + }) + } /// Inserts storage entry responsible for current extrinsic index. #[cfg(test)] From 09804e16833ed1b3ad5b1f114bd0d5d2474ec557 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sun, 9 Feb 2020 12:10:21 +0100 Subject: [PATCH 47/50] Add test feature to bench --- client/db/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index a1d6921440c2d..261e7e44a992d 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -29,7 +29,7 @@ pub mod light; pub mod offchain; -#[cfg(feature = "kvdb-rocksdb")] +#[cfg(feature = "kvdb-rocksdb", test)] pub mod bench; mod children; @@ -83,7 +83,7 @@ use crate::stats::StateUsageStats; use log::{trace, debug, warn}; pub use sc_state_db::PruningMode; -#[cfg(feature = "kvdb-rocksdb")] +#[cfg(feature = "kvdb-rocksdb", test)] pub use bench::BenchmarkingState; #[cfg(feature = "test-helpers")] From 00809ad5e83876bf3d57711e46331f5779cc6bb9 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sun, 9 Feb 2020 12:11:19 +0100 Subject: [PATCH 48/50] Add test feature to bench --- client/db/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index 261e7e44a992d..5fed4d26345f9 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -29,7 +29,7 @@ pub mod light; pub mod offchain; -#[cfg(feature = "kvdb-rocksdb", test)] +#[cfg(any(feature = "kvdb-rocksdb", test))] pub mod bench; mod children; @@ -83,7 +83,7 @@ use crate::stats::StateUsageStats; use log::{trace, debug, warn}; pub use sc_state_db::PruningMode; -#[cfg(feature = "kvdb-rocksdb", test)] +#[cfg(any(feature = "kvdb-rocksdb", test))] pub use bench::BenchmarkingState; #[cfg(feature = "test-helpers")] From 8d509d034a2a670535eb73263722b1a3be568a50 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sun, 9 Feb 2020 12:34:06 +0100 Subject: [PATCH 49/50] Add rocksdb feature flag --- client/service/src/chain_ops.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/service/src/chain_ops.rs b/client/service/src/chain_ops.rs index 592d549cea51b..3d77d9c815e4f 100644 --- a/client/service/src/chain_ops.rs +++ b/client/service/src/chain_ops.rs @@ -31,7 +31,7 @@ use sp_runtime::{ use sp_runtime::generic::{BlockId, SignedBlock}; use codec::{Decode, Encode, IoReader}; use sc_client::{Client, ExecutionStrategy, StateMachine, LocalCallExecutor}; - +#[cfg(feature = "rocksdb")] use sc_client_db::BenchmarkingState; use sp_consensus::import_queue::{IncomingBlock, Link, BlockImportError, BlockImportResult, ImportQueue}; use sp_consensus::BlockOrigin; @@ -50,6 +50,7 @@ pub fn build_spec(spec: ChainSpec, raw: bool) -> error::Result ( spec: ChainSpec, strategy: ExecutionStrategy, From fe2d0a2cdd68698eb3a6697afbf014ab4737d957 Mon Sep 17 00:00:00 2001 From: Gavin Wood Date: Sun, 9 Feb 2020 17:57:49 +0100 Subject: [PATCH 50/50] Update bench.rs --- client/db/src/bench.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/db/src/bench.rs b/client/db/src/bench.rs index c04c193c8c216..9858a5c148bfa 100644 --- a/client/db/src/bench.rs +++ b/client/db/src/bench.rs @@ -77,10 +77,11 @@ impl BenchmarkingState { }; state.reopen()?; - let child_delta = genesis.children.into_iter().map(|(storage_key, child_content)| ( - storage_key, - child_content.data.into_iter().map(|(k, v)| (k, Some(v))), child_content.child_info), - ); + let child_delta = genesis.children.into_iter().map(|(storage_key, child_content)| ( + storage_key, + child_content.data.into_iter().map(|(k, v)| (k, Some(v))), + child_content.child_info + )); let (root, transaction) = state.state.borrow_mut().as_mut().unwrap().full_storage_root( genesis.top.into_iter().map(|(k, v)| (k, Some(v))), child_delta,