Skip to content
This repository was archived by the owner on Nov 1, 2023. It is now read-only.

Commit 98e8ae6

Browse files
ggwpezemostov
authored andcommitted
Sub-commands for benchmark (paritytech#11164)
* Restructure benchmark commands Signed-off-by: Oliver Tale-Yazdi <[email protected]> * Add benchmark block test Signed-off-by: Oliver Tale-Yazdi <[email protected]> * Fixup imports Signed-off-by: Oliver Tale-Yazdi <[email protected]> * CI Signed-off-by: Oliver Tale-Yazdi <[email protected]> * Review fixes Signed-off-by: Oliver Tale-Yazdi <[email protected]> * Extend error message Signed-off-by: Oliver Tale-Yazdi <[email protected]> * Apply suggestions from code review Co-authored-by: Zeke Mostov <[email protected]> * Review fixes Signed-off-by: Oliver Tale-Yazdi <[email protected]> * Add commands to node-template Signed-off-by: Oliver Tale-Yazdi <[email protected]> Co-authored-by: Zeke Mostov <[email protected]>
1 parent 00f728d commit 98e8ae6

File tree

33 files changed

+690
-342
lines changed

33 files changed

+690
-342
lines changed

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bin/node-template/node/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ sp-finality-grandpa = { version = "4.0.0-dev", path = "../../../primitives/final
3636
sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" }
3737
sp-runtime = { version = "6.0.0", path = "../../../primitives/runtime" }
3838
sp-timestamp = { version = "4.0.0-dev", path = "../../../primitives/timestamp" }
39+
sp-inherents = { version = "4.0.0-dev", path = "../../../primitives/inherents" }
40+
sp-keyring = { version = "6.0.0", path = "../../../primitives/keyring" }
41+
frame-system = { version = "4.0.0-dev", path = "../../../frame/system" }
42+
pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment" }
3943

4044
# These dependencies are used for the node template's RPCs
4145
jsonrpc-core = "18.0.0"

bin/node-template/node/src/cli.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ pub enum Subcommand {
3636
/// Revert the chain to a previous state.
3737
Revert(sc_cli::RevertCmd),
3838

39-
/// The custom benchmark subcommand benchmarking runtime pallets.
40-
#[clap(name = "benchmark", about = "Benchmark runtime pallets.")]
39+
/// Sub-commands concerned with benchmarking.
40+
#[clap(subcommand)]
4141
Benchmark(frame_benchmarking_cli::BenchmarkCmd),
4242

4343
/// Try some command against runtime state.

bin/node-template/node/src/command.rs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
use crate::{
22
chain_spec,
33
cli::{Cli, Subcommand},
4+
command_helper::{inherent_benchmark_data, BenchmarkExtrinsicBuilder},
45
service,
56
};
7+
use frame_benchmarking_cli::BenchmarkCmd;
68
use node_template_runtime::Block;
79
use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli};
810
use sc_service::PartialComponents;
11+
use std::sync::Arc;
912

1013
impl SubstrateCli for Cli {
1114
fn impl_name() -> String {
@@ -102,16 +105,41 @@ pub fn run() -> sc_cli::Result<()> {
102105
Ok((cmd.run(client, backend, Some(aux_revert)), task_manager))
103106
})
104107
},
105-
Some(Subcommand::Benchmark(cmd)) =>
106-
if cfg!(feature = "runtime-benchmarks") {
107-
let runner = cli.create_runner(cmd)?;
108+
Some(Subcommand::Benchmark(cmd)) => {
109+
let runner = cli.create_runner(cmd)?;
110+
111+
runner.sync_run(|config| {
112+
let PartialComponents { client, backend, .. } = service::new_partial(&config)?;
113+
114+
// This switch needs to be in the client, since the client decides
115+
// which sub-commands it wants to support.
116+
match cmd {
117+
BenchmarkCmd::Pallet(cmd) => {
118+
if !cfg!(feature = "runtime-benchmarks") {
119+
return Err(
120+
"Runtime benchmarking wasn't enabled when building the node. \
121+
You can enable it with `--features runtime-benchmarks`."
122+
.into(),
123+
)
124+
}
125+
126+
cmd.run::<Block, service::ExecutorDispatch>(config)
127+
},
128+
BenchmarkCmd::Block(cmd) => cmd.run(client),
129+
BenchmarkCmd::Storage(cmd) => {
130+
let db = backend.expose_db();
131+
let storage = backend.expose_storage();
108132

109-
runner.sync_run(|config| cmd.run::<Block, service::ExecutorDispatch>(config))
110-
} else {
111-
Err("Benchmarking wasn't enabled when building the node. You can enable it with \
112-
`--features runtime-benchmarks`."
113-
.into())
114-
},
133+
cmd.run(config, client, db, storage)
134+
},
135+
BenchmarkCmd::Overhead(cmd) => {
136+
let ext_builder = BenchmarkExtrinsicBuilder::new(client.clone());
137+
138+
cmd.run(config, client, inherent_benchmark_data()?, Arc::new(ext_builder))
139+
},
140+
}
141+
})
142+
},
115143
#[cfg(feature = "try-runtime")]
116144
Some(Subcommand::TryRuntime(cmd)) => {
117145
let runner = cli.create_runner(cmd)?;
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// This file is part of Substrate.
2+
3+
// Copyright (C) 2022 Parity Technologies (UK) Ltd.
4+
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5+
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU General Public License as published by
8+
// the Free Software Foundation, either version 3 of the License, or
9+
// (at your option) any later version.
10+
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU General Public License for more details.
15+
16+
// You should have received a copy of the GNU General Public License
17+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
19+
//! Contains code to setup the command invocations in [`super::command`] which would
20+
//! otherwise bloat that module.
21+
22+
use crate::service::FullClient;
23+
24+
use node_template_runtime as runtime;
25+
use runtime::SystemCall;
26+
use sc_cli::Result;
27+
use sc_client_api::BlockBackend;
28+
use sp_core::{Encode, Pair};
29+
use sp_inherents::{InherentData, InherentDataProvider};
30+
use sp_keyring::Sr25519Keyring;
31+
use sp_runtime::{OpaqueExtrinsic, SaturatedConversion};
32+
33+
use std::{sync::Arc, time::Duration};
34+
35+
/// Generates extrinsics for the `benchmark overhead` command.
36+
///
37+
/// Note: Should only be used for benchmarking.
38+
pub struct BenchmarkExtrinsicBuilder {
39+
client: Arc<FullClient>,
40+
}
41+
42+
impl BenchmarkExtrinsicBuilder {
43+
/// Creates a new [`Self`] from the given client.
44+
pub fn new(client: Arc<FullClient>) -> Self {
45+
Self { client }
46+
}
47+
}
48+
49+
impl frame_benchmarking_cli::ExtrinsicBuilder for BenchmarkExtrinsicBuilder {
50+
fn remark(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
51+
let acc = Sr25519Keyring::Bob.pair();
52+
let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic(
53+
self.client.as_ref(),
54+
acc,
55+
SystemCall::remark { remark: vec![] }.into(),
56+
nonce,
57+
)
58+
.into();
59+
60+
Ok(extrinsic)
61+
}
62+
}
63+
64+
/// Create a transaction using the given `call`.
65+
///
66+
/// Note: Should only be used for benchmarking.
67+
pub fn create_benchmark_extrinsic(
68+
client: &FullClient,
69+
sender: sp_core::sr25519::Pair,
70+
call: runtime::Call,
71+
nonce: u32,
72+
) -> runtime::UncheckedExtrinsic {
73+
let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed");
74+
let best_hash = client.chain_info().best_hash;
75+
let best_block = client.chain_info().best_number;
76+
77+
let period = runtime::BlockHashCount::get()
78+
.checked_next_power_of_two()
79+
.map(|c| c / 2)
80+
.unwrap_or(2) as u64;
81+
let extra: runtime::SignedExtra = (
82+
frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
83+
frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
84+
frame_system::CheckTxVersion::<runtime::Runtime>::new(),
85+
frame_system::CheckGenesis::<runtime::Runtime>::new(),
86+
frame_system::CheckEra::<runtime::Runtime>::from(sp_runtime::generic::Era::mortal(
87+
period,
88+
best_block.saturated_into(),
89+
)),
90+
frame_system::CheckNonce::<runtime::Runtime>::from(nonce),
91+
frame_system::CheckWeight::<runtime::Runtime>::new(),
92+
pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
93+
);
94+
95+
let raw_payload = runtime::SignedPayload::from_raw(
96+
call.clone(),
97+
extra.clone(),
98+
(
99+
(),
100+
runtime::VERSION.spec_version,
101+
runtime::VERSION.transaction_version,
102+
genesis_hash,
103+
best_hash,
104+
(),
105+
(),
106+
(),
107+
),
108+
);
109+
let signature = raw_payload.using_encoded(|e| sender.sign(e));
110+
111+
runtime::UncheckedExtrinsic::new_signed(
112+
call.clone(),
113+
sp_runtime::AccountId32::from(sender.public()).into(),
114+
runtime::Signature::Sr25519(signature.clone()),
115+
extra.clone(),
116+
)
117+
}
118+
119+
/// Generates inherent data for the `benchmark overhead` command.
120+
///
121+
/// Note: Should only be used for benchmarking.
122+
pub fn inherent_benchmark_data() -> Result<InherentData> {
123+
let mut inherent_data = InherentData::new();
124+
let d = Duration::from_millis(0);
125+
let timestamp = sp_timestamp::InherentDataProvider::new(d.into());
126+
127+
timestamp
128+
.provide_inherent_data(&mut inherent_data)
129+
.map_err(|e| format!("creating inherent data: {:?}", e))?;
130+
Ok(inherent_data)
131+
}

bin/node-template/node/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ mod chain_spec;
66
mod service;
77
mod cli;
88
mod command;
9+
mod command_helper;
910
mod rpc;
1011

1112
fn main() -> sc_cli::Result<()> {

bin/node-template/node/src/service.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ impl sc_executor::NativeExecutionDispatch for ExecutorDispatch {
3131
}
3232
}
3333

34-
type FullClient =
34+
pub(crate) type FullClient =
3535
sc_service::TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>;
3636
type FullBackend = sc_service::TFullBackend<Block>;
3737
type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;

bin/node-template/runtime/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub use frame_support::{
3333
},
3434
StorageValue,
3535
};
36+
pub use frame_system::Call as SystemCall;
3637
pub use pallet_balances::Call as BalancesCall;
3738
pub use pallet_timestamp::Call as TimestampCall;
3839
use pallet_transaction_payment::CurrencyAdapter;
@@ -306,6 +307,8 @@ pub type SignedExtra = (
306307
);
307308
/// Unchecked extrinsic type as expected by this runtime.
308309
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
310+
/// The payload being signed in transactions.
311+
pub type SignedPayload = generic::SignedPayload<Call, SignedExtra>;
309312
/// Executive: handles dispatch to the various modules.
310313
pub type Executive = frame_executive::Executive<
311314
Runtime,

bin/node/cli/src/cli.rs

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,28 +38,11 @@ pub enum Subcommand {
3838
)]
3939
Inspect(node_inspect::cli::InspectCmd),
4040

41-
/// The custom benchmark subcommmand benchmarking runtime pallets.
42-
#[clap(name = "benchmark", about = "Benchmark runtime pallets.")]
41+
/// Sub-commands concerned with benchmarking.
42+
/// The pallet benchmarking moved to the `pallet` sub-command.
43+
#[clap(subcommand)]
4344
Benchmark(frame_benchmarking_cli::BenchmarkCmd),
4445

45-
/// Benchmark the execution time of historic blocks and compare it to their consumed weight.
46-
#[clap(
47-
name = "benchmark-block",
48-
about = "Benchmark the execution time of historic blocks and compare it to their consumed weight."
49-
)]
50-
BenchmarkBlock(frame_benchmarking_cli::BlockCmd),
51-
52-
/// Sub command for benchmarking the per-block and per-extrinsic execution overhead.
53-
#[clap(
54-
name = "benchmark-overhead",
55-
about = "Benchmark the per-block and per-extrinsic execution overhead."
56-
)]
57-
BenchmarkOverhead(frame_benchmarking_cli::OverheadCmd),
58-
59-
/// Sub command for benchmarking the storage speed.
60-
#[clap(name = "benchmark-storage", about = "Benchmark storage speed.")]
61-
BenchmarkStorage(frame_benchmarking_cli::StorageCmd),
62-
6346
/// Try some command against runtime state.
6447
#[cfg(feature = "try-runtime")]
6548
TryRuntime(try_runtime_cli::TryRuntimeCmd),

