From c077a2b5e16c8dc331005871deb9566274a3ffc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 19 Feb 2020 10:22:36 +0100 Subject: [PATCH 001/108] Consolidate frame benchmarking into a frame crate (#4977) This prs cleans up some of the frame benchmarking stuff: - Move CLI into `frame-benchmarking-cli`. No frame related CLI should exists in the default Substrate CLI. - Move all traits and types related to frame benchmarking into the `frame-benchmarking` trait. Frame types should be isolated in Frame. --- Cargo.lock | 31 +++++ Cargo.toml | 2 + bin/node/cli/Cargo.toml | 3 + bin/node/cli/src/cli.rs | 7 ++ bin/node/cli/src/command.rs | 7 +- bin/node/executor/Cargo.toml | 1 + bin/node/executor/src/lib.rs | 2 +- bin/node/runtime/Cargo.toml | 2 + bin/node/runtime/src/lib.rs | 28 ++--- client/cli/src/lib.rs | 2 +- client/cli/src/params.rs | 118 ++++-------------- client/service/src/chain_ops.rs | 72 ++--------- frame/balances/Cargo.toml | 2 + frame/balances/src/benchmarking.rs | 18 +-- frame/benchmarking/Cargo.toml | 16 +++ frame/benchmarking/src/lib.rs | 141 ++++++++++++++++++++++ frame/identity/Cargo.toml | 2 + frame/identity/src/benchmarking.rs | 59 ++++----- frame/timestamp/Cargo.toml | 2 + frame/timestamp/src/benchmarking.rs | 21 ++-- primitives/io/src/lib.rs | 24 ---- primitives/runtime/src/lib.rs | 12 -- primitives/runtime/src/traits.rs | 70 ----------- utils/frame/benchmarking-cli/Cargo.toml | 17 +++ utils/frame/benchmarking-cli/src/lib.rs | 152 ++++++++++++++++++++++++ 25 files changed, 483 insertions(+), 328 deletions(-) create mode 100644 frame/benchmarking/Cargo.toml create mode 100644 frame/benchmarking/src/lib.rs create mode 100644 utils/frame/benchmarking-cli/Cargo.toml create mode 100644 utils/frame/benchmarking-cli/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index b557048f9d..f518377d62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1441,6 +1441,31 @@ dependencies = [ "parity-scale-codec", ] +[[package]] +name = "frame-benchmarking" +version = "2.0.0" +dependencies = [ + "parity-scale-codec", + "sp-api", + "sp-runtime-interface", + "sp-std", +] + +[[package]] +name = "frame-benchmarking-cli" +version = "2.0.0" +dependencies = [ + "frame-benchmarking", + "parity-scale-codec", + "sc-cli", + "sc-client", + "sc-client-db", + "sc-executor", + "sc-service", + "sp-runtime", + "structopt", +] + [[package]] name = "frame-executive" version = "2.0.0" @@ -3369,6 +3394,7 @@ version = "2.0.0" dependencies = [ "assert_cmd", "browser-utils", + "frame-benchmarking-cli", "frame-support", "frame-system", "futures 0.3.4", @@ -3437,6 +3463,7 @@ name = "node-executor" version = "2.0.0" dependencies = [ "criterion 0.3.1", + "frame-benchmarking", "frame-support", "frame-system", "node-primitives", @@ -3530,6 +3557,7 @@ dependencies = [ name = "node-runtime" version = "2.0.0" dependencies = [ + "frame-benchmarking", "frame-executive", "frame-support", "frame-system", @@ -3966,6 +3994,7 @@ dependencies = [ name = "pallet-balances" version = "2.0.0" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "pallet-transaction-payment", @@ -4197,6 +4226,7 @@ name = "pallet-identity" version = "2.0.0" dependencies = [ "enumflags2", + "frame-benchmarking", "frame-support", "frame-system", "pallet-balances", @@ -4433,6 +4463,7 @@ dependencies = [ name = "pallet-timestamp" version = "2.0.0" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "impl-trait-for-tuples", diff --git a/Cargo.toml b/Cargo.toml index a42a8e24d0..2dc0c8926c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,7 @@ members = [ "frame/authorship", "frame/babe", "frame/balances", + "frame/benchmarking", "frame/collective", "frame/contracts", "frame/contracts/rpc", @@ -156,6 +157,7 @@ members = [ "utils/browser", "utils/build-script-utils", "utils/fork-tree", + "utils/frame/benchmarking-cli", "utils/frame/rpc/support", "utils/frame/rpc/system", "utils/wasm-builder", diff --git a/bin/node/cli/Cargo.toml b/bin/node/cli/Cargo.toml index 079e8d13e2..d383e2c05a 100644 --- a/bin/node/cli/Cargo.toml +++ b/bin/node/cli/Cargo.toml @@ -89,6 +89,7 @@ node-executor = { version = "2.0.0", path = "../executor" } # CLI-specific dependencies sc-cli = { version = "0.8.0", optional = true, path = "../../../client/cli" } +frame-benchmarking-cli = { version = "2.0.0", optional = true, path = "../../../utils/frame/benchmarking-cli" } node-transaction-factory = { version = "0.8.0", optional = true, path = "../transaction-factory" } node-inspect = { version = "0.8.0", optional = true, path = "../inspect" } @@ -112,6 +113,7 @@ build-script-utils = { version = "2.0.0", package = "substrate-build-script-util structopt = { version = "0.3.8", optional = true } node-transaction-factory = { version = "0.8.0", optional = true, path = "../transaction-factory" } node-inspect = { version = "0.8.0", optional = true, path = "../inspect" } +frame-benchmarking-cli = { version = "2.0.0", optional = true, path = "../../../utils/frame/benchmarking-cli" } [build-dependencies.sc-cli] version = "0.8.0" @@ -135,6 +137,7 @@ cli = [ "node-inspect", "node-transaction-factory", "sc-cli", + "frame-benchmarking-cli", "sc-service/rocksdb", "structopt", "vergen", diff --git a/bin/node/cli/src/cli.rs b/bin/node/cli/src/cli.rs index 7dcd02699d..40f1dcf6f4 100644 --- a/bin/node/cli/src/cli.rs +++ b/bin/node/cli/src/cli.rs @@ -53,6 +53,13 @@ pub enum Subcommand { about = "Decode given block or extrinsic using current native runtime." )] Inspect(node_inspect::cli::InspectCmd), + + /// The custom benchmark subcommmand benchmarking runtime pallets. + #[structopt( + name = "benchmark", + about = "Benchmark runtime pallets." + )] + Benchmark(frame_benchmarking_cli::BenchmarkCmd), } /// The `factory` command used to generate transactions. diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index ba0f2785c1..5a942d964c 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -43,12 +43,17 @@ where cmd.init(&mut config, load_spec, &version)?; let client = sc_service::new_full_client::< - node_runtime::Block,node_runtime::RuntimeApi, node_executor::Executor, _, _, + node_runtime::Block, node_runtime::RuntimeApi, node_executor::Executor, _, _, >(&config)?; let inspect = node_inspect::Inspector::::new(client); cmd.run(inspect) }, + Some(Subcommand::Benchmark(cmd)) => { + cmd.init(&mut config, load_spec, &version)?; + + cmd.run::<_, _, node_runtime::Block, node_executor::Executor>(config) + }, Some(Subcommand::Factory(cli_args)) => { sc_cli::init(&cli_args.shared_params, &version)?; sc_cli::init_config(&mut config, &cli_args.shared_params, &version, load_spec)?; diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index 1d894e39fa..f55e1dae58 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -16,6 +16,7 @@ sp-io = { version = "2.0.0", path = "../../../primitives/io" } sp-state-machine = { version = "0.8", path = "../../../primitives/state-machine" } sp-trie = { version = "2.0.0", path = "../../../primitives/trie" } trie-root = "0.16.0" +frame-benchmarking = { version = "2.0.0", path = "../../../frame/benchmarking" } [dev-dependencies] criterion = "0.3.0" diff --git a/bin/node/executor/src/lib.rs b/bin/node/executor/src/lib.rs index 72f40b7c1f..bcc7f48507 100644 --- a/bin/node/executor/src/lib.rs +++ b/bin/node/executor/src/lib.rs @@ -26,5 +26,5 @@ native_executor_instance!( pub Executor, node_runtime::api::dispatch, node_runtime::native_version, - sp_io::benchmarking::HostFunctions, + frame_benchmarking::benchmarking::HostFunctions, ); diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 3f8e8b6731..8156e4d444 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -33,6 +33,7 @@ sp-version = { version = "2.0.0", default-features = false, path = "../../../pri # frame dependencies frame-executive = { version = "2.0.0", default-features = false, path = "../../../frame/executive" } +frame-benchmarking = { version = "2.0.0", default-features = false, path = "../../../frame/benchmarking" } frame-support = { version = "2.0.0", default-features = false, path = "../../../frame/support" } frame-system = { version = "2.0.0", default-features = false, path = "../../../frame/system" } frame-system-rpc-runtime-api = { version = "2.0.0", default-features = false, path = "../../../frame/system/rpc/runtime-api/" } @@ -115,6 +116,7 @@ std = [ "sp-session/std", "pallet-sudo/std", "frame-support/std", + "frame-benchmarking/std", "frame-system-rpc-runtime-api/std", "frame-system/std", "pallet-timestamp/std", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 956fc0bb0e..b60056e045 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -31,14 +31,13 @@ pub use node_primitives::{AccountId, Signature}; use node_primitives::{AccountIndex, Balance, BlockNumber, Hash, Index, Moment}; use sp_api::impl_runtime_apis; use sp_runtime::{ - Permill, Perbill, Percent, ApplyExtrinsicResult, BenchmarkResults, - impl_opaque_keys, generic, create_runtime_str, + Permill, Perbill, Percent, ApplyExtrinsicResult, impl_opaque_keys, generic, create_runtime_str, }; use sp_runtime::curve::PiecewiseLinear; use sp_runtime::transaction_validity::TransactionValidity; use sp_runtime::traits::{ self, BlakeTwo256, Block as BlockT, StaticLookup, SaturatedConversion, - ConvertInto, OpaqueKeys, Benchmarking, + ConvertInto, OpaqueKeys, }; use sp_version::RuntimeVersion; #[cfg(any(feature = "std", test))] @@ -816,28 +815,25 @@ impl_runtime_apis! { } } - impl crate::Benchmark for Runtime { - fn dispatch_benchmark(module: Vec, extrinsic: Vec, steps: u32, repeat: u32) - -> Option> - { + impl frame_benchmarking::Benchmark for Runtime { + fn dispatch_benchmark( + module: Vec, + extrinsic: Vec, + steps: u32, + repeat: u32, + ) -> Option> { + use frame_benchmarking::Benchmarking; + match module.as_slice() { b"pallet-balances" | b"balances" => Balances::run_benchmark(extrinsic, steps, repeat).ok(), b"pallet-identity" | b"identity" => Identity::run_benchmark(extrinsic, steps, repeat).ok(), b"pallet-timestamp" | b"timestamp" => Timestamp::run_benchmark(extrinsic, steps, repeat).ok(), - _ => return None, + _ => None, } } } } -sp_api::decl_runtime_apis! { - pub trait Benchmark - { - fn dispatch_benchmark(module: Vec, extrinsic: Vec, steps: u32, repeat: u32) - -> Option>; - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 7495ad8e75..6259c0a21b 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -57,7 +57,7 @@ use params::{ pub use params::{ SharedParams, ImportParams, ExecutionStrategy, Subcommand, RunCmd, BuildSpecCmd, ExportBlocksCmd, ImportBlocksCmd, CheckBlockCmd, PurgeChainCmd, RevertCmd, - BenchmarkCmd, + WasmExecutionMethod, }; pub use traits::GetSharedParams; use app_dirs::{AppInfo, AppDataType}; diff --git a/client/cli/src/params.rs b/client/cli/src/params.rs index d6c437f668..aaa46c0f63 100644 --- a/client/cli/src/params.rs +++ b/client/cli/src/params.rs @@ -47,29 +47,35 @@ impl Into for ExecutionStrategy { } } -arg_enum! { - /// How to execute Wasm runtime code - #[allow(missing_docs)] - #[derive(Debug, Clone, Copy)] - pub enum WasmExecutionMethod { - // Uses an interpreter. - Interpreted, - // Uses a compiled runtime. - Compiled, +#[allow(missing_docs)] +mod wasm_execution_method { + use super::*; + + arg_enum! { + /// How to execute Wasm runtime code + #[derive(Debug, Clone, Copy)] + pub enum WasmExecutionMethod { + // Uses an interpreter. + Interpreted, + // Uses a compiled runtime. + Compiled, + } } -} -impl WasmExecutionMethod { - /// Returns list of variants that are not disabled by feature flags. - fn enabled_variants() -> Vec<&'static str> { - Self::variants() - .iter() - .cloned() - .filter(|&name| cfg!(feature = "wasmtime") || name != "Compiled") - .collect() + impl WasmExecutionMethod { + /// Returns list of variants that are not disabled by feature flags. + pub fn enabled_variants() -> Vec<&'static str> { + Self::variants() + .iter() + .cloned() + .filter(|&name| cfg!(feature = "wasmtime") || name != "Compiled") + .collect() + } } } +pub use wasm_execution_method::WasmExecutionMethod; + impl Into for WasmExecutionMethod { fn into(self) -> sc_service::config::WasmExecutionMethod { match self { @@ -849,49 +855,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: String, - - /// Select an extrinsic to benchmark. - #[structopt(short, long)] - pub extrinsic: String, - - /// Select how many samples we should take across the variable components. - #[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, - - /// 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, -} - /// All core commands that are provided by default. /// /// The core commands are split into multiple subcommands and `Run` is the default subcommand. From @@ -916,9 +879,6 @@ pub enum Subcommand { /// Remove the whole chain data. PurgeChain(PurgeChainCmd), - - /// Run runtime benchmarks. - Benchmark(BenchmarkCmd), } impl Subcommand { @@ -933,7 +893,6 @@ impl Subcommand { CheckBlock(params) => ¶ms.shared_params, Revert(params) => ¶ms.shared_params, PurgeChain(params) => ¶ms.shared_params, - Benchmark(params) => ¶ms.shared_params, } } @@ -960,7 +919,6 @@ impl Subcommand { Subcommand::ImportBlocks(cmd) => cmd.run(config, builder), Subcommand::CheckBlock(cmd) => cmd.run(config, builder), Subcommand::PurgeChain(cmd) => cmd.run(config), - Subcommand::Benchmark(cmd) => cmd.run(config, builder), Subcommand::Revert(cmd) => cmd.run(config, builder), } } @@ -1238,31 +1196,3 @@ impl RevertCmd { Ok(()) } } - -impl BenchmarkCmd { - /// Runs the command and benchmarks the chain. - pub fn run( - self, - config: Configuration, - _builder: B, - ) -> error::Result<()> - where - B: FnOnce(Configuration) -> Result, - G: RuntimeGenesis, - E: ChainSpecExtension, - BC: ServiceBuilderCommand + Unpin, - BB: sp_runtime::traits::Block + Debug, - <<::Header as HeaderT>::Number as std::str::FromStr>::Err: std::fmt::Debug, - ::Hash: std::str::FromStr, - { - 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(); - let pallet = self.pallet; - let extrinsic = self.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 3d77d9c815..30987170f3 100644 --- a/client/service/src/chain_ops.rs +++ b/client/service/src/chain_ops.rs @@ -22,20 +22,17 @@ use crate::error::Error; use sc_chain_spec::{ChainSpec, RuntimeGenesis, Extension}; use log::{warn, info}; use futures::{future, prelude::*}; -use sp_runtime::{ - BuildStorage, BenchmarkResults, - traits::{ - Block as BlockT, NumberFor, One, Zero, Header, SaturatedConversion - } +use sp_runtime::traits::{ + Block as BlockT, NumberFor, One, Zero, Header, SaturatedConversion }; 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; -use sc_executor::{NativeExecutor, NativeExecutionDispatch, WasmExecutionMethod}; +use sc_client::{Client, LocalCallExecutor}; +use sp_consensus::{ + BlockOrigin, + import_queue::{IncomingBlock, Link, BlockImportError, BlockImportResult, ImportQueue}, +}; +use sc_executor::{NativeExecutor, NativeExecutionDispatch}; use std::{io::{Read, Write, Seek}, pin::Pin}; @@ -49,59 +46,6 @@ pub fn build_spec(spec: ChainSpec, raw: bool) -> error::Result ( - spec: ChainSpec, - strategy: ExecutionStrategy, - wasm_method: WasmExecutionMethod, - pallet: String, - extrinsic: String, - steps: u32, - repeat: u32, -) -> 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(genesis_storage)?; - let executor = NativeExecutor::::new( - wasm_method, - None, // heap pages - ); - let result = StateMachine::<_, _, NumberFor, _>::new( - &state, - None, - &mut changes, - &executor, - "Benchmark_dispatch_benchmark", - &(&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_or(None); - if let Some(results) = results { - // 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"); - // 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."); - } else { - info!("No Results."); - } - Ok(()) -} - - impl< TBl, TRtApi, TGen, TCSExt, TBackend, TExecDisp, TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index 871290b182..f2bf1069af 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -11,6 +11,7 @@ codec = { package = "parity-scale-codec", version = "1.0.0", default-features = 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-benchmarking = { version = "2.0.0", default-features = false, path = "../benchmarking" } frame-support = { version = "2.0.0", default-features = false, path = "../support" } frame-system = { version = "2.0.0", default-features = false, path = "../system" } @@ -27,6 +28,7 @@ std = [ "sp-std/std", "sp-io/std", "sp-runtime/std", + "frame-benchmarking/std", "frame-support/std", "frame-system/std", ] diff --git a/frame/balances/src/benchmarking.rs b/frame/balances/src/benchmarking.rs index 605561d597..e564824aaa 100644 --- a/frame/balances/src/benchmarking.rs +++ b/frame/balances/src/benchmarking.rs @@ -20,8 +20,10 @@ use super::*; use frame_system::RawOrigin; use sp_io::hashing::blake2_256; -use sp_runtime::{BenchmarkResults, BenchmarkParameter}; -use sp_runtime::traits::{Bounded, Benchmarking, BenchmarkingSetup, Dispatchable}; +use frame_benchmarking::{ + BenchmarkResults, BenchmarkParameter, Benchmarking, BenchmarkingSetup, benchmarking, +}; +use sp_runtime::traits::{Bounded, Dispatchable}; use crate::Module as Balances; @@ -271,8 +273,8 @@ impl Benchmarking for Module { }; // Warm up the DB - sp_io::benchmarking::commit_db(); - sp_io::benchmarking::wipe_db(); + benchmarking::commit_db(); + benchmarking::wipe_db(); let components = , RawOrigin>>::components(&selected_benchmark); // results go here @@ -298,11 +300,11 @@ impl Benchmarking for Module { 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(); + benchmarking::commit_db(); // Run the benchmark. - let start = sp_io::benchmarking::current_time(); + let start = benchmarking::current_time(); call.dispatch(caller.clone().into())?; - let finish = sp_io::benchmarking::current_time(); + let finish = benchmarking::current_time(); let elapsed = finish - start; sp_std::if_std!{ if let RawOrigin::Signed(who) = caller.clone() { @@ -312,7 +314,7 @@ impl Benchmarking for Module { } results.push((c.clone(), elapsed)); // Wipe the DB back to the genesis state. - sp_io::benchmarking::wipe_db(); + benchmarking::wipe_db(); } } } diff --git a/frame/benchmarking/Cargo.toml b/frame/benchmarking/Cargo.toml new file mode 100644 index 0000000000..c2748e080d --- /dev/null +++ b/frame/benchmarking/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "frame-benchmarking" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.1.2", default-features = false } +sp-api = { version = "2.0.0", path = "../../primitives/api", default-features = false } +sp-runtime-interface = { version = "2.0.0", path = "../../primitives/runtime-interface", default-features = false } +sp-std = { version = "2.0.0", path = "../../primitives/std", default-features = false } + +[features] +default = [ "std" ] +std = [ "sp-runtime-interface/std", "sp-api/std", "codec/std", "sp-std/std" ] diff --git a/frame/benchmarking/src/lib.rs b/frame/benchmarking/src/lib.rs new file mode 100644 index 0000000000..c57cfb4914 --- /dev/null +++ b/frame/benchmarking/src/lib.rs @@ -0,0 +1,141 @@ +// 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 . + +//! Interfaces and types for benchmarking a FRAME runtime. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::vec::Vec; + +/// An alphabet of possible parameters to use for benchmarking. +#[derive(codec::Encode, codec::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, +} + +/// Results from running benchmarks on a FRAME pallet. +/// 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); + +sp_api::decl_runtime_apis! { + /// Runtime api for benchmarking a FRAME runtime. + pub trait Benchmark { + /// Dispatch the given benchmark. + fn dispatch_benchmark( + module: Vec, + extrinsic: Vec, + steps: u32, + repeat: u32, + ) -> Option>; + } +} + +/// Interface that provides functions for benchmarking the runtime. +#[sp_runtime_interface::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() + } + + /// Reset the trie database to the genesis state. + fn wipe_db(&mut self) { + self.wipe() + } + + /// Commit pending storage changes to the trie database and clear the database cache. + fn commit_db(&mut self) { + self.commit() + } +} + +/// 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>; +} + +/// 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)]) -> Result<(Call, RawOrigin), &'static str>; +} + +/// Creates a `SelectedBenchmark` enum implementing `BenchmarkingSetup`. +/// +/// Every variant must implement [`BenchmarkingSetup`]. +/// +/// ```nocompile +/// +/// struct Transfer; +/// impl BenchmarkingSetup for Transfer { ... } +/// +/// struct SetBalance; +/// impl BenchmarkingSetup for SetBalance { ... } +/// +/// selected_benchmark!(Transfer, SetBalance); +/// ``` +#[macro_export] +macro_rules! selected_benchmark { + ( + $( $bench:ident ),* + ) => { + // The list of available benchmarks for this pallet. + enum SelectedBenchmark { + $( $bench, )* + } + + // Allow us to select a benchmark from the list of available benchmarks. + impl $crate::BenchmarkingSetup, RawOrigin> for SelectedBenchmark { + fn components(&self) -> Vec<($crate::BenchmarkParameter, u32, u32)> { + match self { + $( Self::$bench => <$bench as $crate::BenchmarkingSetup< + T, + Call, + RawOrigin, + >>::components(&$bench), )* + } + } + + fn instance(&self, components: &[($crate::BenchmarkParameter, u32)]) + -> Result<(Call, RawOrigin), &'static str> + { + match self { + $( Self::$bench => <$bench as $crate::BenchmarkingSetup< + T, + Call, + RawOrigin, + >>::instance(&$bench, components), )* + } + } + } + }; +} diff --git a/frame/identity/Cargo.toml b/frame/identity/Cargo.toml index 59e8f721c8..c95d230230 100644 --- a/frame/identity/Cargo.toml +++ b/frame/identity/Cargo.toml @@ -12,6 +12,7 @@ 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-benchmarking = { version = "2.0.0", default-features = false, path = "../benchmarking" } frame-support = { version = "2.0.0", default-features = false, path = "../support" } frame-system = { version = "2.0.0", default-features = false, path = "../system" } @@ -27,6 +28,7 @@ std = [ "sp-std/std", "sp-io/std", "sp-runtime/std", + "frame-benchmarking/std", "frame-support/std", "frame-system/std", ] diff --git a/frame/identity/src/benchmarking.rs b/frame/identity/src/benchmarking.rs index 11e98101ec..c208d32717 100644 --- a/frame/identity/src/benchmarking.rs +++ b/frame/identity/src/benchmarking.rs @@ -20,8 +20,11 @@ use super::*; use frame_system::RawOrigin; use sp_io::hashing::blake2_256; -use sp_runtime::{BenchmarkResults, BenchmarkParameter, selected_benchmark}; -use sp_runtime::traits::{Bounded, Benchmarking, BenchmarkingSetup, Dispatchable}; +use frame_benchmarking::{ + BenchmarkResults, BenchmarkParameter, selected_benchmark, benchmarking, Benchmarking, + BenchmarkingSetup, +}; +use sp_runtime::traits::{Bounded, Dispatchable}; use crate::Module as Identity; @@ -102,7 +105,7 @@ impl BenchmarkingSetup, RawOrigin> for { // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; - benchmarking::add_registrars::(r)?; + add_registrars::(r)?; // Return the `add_registrar` r + 1 call Ok((crate::Call::::add_registrar(account::("registrar", r + 1)), RawOrigin::Root)) @@ -126,7 +129,7 @@ impl BenchmarkingSetup, RawOrigin> for { // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; - benchmarking::add_registrars::(r)?; + add_registrars::(r)?; // The target user let caller = account::("caller", r); @@ -135,7 +138,7 @@ impl BenchmarkingSetup, RawOrigin> for let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); // Add an initial identity - let initial_info = benchmarking::create_identity_info::(1); + let initial_info = create_identity_info::(1); Identity::::set_identity(caller_origin.clone(), initial_info)?; // User requests judgement from all the registrars, and they approve @@ -152,7 +155,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 = benchmarking::create_identity_info::(x); + let info = create_identity_info::(x); // Return the `set_identity` call Ok((crate::Call::::set_identity(info), RawOrigin::Signed(caller))) @@ -181,7 +184,7 @@ impl BenchmarkingSetup, RawOrigin> for let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::::max_value()); // Create their main identity - let info = benchmarking::create_identity_info::(1); + let info = create_identity_info::(1); Identity::::set_identity(caller_origin.clone(), info)?; // Give them s many sub accounts @@ -221,16 +224,16 @@ impl BenchmarkingSetup, RawOrigin> for // Register r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; - benchmarking::add_registrars::(r)?; + 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); + let info = 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)?; + let _ = add_sub_accounts::(caller.clone(), s)?; // User requests judgement from all the registrars, and they approve for i in 0..r { @@ -270,11 +273,11 @@ impl BenchmarkingSetup, RawOrigin> for // Register r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; - benchmarking::add_registrars::(r)?; + 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); + let info = create_identity_info::(x); Identity::::set_identity(caller_origin.clone(), info)?; // Return the `request_judgement` call @@ -304,11 +307,11 @@ impl BenchmarkingSetup, RawOrigin> for // Register r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; - benchmarking::add_registrars::(r)?; + 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); + let info = create_identity_info::(x); Identity::::set_identity(caller_origin.clone(), info)?; // Request judgement @@ -337,7 +340,7 @@ impl BenchmarkingSetup, RawOrigin> for // Register r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; - benchmarking::add_registrars::(r)?; + add_registrars::(r)?; // Add caller as registrar Identity::::add_registrar(RawOrigin::Root.into(), caller.clone())?; @@ -366,7 +369,7 @@ impl BenchmarkingSetup, RawOrigin> for // Register r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; - benchmarking::add_registrars::(r)?; + add_registrars::(r)?; // Add caller as registrar Identity::::add_registrar(RawOrigin::Root.into(), caller.clone())?; @@ -395,7 +398,7 @@ impl BenchmarkingSetup, RawOrigin> for // Register r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; - benchmarking::add_registrars::(r)?; + add_registrars::(r)?; // Add caller as registrar Identity::::add_registrar(RawOrigin::Root.into(), caller.clone())?; @@ -428,7 +431,7 @@ impl BenchmarkingSetup, RawOrigin> for { // Add r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; - benchmarking::add_registrars::(r)?; + add_registrars::(r)?; // The user let user = account::("user", r); @@ -438,7 +441,7 @@ impl BenchmarkingSetup, RawOrigin> for // 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); + let info = create_identity_info::(x); Identity::::set_identity(user_origin.clone(), info)?; // The caller registrar @@ -486,16 +489,16 @@ impl BenchmarkingSetup, RawOrigin> for // Register r registrars let r = components.iter().find(|&c| c.0 == BenchmarkParameter::R).unwrap().1; - benchmarking::add_registrars::(r)?; + 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); + let info = 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)?; + let _ = add_sub_accounts::(caller.clone(), s)?; // User requests judgement from all the registrars, and they approve for i in 0..r { @@ -547,8 +550,8 @@ impl Benchmarking for Module { }; // Warm up the DB - sp_io::benchmarking::commit_db(); - sp_io::benchmarking::wipe_db(); + benchmarking::commit_db(); + benchmarking::wipe_db(); // first one is set_identity. let components = , RawOrigin>>::components(&selected_benchmark); @@ -575,15 +578,15 @@ impl Benchmarking for Module { 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(); + benchmarking::commit_db(); // Run the benchmark. - let start = sp_io::benchmarking::current_time(); + let start = benchmarking::current_time(); call.dispatch(caller.into())?; - let finish = sp_io::benchmarking::current_time(); + let finish = benchmarking::current_time(); let elapsed = finish - start; results.push((c.clone(), elapsed)); // Wipe the DB back to the genesis state. - sp_io::benchmarking::wipe_db(); + benchmarking::wipe_db(); } } } diff --git a/frame/timestamp/Cargo.toml b/frame/timestamp/Cargo.toml index e68392f9e9..107374799d 100644 --- a/frame/timestamp/Cargo.toml +++ b/frame/timestamp/Cargo.toml @@ -12,6 +12,7 @@ sp-std = { version = "2.0.0", default-features = false, path = "../../primitives sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } sp-inherents = { version = "2.0.0", default-features = false, path = "../../primitives/inherents" } +frame-benchmarking = { version = "2.0.0", default-features = false, path = "../benchmarking" } frame-support = { version = "2.0.0", default-features = false, path = "../support" } frame-system = { version = "2.0.0", default-features = false, path = "../system" } sp-timestamp = { version = "2.0.0", default-features = false, path = "../../primitives/timestamp" } @@ -28,6 +29,7 @@ std = [ "codec/std", "sp-std/std", "sp-runtime/std", + "frame-benchmarking/std", "frame-support/std", "serde", "frame-system/std", diff --git a/frame/timestamp/src/benchmarking.rs b/frame/timestamp/src/benchmarking.rs index 55d6d7e046..9310d39dfd 100644 --- a/frame/timestamp/src/benchmarking.rs +++ b/frame/timestamp/src/benchmarking.rs @@ -21,8 +21,11 @@ use super::*; use sp_std::prelude::*; use frame_system::RawOrigin; -use sp_runtime::{BenchmarkResults, BenchmarkParameter, selected_benchmark}; -use sp_runtime::traits::{Benchmarking, BenchmarkingSetup, Dispatchable}; +use frame_benchmarking::{ + BenchmarkResults, BenchmarkParameter, selected_benchmark, benchmarking, + Benchmarking, BenchmarkingSetup, +}; +use sp_runtime::traits::Dispatchable; /// Benchmark `set` extrinsic. struct Set; @@ -54,10 +57,10 @@ impl Benchmarking for Module { b"set" => SelectedBenchmark::Set, _ => return Err("Could not find extrinsic."), }; - + // Warm up the DB - sp_io::benchmarking::commit_db(); - sp_io::benchmarking::wipe_db(); + benchmarking::commit_db(); + benchmarking::wipe_db(); let components = , RawOrigin>>::components(&selected_benchmark); let mut results: Vec = Vec::new(); @@ -87,15 +90,15 @@ impl Benchmarking for Module { >>::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(); + benchmarking::commit_db(); // Run the benchmark. - let start = sp_io::benchmarking::current_time(); + let start = benchmarking::current_time(); call.dispatch(caller.into())?; - let finish = sp_io::benchmarking::current_time(); + let finish = benchmarking::current_time(); let elapsed = finish - start; results.push((c.clone(), elapsed)); // Wipe the DB back to the genesis state. - sp_io::benchmarking::wipe_db(); + benchmarking::wipe_db(); } } } diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index a1e9181f28..5d29fe5c94 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -771,30 +771,6 @@ 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() - } - - /// Reset the trie database to the genesis state. - fn wipe_db(&mut self) { - self.wipe() - } - - /// Commit pending storage changes to the trie database and clear the database cache. - fn commit_db(&mut self) { - self.commit() - } -} - /// Wasm-only interface that provides functions for interacting with the sandbox. #[runtime_interface(wasm_only)] pub trait Sandbox { diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 4d6739bb13..6501dafc0e 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -685,18 +685,6 @@ pub fn print(print: impl traits::Printable) { print.print(); } -/// 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, -} - -/// Results from running benchmarks on a FRAME pallet. -/// 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)] mod tests { use super::*; diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 183df08ab8..f6655f68b4 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -26,7 +26,6 @@ use std::str::FromStr; #[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, @@ -1318,75 +1317,6 @@ pub trait BlockIdTo { ) -> Result>, Self::Error>; } -/// 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>; -} - -/// 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)]) -> Result<(Call, RawOrigin), &'static str>; -} - -/// Creates a `SelectedBenchmark` enum implementing `BenchmarkingSetup`. -/// -/// Every variant must implement [`BenchmarkingSetup`](crate::traits::BenchmarkingSetup). -/// -/// ```nocompile -/// -/// struct Transfer; -/// impl BenchmarkingSetup for Transfer { ... } -/// -/// struct SetBalance; -/// impl BenchmarkingSetup for SetBalance { ... } -/// -/// selected_benchmark!(Transfer, SetBalance); -/// ``` -#[macro_export] -macro_rules! selected_benchmark { - ($($bench:ident),*) => { - // The list of available benchmarks for this pallet. - enum SelectedBenchmark { - $( $bench, )* - } - - // Allow us to select a benchmark from the list of available benchmarks. - impl $crate::traits::BenchmarkingSetup, RawOrigin> for SelectedBenchmark { - fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> { - match self { - $( Self::$bench => <$bench as $crate::traits::BenchmarkingSetup< - T, - Call, - RawOrigin, - >>::components(&$bench), )* - } - } - - fn instance(&self, components: &[(BenchmarkParameter, u32)]) - -> Result<(Call, RawOrigin), &'static str> - { - match self { - $( Self::$bench => <$bench as $crate::traits::BenchmarkingSetup< - T, - Call, - RawOrigin, - >>::instance(&$bench, components), )* - } - } - } - }; -} - #[cfg(test)] mod tests { use super::*; diff --git a/utils/frame/benchmarking-cli/Cargo.toml b/utils/frame/benchmarking-cli/Cargo.toml new file mode 100644 index 0000000000..129104a901 --- /dev/null +++ b/utils/frame/benchmarking-cli/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "frame-benchmarking-cli" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0" + +[dependencies] +frame-benchmarking = { version = "2.0.0", path = "../../../frame/benchmarking" } +sc-service = { version = "0.8.0", path = "../../../client/service" } +sc-cli = { version = "0.8.0", path = "../../../client/cli" } +sc-client = { version = "0.8.0", path = "../../../client" } +sc-client-db = { version = "0.8.0", path = "../../../client/db" } +sc-executor = { version = "0.8.0", path = "../../../client/executor" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +structopt = "0.3.8" +codec = { version = "1.1.2", package = "parity-scale-codec" } diff --git a/utils/frame/benchmarking-cli/src/lib.rs b/utils/frame/benchmarking-cli/src/lib.rs new file mode 100644 index 0000000000..a8303beb0f --- /dev/null +++ b/utils/frame/benchmarking-cli/src/lib.rs @@ -0,0 +1,152 @@ +// 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 . + +use sp_runtime::{BuildStorage, traits::{Block as BlockT, Header as HeaderT, NumberFor}}; +use sc_client::StateMachine; +use sc_cli::{ExecutionStrategy, WasmExecutionMethod}; +use sc_client_db::BenchmarkingState; +use sc_service::{RuntimeGenesis, ChainSpecExtension}; +use sc_executor::{NativeExecutor, NativeExecutionDispatch}; +use std::fmt::Debug; +use codec::{Encode, Decode}; +use frame_benchmarking::BenchmarkResults; + +/// The `benchmark` command used to benchmark FRAME Pallets. +#[derive(Debug, structopt::StructOpt, Clone)] +pub struct BenchmarkCmd { + /// Select a FRAME Pallet to benchmark. + #[structopt(short, long)] + pub pallet: String, + + /// Select an extrinsic to benchmark. + #[structopt(short, long)] + pub extrinsic: String, + + /// Select how many samples we should take across the variable components. + #[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: sc_cli::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, +} + +impl BenchmarkCmd { + /// Parse CLI arguments and initialize given config. + pub fn init( + &self, + config: &mut sc_service::config::Configuration, + spec_factory: impl FnOnce(&str) -> Result>, String>, + version: &sc_cli::VersionInfo, + ) -> sc_cli::error::Result<()> where + G: sc_service::RuntimeGenesis, + E: sc_service::ChainSpecExtension, + { + sc_cli::init_config(config, &self.shared_params, version, spec_factory)?; + // make sure to configure keystore + sc_cli::fill_config_keystore_in_memory(config).map_err(Into::into) + } + + /// Runs the command and benchmarks the chain. + pub fn run( + self, + config: sc_service::Configuration, + ) -> sc_cli::error::Result<()> + where + G: RuntimeGenesis, + E: ChainSpecExtension, + BB: BlockT + Debug, + <<::Header as HeaderT>::Number as std::str::FromStr>::Err: std::fmt::Debug, + ::Hash: std::str::FromStr, + ExecDispatch: NativeExecutionDispatch + 'static, + { + let spec = config.chain_spec.expect("chain_spec is always Some"); + let wasm_method = self.wasm_method.into(); + let strategy = self.execution.unwrap_or(ExecutionStrategy::Native); + + let genesis_storage = spec.build_storage()?; + let mut changes = Default::default(); + let state = BenchmarkingState::::new(genesis_storage)?; + let executor = NativeExecutor::::new( + wasm_method, + None, // heap pages + ); + let result = StateMachine::<_, _, NumberFor, _>::new( + &state, + None, + &mut changes, + &executor, + "Benchmark_dispatch_benchmark", + &(&self.pallet, &self.extrinsic, self.steps, self.repeat).encode(), + Default::default(), + ) + .execute(strategy.into()) + .map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?; + let results = > as Decode>::decode(&mut &result[..]) + .unwrap_or(None); + + if let Some(results) = results { + // Print benchmark metadata + println!( + "Pallet: {:?}, Extrinsic: {:?}, Steps: {:?}, Repeat: {:?}", + self.pallet, + self.extrinsic, + self.steps, + self.repeat, + ); + + // 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); + }); + + eprintln!("Done."); + } else { + eprintln!("No Results."); + } + + Ok(()) + } +} -- GitLab From 5a2824d9b20f151466d92f20c767141c30a35b65 Mon Sep 17 00:00:00 2001 From: Alexander Popiak Date: Wed, 19 Feb 2020 10:46:55 +0100 Subject: [PATCH 002/108] Rename remaining occurences of SRML to FRAME (#4932) * rename remaining SRML occurences to FRAME * Some module -> pallet * remove out of date url Co-authored-by: Shawn Tabrizi Co-authored-by: Cecile Tonglet --- bin/node-template/README.md | 2 +- bin/node-template/pallets/template/src/lib.rs | 4 +- .../pallets/template/src/mock.rs | 4 +- bin/node/rpc/src/lib.rs | 4 +- bin/node/runtime/src/constants.rs | 2 +- docs/CONTRIBUTING.adoc | 2 +- docs/README.adoc | 2 +- frame/assets/src/lib.rs | 4 +- frame/authorship/Cargo.toml | 2 +- frame/authorship/src/lib.rs | 2 +- frame/babe/src/lib.rs | 2 +- frame/balances/src/lib.rs | 4 +- frame/example/src/lib.rs | 124 +++++++++--------- frame/executive/src/lib.rs | 8 +- frame/finality-tracker/src/lib.rs | 2 +- frame/generic-asset/src/lib.rs | 10 +- frame/generic-asset/src/mock.rs | 4 +- frame/identity/src/lib.rs | 4 +- frame/membership/src/lib.rs | 4 +- frame/nicks/src/lib.rs | 4 +- frame/recovery/src/mock.rs | 4 +- frame/scored-pool/src/mock.rs | 4 +- frame/session/src/historical.rs | 2 +- frame/session/src/lib.rs | 2 +- frame/society/src/mock.rs | 4 +- frame/support/procedural/src/lib.rs | 2 +- frame/support/src/dispatch.rs | 8 +- frame/support/src/traits.rs | 2 +- frame/system/src/lib.rs | 6 +- frame/timestamp/src/lib.rs | 2 +- frame/utility/src/lib.rs | 4 +- frame/vesting/src/lib.rs | 4 +- primitives/finality-tracker/src/lib.rs | 2 +- primitives/phragmen/src/lib.rs | 4 +- utils/frame/rpc/system/src/lib.rs | 2 +- 35 files changed, 123 insertions(+), 123 deletions(-) diff --git a/bin/node-template/README.md b/bin/node-template/README.md index c411dbeef5..4ae60478fc 100644 --- a/bin/node-template/README.md +++ b/bin/node-template/README.md @@ -1,6 +1,6 @@ # Substrate Node Template -A new SRML-based Substrate node, ready for hacking. +A new FRAME-based Substrate node, ready for hacking. ## Build diff --git a/bin/node-template/pallets/template/src/lib.rs b/bin/node-template/pallets/template/src/lib.rs index aa4d2cbc99..34e055bf54 100644 --- a/bin/node-template/pallets/template/src/lib.rs +++ b/bin/node-template/pallets/template/src/lib.rs @@ -1,12 +1,12 @@ #![cfg_attr(not(feature = "std"), no_std)] -/// A runtime module template with necessary imports +/// A FRAME pallet 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 +/// For more guidance on Substrate FRAME, see the example pallet /// https://github.com/paritytech/substrate/blob/master/frame/example/src/lib.rs use frame_support::{decl_module, decl_storage, decl_event, decl_error, dispatch}; diff --git a/bin/node-template/pallets/template/src/mock.rs b/bin/node-template/pallets/template/src/mock.rs index b3c1098db6..7a23610e4b 100644 --- a/bin/node-template/pallets/template/src/mock.rs +++ b/bin/node-template/pallets/template/src/mock.rs @@ -11,9 +11,9 @@ impl_outer_origin! { pub enum Origin for Test {} } -// For testing the module, we construct most of a mock runtime. This means +// For testing the pallet, 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. +// configuration traits of pallets we want to use. #[derive(Clone, Eq, PartialEq)] pub struct Test; parameter_types! { diff --git a/bin/node/rpc/src/lib.rs b/bin/node/rpc/src/lib.rs index 16e5446bb1..4e1cfa5673 100644 --- a/bin/node/rpc/src/lib.rs +++ b/bin/node/rpc/src/lib.rs @@ -23,9 +23,9 @@ //! need some strong assumptions about the particular runtime. //! //! The RPCs available in this crate however can make some assumptions -//! about how the runtime is constructed and what `SRML` modules +//! about how the runtime is constructed and what FRAME pallets //! are part of it. Therefore all node-runtime-specific RPCs can -//! be placed here or imported from corresponding `SRML` RPC definitions. +//! be placed here or imported from corresponding FRAME RPC definitions. #![warn(missing_docs)] diff --git a/bin/node/runtime/src/constants.rs b/bin/node/runtime/src/constants.rs index b2c880c08b..bf12492f8d 100644 --- a/bin/node/runtime/src/constants.rs +++ b/bin/node/runtime/src/constants.rs @@ -38,7 +38,7 @@ pub mod time { /// a slot being empty). /// This value is only used indirectly to define the unit constants below /// that are expressed in blocks. The rest of the code should use - /// `SLOT_DURATION` instead (like the timestamp module for calculating the + /// `SLOT_DURATION` instead (like the Timestamp pallet for calculating the /// minimum period). /// /// If using BABE with secondary slots (default) then all of the slots will diff --git a/docs/CONTRIBUTING.adoc b/docs/CONTRIBUTING.adoc index c83b686b09..cdd9809fff 100644 --- a/docs/CONTRIBUTING.adoc +++ b/docs/CONTRIBUTING.adoc @@ -27,7 +27,7 @@ Merging pull requests once CI is successful: . Once a PR is ready for review please add the https://github.com/paritytech/substrate/pulls?q=is%3Apr+is%3Aopen+label%3AA0-pleasereview[`pleasereview`] label. Generally PRs should sit with this label for 48 hours in order to garner feedback. It may be merged before if all relevant parties had a look at it. . If the first review is not an approval, swap `A0-pleasereview` to any label `[A3, A7]` to indicate that the PR has received some feedback, but needs further work. For example. https://github.com/paritytech/substrate/labels/A3-inprogress[`A3-inprogress`] is a general indicator that the PR is work in progress and https://github.com/paritytech/substrate/labels/A4-gotissues[`A4-gotissues`] means that it has significant problems that need fixing. Once the work is done, change the label back to `A0-pleasereview`. You might end up swapping a few times back and forth to climb up the A label group. Once a PR is https://github.com/paritytech/substrate/labels/A8-looksgood[`A8-looksgood`], it is ready to merge. -. PRs that break the external API must be tagged with https://github.com/paritytech/substrate/labels/B2-breaksapi[`breaksapi`], when it changes the SRML or consensus of running system with https://github.com/paritytech/substrate/labels/B3-breaksconsensus[`breaksconsensus`] +. PRs that break the external API must be tagged with https://github.com/paritytech/substrate/labels/B2-breaksapi[`breaksapi`], when it changes the FRAME or consensus of running system with https://github.com/paritytech/substrate/labels/B3-breaksconsensus[`breaksconsensus`] . No PR should be merged until all reviews' comments are addressed. *Reviewing pull requests*: diff --git a/docs/README.adoc b/docs/README.adoc index bbc2713fbe..8d762fee05 100644 --- a/docs/README.adoc +++ b/docs/README.adoc @@ -26,7 +26,7 @@ Substrate is designed for use in one of three ways: **2. Modular**: By hacking together pallets built with Substrate FRAME into a new runtime and possibly altering or reconfiguring the Substrate client's block authoring logic. This affords you a very large amount of freedom over your blockchain's logic, letting you change data types, add or remove modules, and crucially, add your own modules. Much can be changed without touching the block authoring logic (since it is generic). If this is the case, then the existing Substrate binary can be used for block authoring and syncing. If the block authoring logic needs to be tweaked, then a new, altered block authoring binary must be built as a separate project and used by validators. This is how the Polkadot relay chain is built and should suffice for almost all circumstances in the near to mid-term. -**3. Generic**: The entire SRML can be ignored and the entire runtime designed and implemented from scratch. If desired, this can be done in a language other than Rust, provided it can target WebAssembly. If the runtime can be made compatible with the existing client's block authoring logic, then you can simply construct a new genesis block from your Wasm blob and launch your chain with the existing Rust-based Substrate client. If not, then you'll need to alter the client's block authoring logic accordingly. This is probably a useless option for most projects right now, but provides complete flexibility allowing for a long-term, far-reaching upgrade path for the Substrate paradigm. +**3. Generic**: The entire FRAME can be ignored and the entire runtime designed and implemented from scratch. If desired, this can be done in a language other than Rust, provided it can target WebAssembly. If the runtime can be made compatible with the existing client's block authoring logic, then you can simply construct a new genesis block from your Wasm blob and launch your chain with the existing Rust-based Substrate client. If not, then you'll need to alter the client's block authoring logic accordingly. This is probably a useless option for most projects right now, but provides complete flexibility allowing for a long-term, far-reaching upgrade path for the Substrate paradigm. === The Basics of Substrate diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 8cdc9b9cc0..ebd1d17bcf 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -265,9 +265,9 @@ mod tests { pub enum Origin for Test where system = frame_system {} } - // For testing the module, we construct most of a mock runtime. This means + // For testing the pallet, 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. + // configuration traits of pallets we want to use. #[derive(Clone, Eq, PartialEq)] pub struct Test; parameter_types! { diff --git a/frame/authorship/Cargo.toml b/frame/authorship/Cargo.toml index 124d66c1bc..61056820f4 100644 --- a/frame/authorship/Cargo.toml +++ b/frame/authorship/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pallet-authorship" version = "2.0.0" -description = "Block and Uncle Author tracking for the SRML" +description = "Block and Uncle Author tracking for the FRAME" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0" diff --git a/frame/authorship/src/lib.rs b/frame/authorship/src/lib.rs index f2dbd4674f..335e13a7fd 100644 --- a/frame/authorship/src/lib.rs +++ b/frame/authorship/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Authorship tracking for SRML runtimes. +//! Authorship tracking for FRAME runtimes. //! //! This tracks the current author of the block and recent uncles. diff --git a/frame/babe/src/lib.rs b/frame/babe/src/lib.rs index e4e37a4b7a..aba3a75eb9 100644 --- a/frame/babe/src/lib.rs +++ b/frame/babe/src/lib.rs @@ -159,7 +159,7 @@ decl_storage! { } decl_module! { - /// The BABE SRML module + /// The BABE Pallet pub struct Module for enum Call where origin: T::Origin { /// The number of **slots** that an epoch takes. We couple sessions to /// epochs, i.e. we start a new session once the new epoch begins. diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 2c8ae3e18f..0f5e8b40d5 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -92,7 +92,7 @@ //! //! The following examples show how to use the Balances module in your custom module. //! -//! ### Examples from the SRML +//! ### Examples from the FRAME //! //! The Contract module uses the `Currency` trait to handle gas payment, and its types inherit from `Currency`: //! @@ -896,7 +896,7 @@ mod imbalances { // This works as long as `increase_total_issuance_by` doesn't use the Imbalance // types (basically for charging fees). // This should eventually be refactored so that the type item that -// depends on the Imbalance type (DustRemoval) is placed in its own SRML module. +// depends on the Imbalance type (DustRemoval) is placed in its own pallet. struct ElevatedTrait, I: Instance>(T, I); impl, I: Instance> Clone for ElevatedTrait { fn clone(&self) -> Self { unimplemented!() } diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index dbdc2efcf8..39f0d25d32 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -14,22 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! # Example Module +//! # Example Pallet //! //! -//! The Example: A simple example of a runtime module demonstrating -//! concepts, APIs and structures common to most runtime modules. +//! The Example: A simple example of a FRAME pallet demonstrating +//! concepts, APIs and structures common to most FRAME runtimes. //! -//! Run `cargo doc --package pallet-example --open` to view this module's documentation. +//! Run `cargo doc --package pallet-example --open` to view this pallet's documentation. //! //! ### Documentation Guidelines: //! //! -//! +//! //!