Add benchmark extrinsic command (#11456)

* Benchmark extrinsic

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Reduce warmup and repeat

Running this 1000 times with a full block takes ~33 minutes 🙈.
Reducing it to ~3 minutes per default.

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Make ExistentialDeposit public

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add 'bechmark extrinsic' command

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* fmt

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Add --list and cleanup

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Unrelated Clippy

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Clippy

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix tests and doc

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Move implementations up + fmt

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Dont use parameter_types macro

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Cache to_lowercase() call

The .to_lowercase() on the builder is actually not needes
since its already documented to only return lower case.

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Spelling

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Use correct nightly for fmt...

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Rename ED

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix compile

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Subtract block base weight

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fixes

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Use tmp folder for test

This should already be the case since --dev is passed but
somehow not...

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix test

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
This commit is contained in:
Oliver Tale-Yazdi
2022-07-19 08:10:15 +02:00
committed by GitHub
parent 3d95c270e0
commit 1843ae83ba
16 changed files with 537 additions and 109 deletions
@@ -16,12 +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::{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;
@@ -29,20 +31,30 @@ 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(),
@@ -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();
+19 -4
View File
@@ -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},
@@ -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;
@@ -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()),
+2 -2
View File
@@ -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::*;
@@ -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());
}