bin/node/cli/src/command.rs

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616
// You should have received a copy of the GNU General Public License
1717
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1818

19+
use super::command_helper::{inherent_benchmark_data, BenchmarkExtrinsicBuilder};
1920
use crate::{
2021
chain_spec, service,
2122
service::{new_partial, FullClient},
2223
Cli, Subcommand,
2324
};
25+
use frame_benchmarking_cli::*;
2426
use node_executor::ExecutorDispatch;
2527
use node_primitives::Block;
2628
use node_runtime::RuntimeApi;
@@ -92,45 +94,39 @@ pub fn run() -> Result<()> {
9294

9395
runner.sync_run(|config| cmd.run::<Block, RuntimeApi, ExecutorDispatch>(config))
9496
},
95-
Some(Subcommand::Benchmark(cmd)) =>
96-
if cfg!(feature = "runtime-benchmarks") {
97-
let runner = cli.create_runner(cmd)?;
98-
99-
runner.sync_run(|config| cmd.run::<Block, ExecutorDispatch>(config))
100-
} else {
101-
Err("Benchmarking wasn't enabled when building the node. \
102-
You can enable it with `--features runtime-benchmarks`."
103-
.into())
104-
},
105-
Some(Subcommand::BenchmarkBlock(cmd)) => {
97+
Some(Subcommand::Benchmark(cmd)) => {
10698
let runner = cli.create_runner(cmd)?;
107-
runner.async_run(|config| {
108-
let PartialComponents { client, task_manager, .. } = new_partial(&config)?;
109-
Ok((cmd.run(client), task_manager))
110-
})
111-
},
112-
Some(Subcommand::BenchmarkOverhead(cmd)) => {
113-
let runner = cli.create_runner(cmd)?;
114-
runner.async_run(|mut config| {
115-
use super::command_helper::{inherent_data, ExtrinsicBuilder};
116-
// We don't use the authority role since that would start producing blocks
117-
// in the background which would mess with our benchmark.
118-
config.role = sc_service::Role::Full;
119-
120-
let PartialComponents { client, task_manager, .. } = new_partial(&config)?;
121-
let ext_builder = ExtrinsicBuilder::new(client.clone());
122-
123-
Ok((cmd.run(config, client, inherent_data()?, Arc::new(ext_builder)), task_manager))
124-
})
125-
},
126-
Some(Subcommand::BenchmarkStorage(cmd)) => {
127-
let runner = cli.create_runner(cmd)?;
128-
runner.async_run(|config| {
129-
let PartialComponents { client, task_manager, backend, .. } = new_partial(&config)?;
130-
let db = backend.expose_db();
131-
let storage = backend.expose_storage();
13299

133-
Ok((cmd.run(config, client, db, storage), task_manager))
100+
runner.sync_run(|config| {
101+
let PartialComponents { client, backend, .. } = new_partial(&config)?;
102+
103+
// This switch needs to be in the client, since the client decides
104+
// which sub-commands it wants to support.
105+
match cmd {
106+
BenchmarkCmd::Pallet(cmd) => {
107+
if !cfg!(feature = "runtime-benchmarks") {
108+
return Err(
109+
"Runtime benchmarking wasn't enabled when building the node. \
110+
You can enable it with `--features runtime-benchmarks`."
111+
.into(),
112+
)
113+
}
114+
115+
cmd.run::<Block, ExecutorDispatch>(config)
116+
},
117+
BenchmarkCmd::Block(cmd) => cmd.run(client),
118+
BenchmarkCmd::Storage(cmd) => {
119+
let db = backend.expose_db();
120+
let storage = backend.expose_storage();
121+
122+
cmd.run(config, client, db, storage)
123+
},
124+
BenchmarkCmd::Overhead(cmd) => {
125+
let ext_builder = BenchmarkExtrinsicBuilder::new(client.clone());
126+
127+
cmd.run(config, client, inherent_benchmark_data()?, Arc::new(ext_builder))
128+
},
129+
}
134130
})
135131
},
136132
Some(Subcommand::Key(cmd)) => cmd.run(&cli),

0 commit comments

Comments
 (0)