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

Add benchmark extrinsic command #11456

Merged
merged 27 commits into from
Jul 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
051fa6e
Benchmark extrinsic
ggwpez May 18, 2022
43cedac
Reduce warmup and repeat
ggwpez May 18, 2022
5af2d41
Make ExistentialDeposit public
ggwpez May 18, 2022
6d25d10
Add 'bechmark extrinsic' command
ggwpez May 18, 2022
b1d07ee
fmt
ggwpez May 18, 2022
d8e2cdc
Add --list and cleanup
ggwpez May 31, 2022
10361dd
Merge branch 'master' into oty-bench-extrinsic
ggwpez May 31, 2022
9a850ea
Merge remote-tracking branch 'origin/master' into oty-bench-extrinsic
ggwpez Jun 1, 2022
4ecc0d3
Unrelated Clippy
ggwpez Jun 1, 2022
603d0ae
Clippy
ggwpez Jun 1, 2022
a336902
Fix tests and doc
ggwpez Jun 1, 2022
b6d1f25
Merge remote-tracking branch 'origin/master' into oty-bench-extrinsic
ggwpez Jun 1, 2022
abf1326
Merge remote-tracking branch 'origin/master' into oty-bench-extrinsic
ggwpez Jun 11, 2022
5efa7c1
Move implementations up + fmt
ggwpez Jun 17, 2022
fba7975
Dont use parameter_types macro
ggwpez Jun 17, 2022
83f8fcf
Cache to_lowercase() call
ggwpez Jun 17, 2022
3688b13
Spelling
ggwpez Jun 17, 2022
58d7d3f
Use correct nightly for fmt...
ggwpez Jun 17, 2022
7aea64b
Rename ED
ggwpez Jun 17, 2022
b5a193e
Fix compile
ggwpez Jun 17, 2022
87136b1
Merge remote-tracking branch 'origin/master' into oty-bench-extrinsic
ggwpez Jun 17, 2022
a6eaec5
Subtract block base weight
ggwpez Jul 14, 2022
d94db3d
Fixes
ggwpez Jul 14, 2022
e51a14f
Merge remote-tracking branch 'origin/master' into oty-bench-extrinsic
ggwpez Jul 14, 2022
8bc5762
Merge remote-tracking branch 'origin/master' into oty-bench-extrinsic
ggwpez Jul 18, 2022
929eaa0
Use tmp folder for test
ggwpez Jul 18, 2022
f603a06
Fix test
ggwpez Jul 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//! Contains code to setup the command invocations in [`super::command`] which would
//! otherwise bloat that module.
//! Setup code for [`super::command`] which would otherwise bloat that module.
//!
//! Should only be used for benchmarking as it may break in other contexts.

use crate::service::FullClient;

