Benchmark macro (#4962)

* MAcro benchamrks

* Iterative macro

* Tidying it up.

* Macro improvements

* Bits..

* Last benchmaks.

* Repo benchmark macro

* Add the possibility of evaluating arbitrary expressions in a
benchmaark

* Better syntax and docs

* Update `BenchmarkParameter`

* Add `ignore` to sudo-code in docs

* First try of timestamp implementation.

* Fix macro docs, remove warnings.

* Use macro in balances pallet.

* Make some space in frame benchmarking.

* Remove _benchmarks_seed variable.

* Bump impl_version.

Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
Co-authored-by: Marcio Diaz <marcio@parity.io>
This commit is contained in:
Gavin Wood
2020-02-20 17:20:16 +01:00
committed by GitHub
parent 504914b0a6
commit f5176ba377
9 changed files with 5098 additions and 5266 deletions
+9 -80
View File
@@ -21,88 +21,17 @@ use super::*;
use sp_std::prelude::*;
use frame_system::RawOrigin;
use frame_benchmarking::{
BenchmarkResults, BenchmarkParameter, selected_benchmark, benchmarking,
Benchmarking, BenchmarkingSetup,
};
use frame_benchmarking::benchmarks;
use sp_runtime::traits::Dispatchable;
/// Benchmark `set` extrinsic.
struct Set;
impl<T: Trait> BenchmarkingSetup<T, Call<T>, RawOrigin<T::AccountId>> for Set {
fn components(&self) -> Vec<(BenchmarkParameter, u32, u32)> {
vec![
// Current time ("Now")
(BenchmarkParameter::N, 1, 100),
]
const MAX_TIME: u32 = 100;
benchmarks! {
_ {
let n in 1 .. MAX_TIME => ();
}
fn instance(&self, components: &[(BenchmarkParameter, u32)])
-> Result<(Call<T>, RawOrigin<T::AccountId>), &'static str>
{
let user_origin = RawOrigin::None;
let now = components.iter().find(|&c| c.0 == BenchmarkParameter::N).unwrap().1;
// Return the `set` call
Ok((Call::<T>::set(now.into()), user_origin))
}
}
selected_benchmark!(Set);
impl<T: Trait> Benchmarking<BenchmarkResults> for Module<T> {
fn run_benchmark(extrinsic: Vec<u8>, steps: u32, repeat: u32) -> Result<Vec<BenchmarkResults>, &'static str> {
// Map the input to the selected benchmark.
let selected_benchmark = match extrinsic.as_slice() {
b"set" => SelectedBenchmark::Set,
_ => return Err("Could not find extrinsic."),
};
// Warm up the DB
benchmarking::commit_db();
benchmarking::wipe_db();
let components = <SelectedBenchmark as BenchmarkingSetup<T, crate::Call<T>, RawOrigin<T::AccountId>>>::components(&selected_benchmark);
let mut results: Vec<BenchmarkResults> = Vec::new();
// Select the component we will be benchmarking. Each component will be benchmarked.
for (name, low, high) in components.iter() {
// Create up to `STEPS` steps for that component between high and low.
let step_size = ((high - low) / steps).max(1);
let num_of_steps = (high - low) / step_size;
for s in 0..num_of_steps {
// This is the value we will be testing for component `name`
let component_value = low + step_size * s;
// Select the mid value for all the other components.
let c: Vec<(BenchmarkParameter, u32)> = components.iter()
.map(|(n, l, h)|
(*n, if n == name { component_value } else { (h - l) / 2 + l })
).collect();
// Run the benchmark `repeat` times.
for _ in 0..repeat {
// Set up the externalities environment for the setup we want to benchmark.
let (call, caller) = <SelectedBenchmark as BenchmarkingSetup<
T,
Call<T>,
RawOrigin<T::AccountId>,
>>::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.
benchmarking::commit_db();
// Run the benchmark.
let start = benchmarking::current_time();
call.dispatch(caller.into())?;
let finish = benchmarking::current_time();
let elapsed = finish - start;
results.push((c.clone(), elapsed));
// Wipe the DB back to the genesis state.
benchmarking::wipe_db();
}
}
}
return Ok(results);
}
set {
let n in ...;
}: _(RawOrigin::None, n.into())
}