pub use super::*;
#[macro_export]
macro_rules! whitelist {
($acc:ident) => {
frame_benchmarking::benchmarking::add_to_whitelist(
frame_system::Account::<T>::hashed_key_for(&$acc).into(),
);
};
}
#[macro_export]
macro_rules! benchmarks {
(
$( $rest:tt )*
) => {
$crate::benchmarks_iter!(
{ }
{ }
{ }
( )
( )
( )
( )
$( $rest )*
);
}
}
#[macro_export]
macro_rules! benchmarks_instance {
(
$( $rest:tt )*
) => {
$crate::benchmarks_iter!(
{ }
{ I: Instance }
{ }
( )
( )
( )
( )
$( $rest )*
);
}
}
#[macro_export]
macro_rules! benchmarks_instance_pallet {
(
$( $rest:tt )*
) => {
$crate::benchmarks_iter!(
{ }
{ I: 'static }
{ }
( )
( )
( )
( )
$( $rest )*
);
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! benchmarks_iter {
(
{ }
{ $( $instance:ident: $instance_bound:tt )? }
{ $( $where_clause:tt )* }
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
impl_benchmark_test_suite!(
$bench_module:ident,
$new_test_ext:expr,
$test:path
$(, $( $args:tt )* )?);
$( $rest:tt )*
) => {
$crate::benchmarks_iter! {
{ $bench_module, $new_test_ext, $test $(, $( $args )* )? }
{ $( $instance: $instance_bound )? }
{ $( $where_clause )* }
( $( $names )* )
( $( $names_extra )* )
( $( $names_skip_meta )* )
( $( $pov_name: $( $storage = $pov_mode )*; )* )
$( $rest )*
}
};
(
{ }
{ $( $instance:ident: $instance_bound:tt )? }
{ $( $where_clause:tt )* }
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
impl_benchmark_test_suite!(
$bench_module:ident,
$new_test_ext:expr,
$test:path
$(, $( $args:tt )* )?)
$( $rest:tt )*
) => {
$crate::benchmarks_iter! {
{ $bench_module, $new_test_ext, $test $(, $( $args )* )? }
{ $( $instance: $instance_bound )? }
{ $( $where_clause )* }
( $( $names )* )
( $( $names_extra )* )
( $( $names_skip_meta )* )
( $( $pov_name: $( $storage = $pov_mode )*; )* )
$( $rest )*
}
};
(
{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
{ $( $instance:ident: $instance_bound:tt )? }
{ $( $where_clause:tt )* }
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
where_clause { where $( $where_bound:tt )* }
$( $rest:tt )*
) => {
$crate::benchmarks_iter! {
{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
{ $( $instance: $instance_bound)? }
{ $( $where_bound )* }
( $( $names )* )
( $( $names_extra )* )
( $( $names_skip_meta )* )
( $( $pov_name: $( $storage = $pov_mode )*; )* )
$( $rest )*
}
};
(
{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
{ $( $instance:ident: $instance_bound:tt )? }
{ $( $where_clause:tt )* }
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
#[skip_meta]
$( #[ $($attributes:tt)+ ] )*
$name:ident
$( $rest:tt )*
) => {
$crate::benchmarks_iter! {
{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
{ $( $instance: $instance_bound )? }
{ $( $where_clause )* }
( $( $names )* )
( $( $names_extra )* )
( $( $names_skip_meta )* $name )
( $( $pov_name: $( $storage = $pov_mode )*; )* )
$( #[ $( $attributes )+ ] )*
$name
$( $rest )*
}
};
(
{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
{ $( $instance:ident: $instance_bound:tt )? }
{ $( $where_clause:tt )* }
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
#[extra]
$( #[ $($attributes:tt)+ ] )*
$name:ident
$( $rest:tt )*
) => {
$crate::benchmarks_iter! {
{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
{ $( $instance: $instance_bound )? }
{ $( $where_clause )* }
( $( $names )* )
( $( $names_extra )* $name )
( $( $names_skip_meta )* )
( $( $pov_name: $( $storage = $pov_mode )*; )* )
$( #[ $( $attributes )+ ] )*
$name
$( $rest )*
}
};
(
{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
{ $( $instance:ident: $instance_bound:tt )? }
{ $( $where_clause:tt )* }
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
( $( $old_pov_name:ident: $( $old_storage:path = $old_pov_mode:ident )*; )* )
#[pov_mode = $mode:ident $( { $( $storage:path: $pov_mode:ident )* } )?]
$( #[ $($attributes:tt)+ ] )*
$name:ident
$( $rest:tt )*
) => {
$crate::benchmarks_iter! {
{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
{ $( $instance: $instance_bound )? }
{ $( $where_clause )* }
( $( $names )* )
( $( $names_extra )* )
( $( $names_skip_meta )* )
( $name: ALL = $mode $($( $storage = $pov_mode )*)?; $( $old_pov_name: $( $old_storage = $old_pov_mode )*; )* )
$( #[ $( $attributes )+ ] )*
$name
$( $rest )*
}
};
(
{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
{ $( $instance:ident: $instance_bound:tt )? }
{ $( $where_clause:tt )* }
( $( $names:tt )* ) ( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
$name:ident { $( $code:tt )* }: _ $(< $origin_type:ty>)? ( $origin:expr $( , $arg:expr )* )
verify $postcode:block
$( $rest:tt )*
) => {
$crate::benchmarks_iter! {
{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
{ $( $instance: $instance_bound )? }
{ $( $where_clause )* }
( $( $names )* )
( $( $names_extra )* )
( $( $names_skip_meta )* )
( $( $pov_name: $( $storage = $pov_mode )*; )* )
$name { $( $code )* }: $name $(< $origin_type >)? ( $origin $( , $arg )* )
verify $postcode
$( $rest )*
}
};
(
{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
{ $( $instance:ident: $instance_bound:tt )? }
{ $( $where_clause:tt )* }
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
$name:ident { $( $code:tt )* }: $dispatch:ident $(<$origin_type:ty>)? ( $origin:expr $( , $arg:expr )* )
verify $postcode:block
$( $rest:tt )*
) => {
$crate::__private::paste::paste! {
$crate::benchmarks_iter! {
{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
{ $( $instance: $instance_bound )? }
{ $( $where_clause )* }
( $( $names )* )
( $( $names_extra )* )
( $( $names_skip_meta )* )
( $( $pov_name: $( $storage = $pov_mode )*; )* )
$name {
$( $code )*
let __call = Call::<
T
$( , $instance )?
>:: [< new_call_variant_ $dispatch >] (
$($arg),*
);
let __benchmarked_call_encoded = $crate::__private::codec::Encode::encode(
&__call
);
}: {
let __call_decoded = <
Call<T $(, $instance )?>
as $crate::__private::codec::Decode
>::decode(&mut &__benchmarked_call_encoded[..])
.expect("call is encoded above, encoding must be correct");
let __origin = $crate::to_origin!($origin $(, $origin_type)?);
<Call<T $(, $instance)? > as $crate::__private::traits::UnfilteredDispatchable
>::dispatch_bypass_filter(__call_decoded, __origin)?;
}
verify $postcode
$( $rest )*
}
}
};
(
{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
{ $( $instance:ident: $instance_bound:tt )? }
{ $( $where_clause:tt )* }
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
$name:ident { $( $code:tt )* }: $eval:block
verify $postcode:block
$( $rest:tt )*
) => {
$crate::benchmark_backend! {
{ $( $instance: $instance_bound )? }
$name
{ $( $where_clause )* }
{ }
{ $eval }
{ $( $code )* }
$postcode
}
#[cfg(test)]
$crate::impl_benchmark_test!(
{ $( $where_clause )* }
{ $( $instance: $instance_bound )? }
$name
);
$crate::benchmarks_iter!(
{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
{ $( $instance: $instance_bound )? }
{ $( $where_clause )* }
( $( $names )* { $( $instance )? } $name )
( $( $names_extra )* )
( $( $names_skip_meta )* )
( $( $pov_name: $( $storage = $pov_mode )*; )* )
$( $rest )*
);
};
(
{ $bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )? }
{ $( $instance:ident: $instance_bound:tt )? }
{ $( $where_clause:tt )* }
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
) => {
$crate::selected_benchmark!(
{ $( $where_clause)* }
{ $( $instance: $instance_bound )? }
$( $names )*
);
$crate::impl_benchmark!(
{ $( $where_clause )* }
{ $( $instance: $instance_bound )? }
( $( $names )* )
( $( $names_extra ),* )
( $( $names_skip_meta ),* )
( $( $pov_name: $( $storage = $pov_mode )*; )* )
);
$crate::impl_test_function!(
( $( $names )* )
( $( $names_extra )* )
( $( $names_skip_meta )* )
$bench_module,
$new_test_ext,
$test
$(, $( $args )* )?
);
};
(
{ }
{ $( $instance:ident: $instance_bound:tt )? }
{ $( $where_clause:tt )* }
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
) => {
$crate::selected_benchmark!(
{ $( $where_clause)* }
{ $( $instance: $instance_bound )? }
$( $names )*
);
$crate::impl_benchmark!(
{ $( $where_clause )* }
{ $( $instance: $instance_bound )? }
( $( $names )* )
( $( $names_extra ),* )
( $( $names_skip_meta ),* )
( $( $pov_name: $( $storage = $pov_mode )*; )* )
);
};
(
{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
{ $( $instance:ident: $instance_bound:tt )? }
{ $( $where_clause:tt )* }
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
$name:ident { $( $code:tt )* }: _ $(<$origin_type:ty>)? ( $origin:expr $( , $arg:expr )* )
$( $rest:tt )*
) => {
$crate::benchmarks_iter! {
{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
{ $( $instance: $instance_bound )? }
{ $( $where_clause )* }
( $( $names )* )
( $( $names_extra )* )
( $( $names_skip_meta )* )
( $( $pov_name: $( $storage = $pov_mode )*; )* )
$name { $( $code )* }: _ $(<$origin_type>)? ( $origin $( , $arg )* )
verify { }
$( $rest )*
}
};
(
{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
{ $( $instance:ident: $instance_bound:tt )? }
{ $( $where_clause:tt )* }
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
$name:ident { $( $code:tt )* }: $dispatch:ident $(<$origin_type:ty>)? ( $origin:expr $( , $arg:expr )* )
$( $rest:tt )*
) => {
$crate::benchmarks_iter! {
{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
{ $( $instance: $instance_bound )? }
{ $( $where_clause )* }
( $( $names )* )
( $( $names_extra )* )
( $( $names_skip_meta )* )
( $( $pov_name: $( $storage = $pov_mode )*; )* )
$name { $( $code )* }: $dispatch $(<$origin_type>)? ( $origin $( , $arg )* )
verify { }
$( $rest )*
}
};
(
{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
{ $( $instance:ident: $instance_bound:tt )? }
{ $( $where_clause:tt )* }
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
$name:ident { $( $code:tt )* }: $(<$origin_type:ty>)? $eval:block
$( $rest:tt )*
) => {
$crate::benchmarks_iter!(
{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
{ $( $instance: $instance_bound )? }
{ $( $where_clause )* }
( $( $names )* )
( $( $names_extra )* )
( $( $names_skip_meta )* )
( $( $pov_name: $( $storage = $pov_mode )*; )* )
$name { $( $code )* }: $(<$origin_type>)? $eval
verify { }
$( $rest )*
);
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! to_origin {
($origin:expr) => {
$origin.into()
};
($origin:expr, $origin_type:ty) => {
<<T as frame_system::Config>::RuntimeOrigin as From<$origin_type>>::from($origin)
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! benchmark_backend {
(
{ $( $instance:ident: $instance_bound:tt )? }
$name:ident
{ $( $where_clause:tt )* }
{ $( PRE { $( $pre_parsed:tt )* } )* }
{ $eval:block }
{
let $pre_id:tt $( : $pre_ty:ty )? = $pre_ex:expr;
$( $rest:tt )*
}
$postcode:block
) => {
$crate::benchmark_backend! {
{ $( $instance: $instance_bound )? }
$name
{ $( $where_clause )* }
{
$( PRE { $( $pre_parsed )* } )*
PRE { $pre_id , $( $pre_ty , )? $pre_ex }
}
{ $eval }
{ $( $rest )* }
$postcode
}
};
(
{ $( $instance:ident: $instance_bound:tt )? }
$name:ident
{ $( $where_clause:tt )* }
{ $( $parsed:tt )* }
{ $eval:block }
{
let $param:ident in ( $param_from:expr ) .. $param_to:expr => $param_instancer:expr;
$( $rest:tt )*
}
$postcode:block
) => {
$crate::benchmark_backend! {
{ $( $instance: $instance_bound )? }
$name
{ $( $where_clause )* }
{
$( $parsed )*
PARAM { $param , $param_from , $param_to , $param_instancer }
}
{ $eval }
{ $( $rest )* }
$postcode
}
};
(
{ $( $instance:ident: $instance_bound:tt )? }
$name:ident
{ $( $where_clause:tt )* }
{ $( $parsed:tt )* }
{ $eval:block }
{
let $param:ident in $param_from:tt .. $param_to:expr => $param_instancer:expr ;
$( $rest:tt )*
}
$postcode:block
) => {
$crate::benchmark_backend! {
{ $( $instance: $instance_bound )? }
$name
{ $( $where_clause )* }
{ $( $parsed )* }
{ $eval }
{
let $param in ( $param_from ) .. $param_to => $param_instancer;
$( $rest )*
}
$postcode
}
};
(
{ $( $instance:ident: $instance_bound:tt )? }
$name:ident
{ $( $where_clause:tt )* }
{ $( $parsed:tt )* }
{ $eval:block }
{
let $param:ident in $param_from:tt .. $param_to:expr;
$( $rest:tt )*
}
$postcode:block
) => {
$crate::benchmark_backend! {
{ $( $instance: $instance_bound )? }
$name
{ $( $where_clause )* }
{ $( $parsed )* }
{ $eval }
{
let $param in $param_from .. $param_to => ();
$( $rest )*
}
$postcode
}
};
(
{ $( $instance:ident: $instance_bound:tt )? }
$name:ident
{ $( $where_clause:tt )* }
{
$( PRE { $pre_id:tt , $( $pre_ty:ty , )? $pre_ex:expr } )*
$( PARAM { $param:ident , $param_from:expr , $param_to:expr , $param_instancer:expr } )*
}
{ $eval:block }
{ $( $post:tt )* }
$postcode:block
) => {
#[allow(non_camel_case_types)]
struct $name;
#[allow(unused_variables)]
impl<T: Config $( <$instance>, $instance: $instance_bound )? >
$crate::BenchmarkingSetup<T $(, $instance)? > for $name
where $( $where_clause )*
{
fn components(&self) -> $crate::__private::Vec<($crate::BenchmarkParameter, u32, u32)> {
$crate::__private::vec! [
$(
($crate::BenchmarkParameter::$param, $param_from, $param_to)
),*
]
}
fn instance(
&self,
recording: &mut impl $crate::Recording,
components: &[($crate::BenchmarkParameter, u32)],
verify: bool
) -> Result<(), $crate::BenchmarkError> {
$(
let $param = components.iter()
.find(|&c| c.0 == $crate::BenchmarkParameter::$param)
.ok_or("Could not find component in benchmark preparation.")?
.1;
)*
$(
let $pre_id $( : $pre_ty )? = $pre_ex;
)*
$( $param_instancer ; )*
$( $post )*
recording.start();
$eval;
recording.stop();
if verify {
$postcode;
}
Ok(())
}
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! impl_bench_case_tests {
(
{ $module:ident, $new_test_exec:expr, $exec_name:ident, $test:path, $extra:expr }
{ $( $names_extra:tt )* }
$( { $( $bench_inst:ident )? } $bench:ident )*
)
=> {
$crate::impl_bench_name_tests!(
$module, $new_test_exec, $exec_name, $test, $extra,
{ $( $names_extra )* },
$( { $bench } )+
);
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! impl_bench_name_tests {
(
$module:ident, $new_test_exec:expr, $exec_name:ident, $test:path, $extra:expr,
{ $( $names_extra:tt )* },
{ $name:ident }
) => {
$crate::__private::paste::paste! {
#[test]
fn [<bench_ $name>] () {
$new_test_exec.$exec_name(|| {
if !($extra) {
let disabled = $crate::__private::vec![ $( stringify!($names_extra).as_ref() ),* ];
if disabled.contains(&stringify!($name)) {
$crate::__private::log::debug!(
"extra benchmark skipped - {}",
stringify!($name),
);
return ();
}
}
match std::panic::catch_unwind(|| {
$module::<$test>::[< test_benchmark_ $name >] ()
}) {
Err(err) => {
panic!("{}: {:?}", stringify!($name), err);
},
Ok(Err(err)) => {
match err {
$crate::BenchmarkError::Stop(err) => {
panic!("{}: {:?}", stringify!($name), err);
},
$crate::BenchmarkError::Override(_) => {
$crate::__private::log::error!(
"benchmark error overridden - {}",
stringify!($name),
);
},
$crate::BenchmarkError::Skip => {
$crate::__private::log::debug!(
"benchmark skipped - {}",
stringify!($name),
);
},
$crate::BenchmarkError::Weightless => {
$crate::__private::log::debug!(
"benchmark weightless skipped - {}",
stringify!($name),
);
}
}
},
Ok(Ok(())) => (),
}
});
}
}
};
(
$module:ident, $new_test_exec:expr, $exec_name:ident, $test:path, $extra:expr,
{ $( $names_extra:tt )* },
{ $name:ident } $( { $rest:ident } )+
) => {
$crate::impl_bench_name_tests!($module, $new_test_exec, $exec_name, $test, $extra,
{ $( $names_extra )* }, { $name });
$crate::impl_bench_name_tests!($module, $new_test_exec, $exec_name, $test, $extra,
{ $( $names_extra )* }, $( { $rest } )+);
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! selected_benchmark {
(
{ $( $where_clause:tt )* }
{ $( $instance:ident: $instance_bound:tt )? }
$( { $( $bench_inst:ident )? } $bench:ident )*
) => {
#[allow(non_camel_case_types)]
enum SelectedBenchmark {
$( $bench, )*
}
impl<T: Config $( <$instance>, $instance: $instance_bound )? >
$crate::BenchmarkingSetup<T $(, $instance )? > for SelectedBenchmark
where $( $where_clause )*
{
fn components(&self) -> $crate::__private::Vec<($crate::BenchmarkParameter, u32, u32)> {
match self {
$(
Self::$bench => <
$bench as $crate::BenchmarkingSetup<T $(, $bench_inst)? >
>::components(&$bench),
)*
}
}
fn instance(
&self,
recording: &mut impl $crate::Recording,
components: &[($crate::BenchmarkParameter, u32)],
verify: bool
) -> Result<(), $crate::BenchmarkError> {
match self {
$(
Self::$bench => <
$bench as $crate::BenchmarkingSetup<T $(, $bench_inst)? >
>::instance(&$bench, recording, components, verify),
)*
}
}
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! impl_benchmark {
(
{ $( $where_clause:tt )* }
{ $( $instance:ident: $instance_bound:tt )? }
( $( { $( $name_inst:ident )? } $name:ident )* )
( $( $name_extra:ident ),* )
( $( $name_skip_meta:ident ),* )
( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
) => {
#[cfg(any(feature = "runtime-benchmarks", test))]
impl<T: Config $(<$instance>, $instance: $instance_bound )? >
$crate::Benchmarking for Pallet<T $(, $instance)? >
where T: frame_system::Config, $( $where_clause )*
{
fn benchmarks(extra: bool) -> $crate::__private::Vec<$crate::BenchmarkMetadata> {
$($crate::validate_pov_mode!(
$pov_name: $( $storage = $pov_mode )*;
);)*
let mut all_names = $crate::__private::vec![ $( stringify!($name).as_ref() ),* ];
if !extra {
let extra = [ $( stringify!($name_extra).as_ref() ),* ];
all_names.retain(|x| !extra.contains(x));
}
let pov_modes: $crate::__private::Vec<($crate::__private::Vec<u8>, $crate::__private::Vec<($crate::__private::Vec<u8>, $crate::__private::Vec<u8>)>)> = $crate::__private::vec![
$(
(stringify!($pov_name).as_bytes().to_vec(),
$crate::__private::vec![
$( ( stringify!($storage).as_bytes().to_vec(),
stringify!($pov_mode).as_bytes().to_vec() ), )*
]),
)*
];
all_names.into_iter().map(|benchmark| {
let selected_benchmark = match benchmark {
$( stringify!($name) => SelectedBenchmark::$name, )*
_ => panic!("all benchmarks should be selectable"),
};
let name = benchmark.as_bytes().to_vec();
let components = <
SelectedBenchmark as $crate::BenchmarkingSetup<T $(, $instance)?>
>::components(&selected_benchmark);
$crate::BenchmarkMetadata {
name: name.clone(),
components,
pov_modes: pov_modes.iter().find(|p| p.0 == name).map(|p| p.1.clone()).unwrap_or_default(),
}
}).collect::<$crate::__private::Vec<_>>()
}
fn run_benchmark(
extrinsic: &[u8],
c: &[($crate::BenchmarkParameter, u32)],
whitelist: &[$crate::__private::TrackedStorageKey],
verify: bool,
internal_repeats: u32,
) -> Result<$crate::__private::Vec<$crate::BenchmarkResult>, $crate::BenchmarkError> {
let extrinsic = $crate::__private::str::from_utf8(extrinsic)
.map_err(|_| "`extrinsic` is not a valid utf8 string!")?;
let selected_benchmark = match extrinsic {
$( stringify!($name) => SelectedBenchmark::$name, )*
_ => return Err("Could not find extrinsic.".into()),
};
let mut whitelist = whitelist.to_vec();
let whitelisted_caller_key =
<frame_system::Account::<T> as $crate::__private::storage::StorageMap<_,_>>::hashed_key_for(
$crate::whitelisted_caller::<T::AccountId>()
);
whitelist.push(whitelisted_caller_key.into());
let transactional_layer_key = $crate::__private::TrackedStorageKey::new(
$crate::__private::storage::transactional::TRANSACTION_LEVEL_KEY.into()
);
whitelist.push(transactional_layer_key);
let extrinsic_index = $crate::__private::TrackedStorageKey::new(
$crate::__private::well_known_keys::EXTRINSIC_INDEX.into()
);
whitelist.push(extrinsic_index);
let intrablock_entropy = $crate::__private::TrackedStorageKey::new(
$crate::__private::well_known_keys::INTRABLOCK_ENTROPY.into()
);
whitelist.push(intrablock_entropy);
$crate::benchmarking::set_whitelist(whitelist.clone());
let mut results: $crate::__private::Vec<$crate::BenchmarkResult> = $crate::__private::Vec::new();
let on_before_start = || {
if $crate::__private::Zero::is_zero(&frame_system::Pallet::<T>::block_number()) {
frame_system::Pallet::<T>::set_block_number(1u32.into());
}
$crate::benchmarking::commit_db();
for key in &whitelist {
$crate::__private::storage::unhashed::get_raw(&key.key);
}
$crate::benchmarking::reset_read_write_count();
};
for _ in 0 .. internal_repeats.max(1) {
$crate::__private::defer!($crate::benchmarking::wipe_db());
$crate::__private::log::trace!(
target: "benchmark",
"Start Benchmark: {} ({:?}) verify {}",
extrinsic,
c,
verify
);
let mut recording = $crate::BenchmarkRecording::new(&on_before_start);
<SelectedBenchmark as $crate::BenchmarkingSetup<T $(, $instance)?>>::instance(&selected_benchmark, &mut recording, c, verify)?;
let elapsed_extrinsic = recording.elapsed_extrinsic().expect("elapsed time should be recorded");
let diff_pov = recording.diff_pov().unwrap_or_default();
$crate::benchmarking::commit_db();
$crate::__private::log::trace!(
target: "benchmark",
"End Benchmark: {} ns", elapsed_extrinsic
);
let read_write_count = $crate::benchmarking::read_write_count();
$crate::__private::log::trace!(
target: "benchmark",
"Read/Write Count {:?}", read_write_count
);
$crate::__private::log::trace!(
target: "benchmark",
"Proof sizes: before {:?} after {:?} diff {}", recording.start_pov(), recording.end_pov(), &diff_pov
);
let start_storage_root = $crate::benchmarking::current_time();
$crate::__private::storage_root($crate::__private::StateVersion::V1);
let finish_storage_root = $crate::benchmarking::current_time();
let elapsed_storage_root = finish_storage_root - start_storage_root;
let skip_meta = [ $( stringify!($name_skip_meta).as_ref() ),* ];
let read_and_written_keys = if skip_meta.contains(&extrinsic) {
$crate::__private::vec![(b"Skipped Metadata".to_vec(), 0, 0, false)]
} else {
$crate::benchmarking::get_read_and_written_keys()
};
results.push($crate::BenchmarkResult {
components: c.to_vec(),
extrinsic_time: elapsed_extrinsic,
storage_root_time: elapsed_storage_root,
reads: read_write_count.0,
repeat_reads: read_write_count.1,
writes: read_write_count.2,
repeat_writes: read_write_count.3,
proof_size: diff_pov,
keys: read_and_written_keys,
});
}
return Ok(results);
}
}
#[cfg(test)]
impl<T: Config $(<$instance>, $instance: $instance_bound )? >
Pallet<T $(, $instance)? >
where T: frame_system::Config, $( $where_clause )*
{
#[allow(unused)]
fn test_bench_by_name(name: &[u8]) -> Result<(), $crate::BenchmarkError> {
let name = $crate::__private::str::from_utf8(name)
.map_err(|_| -> $crate::BenchmarkError { "`name` is not a valid utf8 string!".into() })?;
match name {
$( stringify!($name) => {
$crate::__private::paste::paste! { Self::[< test_benchmark_ $name >]() }
} )*
_ => Err("Could not find test for requested benchmark.".into()),
}
}
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! impl_benchmark_test {
(
{ $( $where_clause:tt )* }
{ $( $instance:ident: $instance_bound:tt )? }
$name:ident
) => {
$crate::__private::paste::item! {
#[cfg(test)]
impl<T: Config $(<$instance>, $instance: $instance_bound )? >
Pallet<T $(, $instance)? >
where T: frame_system::Config, $( $where_clause )*
{
#[allow(unused)]
fn [<test_benchmark_ $name>] () -> Result<(), $crate::BenchmarkError> {
let selected_benchmark = SelectedBenchmark::$name;
let components = <
SelectedBenchmark as $crate::BenchmarkingSetup<T, _>
>::components(&selected_benchmark);
let execute_benchmark = |
c: $crate::__private::Vec<($crate::BenchmarkParameter, u32)>
| -> Result<(), $crate::BenchmarkError> {
$crate::__private::defer!($crate::benchmarking::wipe_db());
let on_before_start = || {
if $crate::__private::Zero::is_zero(&frame_system::Pallet::<T>::block_number()) {
frame_system::Pallet::<T>::set_block_number(1u32.into());
}
};
<SelectedBenchmark as $crate::BenchmarkingSetup<T, _>>::test_instance(&selected_benchmark, &c, &on_before_start)
};
if components.is_empty() {
execute_benchmark(Default::default())?;
} else {
let num_values: u32 = if let Ok(ev) = std::env::var("VALUES_PER_COMPONENT") {
ev.parse().map_err(|_| {
$crate::BenchmarkError::Stop(
"Could not parse env var `VALUES_PER_COMPONENT` as u32."
)
})?
} else {
6
};
if num_values < 2 {
return Err("`VALUES_PER_COMPONENT` must be at least 2".into());
}
for (name, low, high) in components.clone().into_iter() {
let mut values = $crate::__private::vec![low];
let diff = (high - low).min(num_values - 1);
let slope = (high - low) as f32 / diff as f32;
for i in 1..=diff {
let value = ((low as f32 + slope * i as f32) as u32)
.clamp(low, high);
values.push(value);
}
for component_value in values {
let c: $crate::__private::Vec<($crate::BenchmarkParameter, u32)> = components
.iter()
.map(|(n, _, h)|
if *n == name {
(*n, component_value)
} else {
(*n, *h)
}
)
.collect();
execute_benchmark(c)?;
}
}
}
Ok(())
}
}
}
};
}
#[macro_export]
macro_rules! impl_benchmark_test_suite {
(
$bench_module:ident,
$new_test_ext:expr,
$test:path
$(, $( $rest:tt )* )?
) => {
$crate::impl_test_function!(
()
()
()
$bench_module,
$new_test_ext,
$test
$(, $( $rest )* )?
);
}
}
#[macro_export]
macro_rules! validate_pov_mode {
() => {};
( $_bench:ident: ; ) => { };
( $_bench:ident: $_car:path = Ignored ; ) => { };
( $bench:ident: $_car:path = Ignored $( $storage:path = $_pov_mode:ident )+; ) => {
compile_error!(
concat!(concat!("`pov_mode = Ignored` is exclusive. Please remove the attribute from keys: ", $( stringify!($storage) )+), " on benchmark '", stringify!($bench), "'"));
};
( $bench:ident: $car:path = Measured $( $storage:path = $pov_mode:ident )*; ) => {
$crate::validate_pov_mode!(
$bench: $( $storage = $pov_mode )*;
);
};
( $bench:ident: $car:path = MaxEncodedLen $( $storage:path = $pov_mode:ident )*; ) => {
$crate::validate_pov_mode!(
$bench: $( $storage = $pov_mode )*;
);
};
( $bench:ident: $key:path = $unknown:ident $( $_storage:path = $_pov_mode:ident )*; ) => {
compile_error!(
concat!("Unknown pov_mode '", stringify!($unknown) ,"' for benchmark '", stringify!($bench), "' on key '", stringify!($key), "'. Must be one of: Ignored, Measured, MaxEncodedLen")
);
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! impl_test_function {
(
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
$bench_module:ident,
$new_test_ext:expr,
$test:path
$(, $( $rest:tt )* )?
) => {
$crate::impl_test_function!(
@cases:
( $( $names )* )
( $( $names_extra )* )
( $( $names_skip_meta )* )
@selected:
$bench_module,
$new_test_ext,
$test,
benchmarks_path = super,
extra = true,
exec_name = execute_with,
@user:
$( $( $rest )* )?
);
};
(
@cases:
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
@selected:
$bench_module:ident,
$new_test_ext:expr,
$test:path,
benchmarks_path = $old:ident,
extra = $extra:expr,
exec_name = $exec_name:ident,
@user:
benchmarks_path = $benchmarks_path:ident
$(, $( $rest:tt )* )?
) => {
$crate::impl_test_function!(
@cases:
( $( $names )* )
( $( $names_extra )* )
( $( $names_skip_meta )* )
@selected:
$bench_module,
$new_test_ext,
$test,
benchmarks_path = $benchmarks_path,
extra = $extra,
exec_name = $exec_name,
@user:
$( $( $rest )* )?
);
};
(
@cases:
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
@selected:
$bench_module:ident,
$new_test_ext:expr,
$test:path,
benchmarks_path = $benchmarks_path:ident,
extra = $old:expr,
exec_name = $exec_name:ident,
@user:
extra = $extra:expr
$(, $( $rest:tt )* )?
) => {
$crate::impl_test_function!(
@cases:
( $( $names )* )
( $( $names_extra )* )
( $( $names_skip_meta )* )
@selected:
$bench_module,
$new_test_ext,
$test,
benchmarks_path = $benchmarks_path,
extra = $extra,
exec_name = $exec_name,
@user:
$( $( $rest )* )?
);
};
(
@cases:
( $( $names:tt )* )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
@selected:
$bench_module:ident,
$new_test_ext:expr,
$test:path,
benchmarks_path = $benchmarks_path:ident,
extra = $extra:expr,
exec_name = $old:ident,
@user:
exec_name = $exec_name:ident
$(, $( $rest:tt )* )?
) => {
$crate::impl_test_function!(
@cases:
( $( $names )* )
( $( $names_extra )* )
( $( $names_skip_meta )* )
@selected:
$bench_module,
$new_test_ext,
$test,
benchmarks_path = $benchmarks_path,
extra = $extra,
exec_name = $exec_name,
@user:
$( $( $rest )* )?
);
};
(
@cases:
( $( $names:tt )+ )
( $( $names_extra:tt )* )
( $( $names_skip_meta:tt )* )
@selected:
$bench_module:ident,
$new_test_ext:expr,
$test:path,
benchmarks_path = $path_to_benchmarks_invocation:ident,
extra = $extra:expr,
exec_name = $exec_name:ident,
@user:
$(,)?
) => {
$crate::impl_bench_case_tests!(
{ $bench_module, $new_test_ext, $exec_name, $test, $extra }
{ $( $names_extra:tt )* }
$($names)+
);
};
(
@cases:
()
()
()
@selected:
$bench_module:ident,
$new_test_ext:expr,
$test:path,
benchmarks_path = $path_to_benchmarks_invocation:ident,
extra = $extra:expr,
exec_name = $exec_name:ident,
@user:
$(,)?
) => {
#[cfg(test)]
mod benchmark_tests {
use super::$bench_module;
#[test]
fn test_benchmarks() {
$new_test_ext.$exec_name(|| {
use $crate::Benchmarking;
let mut anything_failed = false;
println!("failing benchmark tests:");
for benchmark_metadata in $bench_module::<$test>::benchmarks($extra) {
let benchmark_name = &benchmark_metadata.name;
match std::panic::catch_unwind(|| {
$bench_module::<$test>::test_bench_by_name(benchmark_name)
}) {
Err(err) => {
println!(
"{}: {:?}",
$crate::__private::str::from_utf8(benchmark_name)
.expect("benchmark name is always a valid string!"),
err,
);
anything_failed = true;
},
Ok(Err(err)) => {
match err {
$crate::BenchmarkError::Stop(err) => {
println!(
"{}: {:?}",
$crate::__private::str::from_utf8(benchmark_name)
.expect("benchmark name is always a valid string!"),
err,
);
anything_failed = true;
},
$crate::BenchmarkError::Override(_) => {
$crate::__private::log::error!(
"WARNING: benchmark error overridden - {}",
$crate::__private::str::from_utf8(benchmark_name)
.expect("benchmark name is always a valid string!"),
);
},
$crate::BenchmarkError::Skip => {
$crate::__private::log::error!(
"WARNING: benchmark error skipped - {}",
$crate::__private::str::from_utf8(benchmark_name)
.expect("benchmark name is always a valid string!"),
);
}
$crate::BenchmarkError::Weightless => {
$crate::__private::log::error!(
"WARNING: benchmark weightless skipped - {}",
$crate::__private::str::from_utf8(benchmark_name)
.expect("benchmark name is always a valid string!"),
);
}
}
},
Ok(Ok(())) => (),
}
}
assert!(!anything_failed);
});
}
}
};
}
pub fn show_benchmark_debug_info(
instance_string: &[u8],
benchmark: &[u8],
components: &[(BenchmarkParameter, u32)],
verify: &bool,
error_message: &str,
) -> alloc::string::String {
alloc::format!(
"\n* Pallet: {}\n\
* Benchmark: {}\n\
* Components: {:?}\n\
* Verify: {:?}\n\
* Error message: {}",
alloc::str::from_utf8(instance_string)
.expect("it's all just strings ran through the wasm interface. qed"),
alloc::str::from_utf8(benchmark)
.expect("it's all just strings ran through the wasm interface. qed"),
components,
verify,
error_message,
)
}
#[macro_export]
macro_rules! add_benchmark {
( $params:ident, $batches:ident, $name:path, $location:ty ) => {
let name_string = stringify!($name).as_bytes();
let instance_string = stringify!($location).as_bytes();
let (config, whitelist) = $params;
let $crate::BenchmarkConfig {
pallet,
instance,
benchmark,
selected_components,
verify,
internal_repeats,
} = config;
if &pallet[..] == &name_string[..] && &instance[..] == &instance_string[..] {
let benchmark_result = <$location>::run_benchmark(
&benchmark[..],
&selected_components[..],
whitelist,
*verify,
*internal_repeats,
);
let final_results = match benchmark_result {
Ok(results) => Some(results),
Err($crate::BenchmarkError::Override(mut result)) => {
$crate::__private::log::error!(
"WARNING: benchmark error overridden - {}",
$crate::__private::str::from_utf8(benchmark)
.expect("benchmark name is always a valid string!")
);
result.keys.insert(0, (b"Benchmark Override".to_vec(), 0, 0, false));
Some($crate::__private::vec![result])
},
Err($crate::BenchmarkError::Stop(e)) => {
$crate::show_benchmark_debug_info(
instance_string,
benchmark,
selected_components,
verify,
e,
);
return Err(e.into())
},
Err($crate::BenchmarkError::Skip) => {
$crate::__private::log::error!(
"WARNING: benchmark error skipped - {}",
$crate::__private::str::from_utf8(benchmark)
.expect("benchmark name is always a valid string!")
);
None
},
Err($crate::BenchmarkError::Weightless) => {
$crate::__private::log::error!(
"WARNING: benchmark weightless skipped - {}",
$crate::__private::str::from_utf8(benchmark)
.expect("benchmark name is always a valid string!")
);
Some($crate::__private::vec![$crate::BenchmarkResult {
components: selected_components.clone(),
..Default::default()
}])
},
};
if let Some(final_results) = final_results {
$batches.push($crate::BenchmarkBatch {
pallet: name_string.to_vec(),
instance: instance_string.to_vec(),
benchmark: benchmark.clone(),
results: final_results,
});
}
}
};
}
#[macro_export]
macro_rules! list_benchmark {
( $list:ident, $extra:ident, $name:path, $location:ty ) => {
let pallet_string = stringify!($name).as_bytes();
let instance_string = stringify!($location).as_bytes();
let benchmarks = <$location>::benchmarks($extra);
let pallet_benchmarks = BenchmarkList {
pallet: pallet_string.to_vec(),
instance: instance_string.to_vec(),
benchmarks: benchmarks.to_vec(),
};
$list.push(pallet_benchmarks)
};
}
#[macro_export]
macro_rules! define_benchmarks {
( $([ $names:path, $locations:ty ])* ) => {
#[macro_export]
macro_rules! list_benchmarks {
( $list:ident, $extra:ident ) => {
$( $crate::list_benchmark!( $list, $extra, $names, $locations); )*
}
}
#[macro_export]
macro_rules! add_benchmarks {
( $params:ident, $batches:ident ) => {
$( $crate::add_benchmark!( $params, $batches, $names, $locations ); )*
}
}
}
}
pub use add_benchmark;
pub use benchmark_backend;
pub use benchmarks;
pub use benchmarks_instance;
pub use benchmarks_instance_pallet;
pub use benchmarks_iter;
pub use define_benchmarks;
pub use impl_bench_case_tests;
pub use impl_bench_name_tests;
pub use impl_benchmark;
pub use impl_benchmark_test;
pub use impl_benchmark_test_suite;
pub use impl_test_function;
pub use list_benchmark;
pub use selected_benchmark;
pub use to_origin;
pub use whitelist;