use node_template_runtime as runtime;
use runtime::SystemCall;
use runtime::{AccountId, Balance, BalancesCall, SystemCall};
use sc_cli::Result;
use sc_client_api::BlockBackend;
use sp_core::{Encode, Pair};
Expand All @@ -35,19 +36,27 @@ use std::{sync::Arc, time::Duration};
/// Generates extrinsics for the `benchmark overhead` command.
///
/// Note: Should only be used for benchmarking.
pub struct BenchmarkExtrinsicBuilder {
pub struct RemarkBuilder {
client: Arc<FullClient>,
}

impl BenchmarkExtrinsicBuilder {
impl RemarkBuilder {
/// Creates a new [`Self`] from the given client.
pub fn new(client: Arc<FullClient>) -> Self {
Self { client }
}
}
ggwpez marked this conversation as resolved.
Show resolved Hide resolved

impl frame_benchmarking_cli::ExtrinsicBuilder for BenchmarkExtrinsicBuilder {
fn remark(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
impl frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder {
fn pallet(&self) -> &str {
"system"
}

fn extrinsic(&self) -> &str {
"remark"
}

fn build(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
let acc = Sr25519Keyring::Bob.pair();
let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic(
self.client.as_ref(),
Expand All @@ -61,6 +70,49 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for BenchmarkExtrinsicBuilder {
}
}

/// Generates `Balances::TransferKeepAlive` extrinsics for the benchmarks.
///
/// Note: Should only be used for benchmarking.
pub struct TransferKeepAliveBuilder {
client: Arc<FullClient>,
dest: AccountId,
value: Balance,
}

impl TransferKeepAliveBuilder {
/// Creates a new [`Self`] from the given client.
pub fn new(client: Arc<FullClient>, dest: AccountId, value: Balance) -> Self {
Self { client, dest, value }
}
}

impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder {
fn pallet(&self) -> &str {
"balances"
}

fn extrinsic(&self) -> &str {
"transfer_keep_alive"
}

fn build(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
let acc = Sr25519Keyring::Bob.pair();
let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic(
self.client.as_ref(),
acc,
BalancesCall::transfer_keep_alive {
dest: self.dest.clone().into(),
value: self.value.into(),
}
.into(),
nonce,
)
.into();

Ok(extrinsic)
}
}

/// Create a transaction using the given `call`.
///
/// Note: Should only be used for benchmarking.
Expand Down
26 changes: 20 additions & 6 deletions bin/node-template/node/src/command.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use crate::{
benchmarking::{inherent_benchmark_data, RemarkBuilder, TransferKeepAliveBuilder},
chain_spec,
cli::{Cli, Subcommand},
command_helper::{inherent_benchmark_data, BenchmarkExtrinsicBuilder},
service,
};
use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE};
use node_template_runtime::Block;
use frame_benchmarking_cli::{BenchmarkCmd, ExtrinsicFactory, SUBSTRATE_REFERENCE_HARDWARE};
use node_template_runtime::{Block, EXISTENTIAL_DEPOSIT};
use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli};
use sc_service::PartialComponents;
use std::sync::Arc;
use sp_keyring::Sr25519Keyring;

impl SubstrateCli for Cli {
fn impl_name() -> String {
Expand Down Expand Up @@ -137,9 +137,23 @@ pub fn run() -> sc_cli::Result<()> {
},
BenchmarkCmd::Overhead(cmd) => {
let PartialComponents { client, .. } = service::new_partial(&config)?;
let ext_builder = BenchmarkExtrinsicBuilder::new(client.clone());
let ext_builder = RemarkBuilder::new(client.clone());

cmd.run(config, client, inherent_benchmark_data()?, Arc::new(ext_builder))
cmd.run(config, client, inherent_benchmark_data()?, &ext_builder)
},
BenchmarkCmd::Extrinsic(cmd) => {
let PartialComponents { client, .. } = service::new_partial(&config)?;
// Register the *Remark* and *TKA* builders.
let ext_factory = ExtrinsicFactory(vec![
Box::new(RemarkBuilder::new(client.clone())),
Box::new(TransferKeepAliveBuilder::new(
client.clone(),
Sr25519Keyring::Alice.to_account_id(),
EXISTENTIAL_DEPOSIT,
)),
]);

cmd.run(client, inherent_benchmark_data()?, &ext_factory)
},
BenchmarkCmd::Machine(cmd) =>
cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()),
Expand Down
2 changes: 1 addition & 1 deletion bin/node-template/node/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
mod chain_spec;
#[macro_use]
mod service;
mod benchmarking;
mod cli;
mod command;
mod command_helper;
mod rpc;

fn main() -> sc_cli::Result<()> {
Expand Down
5 changes: 4 additions & 1 deletion bin/node-template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ impl pallet_timestamp::Config for Runtime {
type WeightInfo = ();
}

/// Existential deposit.
pub const EXISTENTIAL_DEPOSIT: u128 = 500;

ggwpez marked this conversation as resolved.
Show resolved Hide resolved
impl pallet_balances::Config for Runtime {
type MaxLocks = ConstU32<50>;
type MaxReserves = ();
Expand All @@ -243,7 +246,7 @@ impl pallet_balances::Config for Runtime {
/// The ubiquitous event type.
type Event = Event;
type DustRemoval = ();
type ExistentialDeposit = ConstU128<500>;
type ExistentialDeposit = ConstU128<EXISTENTIAL_DEPOSIT>;
type AccountStore = System;
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,45 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//! Contains code to setup the command invocations in [`super::command`] which would
//! otherwise bloat that module.
//! Setup code for [`super::command`] which would otherwise bloat that module.
//!
//! Should only be used for benchmarking as it may break in other contexts.

use crate::service::{create_extrinsic, FullClient};

use node_runtime::SystemCall;
use node_primitives::{AccountId, Balance};
use node_runtime::{BalancesCall, SystemCall};
use sc_cli::Result;
use sp_inherents::{InherentData, InherentDataProvider};
use sp_keyring::Sr25519Keyring;
use sp_runtime::OpaqueExtrinsic;

use std::{sync::Arc, time::Duration};

/// Generates extrinsics for the `benchmark overhead` command.
pub struct BenchmarkExtrinsicBuilder {
/// Generates `System::Remark` extrinsics for the benchmarks.
///
/// Note: Should only be used for benchmarking.
pub struct RemarkBuilder {
client: Arc<FullClient>,
}

impl BenchmarkExtrinsicBuilder {
impl RemarkBuilder {
/// Creates a new [`Self`] from the given client.
pub fn new(client: Arc<FullClient>) -> Self {
Self { client }
}
}

impl frame_benchmarking_cli::ExtrinsicBuilder for BenchmarkExtrinsicBuilder {
fn remark(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
impl frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder {
fn pallet(&self) -> &str {
"system"
}

fn extrinsic(&self) -> &str {
"remark"
}

fn build(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
let acc = Sr25519Keyring::Bob.pair();
let extrinsic: OpaqueExtrinsic = create_extrinsic(
self.client.as_ref(),
Expand All @@ -56,6 +68,48 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for BenchmarkExtrinsicBuilder {
}
}

/// Generates `Balances::TransferKeepAlive` extrinsics for the benchmarks.
///
/// Note: Should only be used for benchmarking.
pub struct TransferKeepAliveBuilder {
client: Arc<FullClient>,
dest: AccountId,
value: Balance,
}

impl TransferKeepAliveBuilder {
/// Creates a new [`Self`] from the given client.
pub fn new(client: Arc<FullClient>, dest: AccountId, value: Balance) -> Self {
Self { client, dest, value }
}
}

impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder {
fn pallet(&self) -> &str {
"balances"
}

fn extrinsic(&self) -> &str {
"transfer_keep_alive"
}

fn build(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
let acc = Sr25519Keyring::Bob.pair();
let extrinsic: OpaqueExtrinsic = create_extrinsic(
self.client.as_ref(),
acc,
BalancesCall::transfer_keep_alive {
dest: self.dest.clone().into(),
value: self.value.into(),
},
Some(nonce),
)
.into();

Ok(extrinsic)
}
}

/// Generates inherent data for the `benchmark overhead` command.
pub fn inherent_benchmark_data() -> Result<InherentData> {
let mut inherent_data = InherentData::new();
Expand Down
23 changes: 19 additions & 4 deletions bin/node/cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use super::command_helper::{inherent_benchmark_data, BenchmarkExtrinsicBuilder};
use super::benchmarking::{inherent_benchmark_data, RemarkBuilder, TransferKeepAliveBuilder};
use crate::{
chain_spec, service,
service::{new_partial, FullClient},
Expand All @@ -25,9 +25,10 @@ use crate::{
use frame_benchmarking_cli::*;
use node_executor::ExecutorDispatch;
use node_primitives::Block;
use node_runtime::RuntimeApi;
use node_runtime::{ExistentialDeposit, RuntimeApi};
use sc_cli::{ChainSpec, Result, RuntimeVersion, SubstrateCli};
use sc_service::PartialComponents;
use sp_keyring::Sr25519Keyring;

use std::sync::Arc;

Expand Down Expand Up @@ -126,9 +127,23 @@ pub fn run() -> Result<()> {
},
BenchmarkCmd::Overhead(cmd) => {
let PartialComponents { client, .. } = new_partial(&config)?;
let ext_builder = BenchmarkExtrinsicBuilder::new(client.clone());
let ext_builder = RemarkBuilder::new(client.clone());

cmd.run(config, client, inherent_benchmark_data()?, Arc::new(ext_builder))
cmd.run(config, client, inherent_benchmark_data()?, &ext_builder)
},
BenchmarkCmd::Extrinsic(cmd) => {
let PartialComponents { client, .. } = service::new_partial(&config)?;
// Register the *Remark* and *TKA* builders.
let ext_factory = ExtrinsicFactory(vec![
Box::new(RemarkBuilder::new(client.clone())),
Box::new(TransferKeepAliveBuilder::new(
client.clone(),
Sr25519Keyring::Alice.to_account_id(),
ExistentialDeposit::get(),
)),
]);

cmd.run(client, inherent_benchmark_data()?, &ext_factory)
},
BenchmarkCmd::Machine(cmd) =>
cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()),
Expand Down
4 changes: 2 additions & 2 deletions bin/node/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ pub mod chain_spec;
#[macro_use]
pub mod service;
#[cfg(feature = "cli")]
mod benchmarking;
#[cfg(feature = "cli")]
mod cli;
#[cfg(feature = "cli")]
mod command;
#[cfg(feature = "cli")]
mod command_helper;

#[cfg(feature = "cli")]
pub use cli::*;
Expand Down
46 changes: 46 additions & 0 deletions bin/node/cli/tests/benchmark_extrinsic_works.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// This file is part of Substrate.

// Copyright (C) 2022 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program 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.

// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.

use assert_cmd::cargo::cargo_bin;
use std::process::Command;
use tempfile::tempdir;

/// Tests that the `benchmark extrinsic` command works for
/// remark and transfer_keep_alive within the substrate dev runtime.
#[test]
fn benchmark_extrinsic_works() {
benchmark_extrinsic("system", "remark");
benchmark_extrinsic("balances", "transfer_keep_alive");
}

/// Checks that the `benchmark extrinsic` command works for the given pallet and extrinsic.
fn benchmark_extrinsic(pallet: &str, extrinsic: &str) {
let base_dir = tempdir().expect("could not create a temp dir");

let status = Command::new(cargo_bin("substrate"))
.args(&["benchmark", "extrinsic", "--dev"])
.arg("-d")
.arg(base_dir.path())
.args(&["--pallet", pallet, "--extrinsic", extrinsic])
// Run with low repeats for faster execution.
.args(["--warmup=10", "--repeat=10", "--max-ext-per-block=10"])
.status()
.unwrap();

assert!(status.success());
}
Loading