pezframe_benchmarking/
v1.rs

1// This file is part of Bizinikiwi.
2
3// Copyright (C) Parity Technologies (UK) Ltd. and Dijital Kurdistan Tech Institute
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Macros for benchmarking a FRAME runtime.
19
20pub use super::*;
21
22/// Whitelist the given account.
23#[macro_export]
24macro_rules! whitelist {
25	($acc:ident) => {
26		pezframe_benchmarking::benchmarking::add_to_whitelist(
27			pezframe_system::Account::<T>::hashed_key_for(&$acc).into(),
28		);
29	};
30}
31
32/// Construct pezpallet benchmarks for weighing dispatchables.
33///
34/// Works around the idea of complexity parameters, named by a single letter (which is usually
35/// upper cased in complexity notation but is lower-cased for use in this macro).
36///
37/// Complexity parameters ("parameters") have a range which is a `u32` pair. Every time a benchmark
38/// is prepared and run, this parameter takes a concrete value within the range. There is an
39/// associated instancing block, which is a single expression that is evaluated during
40/// preparation. It may use `?` (`i.e. `return Err(...)`) to bail with a string error. Here's a
41/// few examples:
42///
43/// ```ignore
44/// // These two are equivalent:
45/// let x in 0 .. 10;
46/// let x in 0 .. 10 => ();
47/// // This one calls a setup function and might return an error (which would be terminal).
48/// let y in 0 .. 10 => setup(y)?;
49/// // This one uses a code block to do lots of stuff:
50/// let z in 0 .. 10 => {
51///   let a = z * z / 5;
52///   let b = do_something(a)?;
53///   combine_into(z, b);
54/// }
55/// ```
56///
57/// Note that due to parsing restrictions, if the `from` expression is not a single token (i.e. a
58/// literal or constant), then it must be parenthesized.
59///
60/// The macro allows for a number of "arms", each representing an individual benchmark. Using the
61/// simple syntax, the associated dispatchable function maps 1:1 with the benchmark and the name of
62/// the benchmark is the same as that of the associated function. However, extended syntax allows
63/// for arbitrary expressions to be evaluated in a benchmark (including for example,
64/// `on_initialize`).
65///
66/// Note that the ranges are *inclusive* on both sides. This is in contrast to ranges in Rust which
67/// are left-inclusive right-exclusive.
68///
69/// Each arm may also have a block of code which is run prior to any instancing and a block of code
70/// which is run afterwards. All code blocks may draw upon the specific value of each parameter
71/// at any time. Local variables are shared between the two pre- and post- code blocks, but do not
72/// leak from the interior of any instancing expressions.
73///
74/// Example:
75/// ```ignore
76/// benchmarks! {
77///   where_clause {  where T::A: From<u32> } // Optional line to give additional bound on `T`.
78///
79///   // first dispatchable: foo; this is a user dispatchable and operates on a `u8` vector of
80///   // size `l`
81///   foo {
82///     let caller = account::<T>(b"caller", 0, benchmarks_seed);
83///     let l in 1 .. MAX_LENGTH => initialize_l(l);
84///   }: _(RuntimeOrigin::Signed(caller), vec![0u8; l])
85///
86///   // second dispatchable: bar; this is a root dispatchable and accepts a `u8` vector of size
87///   // `l`.
88///   // In this case, we explicitly name the call using `bar` instead of `_`.
89///   bar {
90///     let l in 1 .. MAX_LENGTH => initialize_l(l);
91///   }: bar(RuntimeOrigin::Root, vec![0u8; l])
92///
93///   // third dispatchable: baz; this is a user dispatchable. It isn't dependent on length like the
94///   // other two but has its own complexity `c` that needs setting up. It uses `caller` (in the
95///   // pre-instancing block) within the code block. This is only allowed in the param instancers
96///   // of arms.
97///   baz1 {
98///     let caller = account::<T>(b"caller", 0, benchmarks_seed);
99///     let c = 0 .. 10 => setup_c(&caller, c);
100///   }: baz(RuntimeOrigin::Signed(caller))
101///
102///   // this is a second benchmark of the baz dispatchable with a different setup.
103///   baz2 {
104///     let caller = account::<T>(b"caller", 0, benchmarks_seed);
105///     let c = 0 .. 10 => setup_c_in_some_other_way(&caller, c);
106///   }: baz(RuntimeOrigin::Signed(caller))
107///
108///   // You may optionally specify the origin type if it can't be determined automatically like
109///   // this.
110///   baz3 {
111///     let caller = account::<T>(b"caller", 0, benchmarks_seed);
112///     let l in 1 .. MAX_LENGTH => initialize_l(l);
113///   }: baz<T::RuntimeOrigin>(RuntimeOrigin::Signed(caller), vec![0u8; l])
114///
115///   // this is benchmarking some code that is not a dispatchable.
116///   populate_a_set {
117///     let x in 0 .. 10_000;
118///     let mut m = Vec::<u32>::new();
119///     for i in 0..x {
120///       m.insert(i);
121///     }
122///   }: { m.into_iter().collect::<BTreeSet>() }
123/// }
124/// ```
125///
126/// Test functions are automatically generated for each benchmark and are accessible to you when you
127/// run `cargo test`. All tests are named `test_benchmark_<benchmark_name>`, implemented on the
128/// Pezpallet struct, and run them in a test externalities environment. The test function runs your
129/// benchmark just like a regular benchmark, but only testing at the lowest and highest values for
130/// each component. The function will return `Ok(())` if the benchmarks return no errors.
131///
132/// It is also possible to generate one #[test] function per benchmark by calling the
133/// `impl_benchmark_test_suite` macro inside the `benchmarks` block. The functions will be named
134/// `bench_<benchmark_name>` and can be run via `cargo test`.
135/// You will see one line of output per benchmark. This approach will give you more understandable
136/// error messages and allows for parallel benchmark execution.
137///
138/// You can optionally add a `verify` code block at the end of a benchmark to test any final state
139/// of your benchmark in a unit test. For example:
140///
141/// ```ignore
142/// sort_vector {
143/// 	let x in 1 .. 10000;
144/// 	let mut m = Vec::<u32>::new();
145/// 	for i in (0..x).rev() {
146/// 		m.push(i);
147/// 	}
148/// }: {
149/// 	m.sort();
150/// } verify {
151/// 	ensure!(m[0] == 0, "You forgot to sort!")
152/// }
153/// ```
154///
155/// These `verify` blocks will not affect your benchmark results!
156///
157/// You can construct benchmark by using the `impl_benchmark_test_suite` macro or
158/// by manually implementing them like so:
159///
160/// ```ignore
161/// #[test]
162/// fn test_benchmarks() {
163///   new_test_ext().execute_with(|| {
164///     assert_ok!(Pezpallet::<Test>::test_benchmark_dummy());
165///     assert_err!(Pezpallet::<Test>::test_benchmark_other_name(), "Bad origin");
166///     assert_ok!(Pezpallet::<Test>::test_benchmark_sort_vector());
167///     assert_err!(Pezpallet::<Test>::test_benchmark_broken_benchmark(), "You forgot to sort!");
168///   });
169/// }
170/// ```
171#[macro_export]
172macro_rules! benchmarks {
173	(
174		$( $rest:tt )*
175	) => {
176		$crate::benchmarks_iter!(
177			{ }
178			{ }
179			{ }
180			( )
181			( )
182			( )
183			( )
184			$( $rest )*
185		);
186	}
187}
188
189/// Same as [`benchmarks`] but for instantiable module.
190///
191/// NOTE: For pezpallet declared with [`pezframe_support::pezpallet`], use
192/// [`benchmarks_instance_pallet`].
193#[macro_export]
194macro_rules! benchmarks_instance {
195	(
196		$( $rest:tt )*
197	) => {
198		$crate::benchmarks_iter!(
199			{ }
200			{ I: Instance }
201			{ }
202			( )
203			( )
204			( )
205			( )
206			$( $rest )*
207		);
208	}
209}
210
211/// Same as [`benchmarks`] but for instantiable pezpallet declared [`pezframe_support::pezpallet`].
212///
213/// NOTE: For pezpallet declared with `decl_module!`, use [`benchmarks_instance`].
214#[macro_export]
215macro_rules! benchmarks_instance_pallet {
216	(
217		$( $rest:tt )*
218	) => {
219		$crate::benchmarks_iter!(
220			{ }
221			{ I: 'static }
222			{ }
223			( )
224			( )
225			( )
226			( )
227			$( $rest )*
228		);
229	}
230}
231
232#[macro_export]
233#[doc(hidden)]
234macro_rules! benchmarks_iter {
235	// detect and extract `impl_benchmark_test_suite` call:
236	// - with a semi-colon
237	(
238		{ }
239		{ $( $instance:ident: $instance_bound:tt )? }
240		{ $( $where_clause:tt )* }
241		( $( $names:tt )* )
242		( $( $names_extra:tt )* )
243		( $( $names_skip_meta:tt )* )
244		( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
245		impl_benchmark_test_suite!(
246			$bench_module:ident,
247			$new_test_ext:expr,
248			$test:path
249			$(, $( $args:tt )* )?);
250		$( $rest:tt )*
251	) => {
252		$crate::benchmarks_iter! {
253			{ $bench_module, $new_test_ext, $test $(, $( $args )* )? }
254			{ $( $instance: $instance_bound )? }
255			{ $( $where_clause )* }
256			( $( $names )* )
257			( $( $names_extra )* )
258			( $( $names_skip_meta )* )
259			( $( $pov_name: $( $storage = $pov_mode )*; )* )
260			$( $rest )*
261		}
262	};
263	// - without a semicolon
264	(
265		{ }
266		{ $( $instance:ident: $instance_bound:tt )? }
267		{ $( $where_clause:tt )* }
268		( $( $names:tt )* )
269		( $( $names_extra:tt )* )
270		( $( $names_skip_meta:tt )* )
271		( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
272		impl_benchmark_test_suite!(
273			$bench_module:ident,
274			$new_test_ext:expr,
275			$test:path
276			$(, $( $args:tt )* )?)
277		$( $rest:tt )*
278	) => {
279		$crate::benchmarks_iter! {
280			{ $bench_module, $new_test_ext, $test $(, $( $args )* )? }
281			{ $( $instance: $instance_bound )? }
282			{ $( $where_clause )* }
283			( $( $names )* )
284			( $( $names_extra )* )
285			( $( $names_skip_meta )* )
286			( $( $pov_name: $( $storage = $pov_mode )*; )* )
287			$( $rest )*
288		}
289	};
290	// detect and extract where clause:
291	(
292		{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
293		{ $( $instance:ident: $instance_bound:tt )? }
294		{ $( $where_clause:tt )* }
295		( $( $names:tt )* )
296		( $( $names_extra:tt )* )
297		( $( $names_skip_meta:tt )* )
298		( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
299		where_clause { where $( $where_bound:tt )* }
300		$( $rest:tt )*
301	) => {
302		$crate::benchmarks_iter! {
303			{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
304			{ $( $instance: $instance_bound)? }
305			{ $( $where_bound )* }
306			( $( $names )* )
307			( $( $names_extra )* )
308			( $( $names_skip_meta )* )
309			( $( $pov_name: $( $storage = $pov_mode )*; )* )
310			$( $rest )*
311		}
312	};
313	// detect and extract `#[skip_meta]` tag:
314	(
315		{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
316		{ $( $instance:ident: $instance_bound:tt )? }
317		{ $( $where_clause:tt )* }
318		( $( $names:tt )* )
319		( $( $names_extra:tt )* )
320		( $( $names_skip_meta:tt )* )
321		( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
322		#[skip_meta]
323		$( #[ $($attributes:tt)+ ] )*
324		$name:ident
325		$( $rest:tt )*
326	) => {
327		$crate::benchmarks_iter! {
328			{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
329			{ $( $instance: $instance_bound )? }
330			{ $( $where_clause )* }
331			( $( $names )* )
332			( $( $names_extra )* )
333			( $( $names_skip_meta )* $name )
334			( $( $pov_name: $( $storage = $pov_mode )*; )* )
335			$( #[ $( $attributes )+ ] )*
336			$name
337			$( $rest )*
338		}
339	};
340	// detect and extract `#[extra]` tag:
341	(
342		{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
343		{ $( $instance:ident: $instance_bound:tt )? }
344		{ $( $where_clause:tt )* }
345		( $( $names:tt )* )
346		( $( $names_extra:tt )* )
347		( $( $names_skip_meta:tt )* )
348		( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
349		#[extra]
350		$( #[ $($attributes:tt)+ ] )*
351		$name:ident
352		$( $rest:tt )*
353	) => {
354		$crate::benchmarks_iter! {
355			{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
356			{ $( $instance: $instance_bound )? }
357			{ $( $where_clause )* }
358			( $( $names )* )
359			( $( $names_extra )* $name )
360			( $( $names_skip_meta )* )
361			( $( $pov_name: $( $storage = $pov_mode )*; )* )
362			$( #[ $( $attributes )+ ] )*
363			$name
364			$( $rest )*
365		}
366	};
367	// detect and extract `#[pov_mode = Mode { Pezpallet::Storage: Mode ... }]` tag:
368	(
369		{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
370		{ $( $instance:ident: $instance_bound:tt )? }
371		{ $( $where_clause:tt )* }
372		( $( $names:tt )* )
373		( $( $names_extra:tt )* )
374		( $( $names_skip_meta:tt )* )
375		( $( $old_pov_name:ident: $( $old_storage:path = $old_pov_mode:ident )*; )* )
376		#[pov_mode = $mode:ident $( { $( $storage:path: $pov_mode:ident )* } )?]
377		$( #[ $($attributes:tt)+ ] )*
378		$name:ident
379		$( $rest:tt )*
380	) => {
381		$crate::benchmarks_iter! {
382			{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
383			{ $( $instance: $instance_bound )? }
384			{ $( $where_clause )* }
385			( $( $names )* )
386			( $( $names_extra )* )
387			( $( $names_skip_meta )* )
388			( $name: ALL = $mode $($( $storage = $pov_mode )*)?; $( $old_pov_name: $( $old_storage = $old_pov_mode )*; )* )
389			$( #[ $( $attributes )+ ] )*
390			$name
391			$( $rest )*
392		}
393	};
394	// mutation arm:
395	(
396		{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
397		{ $( $instance:ident: $instance_bound:tt )? }
398		{ $( $where_clause:tt )* }
399		( $( $names:tt )* ) // This contains $( $( { $instance } )? $name:ident )*
400		( $( $names_extra:tt )* )
401		( $( $names_skip_meta:tt )* )
402		( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
403		$name:ident { $( $code:tt )* }: _ $(< $origin_type:ty>)? ( $origin:expr $( , $arg:expr )* )
404		verify $postcode:block
405		$( $rest:tt )*
406	) => {
407		$crate::benchmarks_iter! {
408			{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
409			{ $( $instance: $instance_bound )? }
410			{ $( $where_clause )* }
411			( $( $names )* )
412			( $( $names_extra )* )
413			( $( $names_skip_meta )* )
414			( $( $pov_name: $( $storage = $pov_mode )*; )* )
415			$name { $( $code )* }: $name $(< $origin_type >)? ( $origin $( , $arg )* )
416			verify $postcode
417			$( $rest )*
418		}
419	};
420	// mutation arm:
421	(
422		{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
423		{ $( $instance:ident: $instance_bound:tt )? }
424		{ $( $where_clause:tt )* }
425		( $( $names:tt )* )
426		( $( $names_extra:tt )* )
427		( $( $names_skip_meta:tt )* )
428		( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
429		$name:ident { $( $code:tt )* }: $dispatch:ident $(<$origin_type:ty>)? ( $origin:expr $( , $arg:expr )* )
430		verify $postcode:block
431		$( $rest:tt )*
432	) => {
433		$crate::__private::paste::paste! {
434			$crate::benchmarks_iter! {
435				{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
436				{ $( $instance: $instance_bound )? }
437				{ $( $where_clause )* }
438				( $( $names )* )
439				( $( $names_extra )* )
440				( $( $names_skip_meta )* )
441				( $( $pov_name: $( $storage = $pov_mode )*; )* )
442				$name {
443					$( $code )*
444					let __call = Call::<
445						T
446						$( , $instance )?
447					>:: [< new_call_variant_ $dispatch >] (
448						$($arg),*
449					);
450					let __benchmarked_call_encoded = $crate::__private::codec::Encode::encode(
451						&__call
452					);
453				}: {
454					let __call_decoded = <
455						Call<T $(, $instance )?>
456						as $crate::__private::codec::Decode
457					>::decode(&mut &__benchmarked_call_encoded[..])
458						.expect("call is encoded above, encoding must be correct");
459					let __origin = $crate::to_origin!($origin $(, $origin_type)?);
460					<Call<T $(, $instance)? > as $crate::__private::traits::UnfilteredDispatchable
461						>::dispatch_bypass_filter(__call_decoded, __origin)?;
462				}
463				verify $postcode
464				$( $rest )*
465			}
466		}
467	};
468	// iteration arm:
469	(
470		{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
471		{ $( $instance:ident: $instance_bound:tt )? }
472		{ $( $where_clause:tt )* }
473		( $( $names:tt )* )
474		( $( $names_extra:tt )* )
475		( $( $names_skip_meta:tt )* )
476		( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
477		$name:ident { $( $code:tt )* }: $eval:block
478		verify $postcode:block
479		$( $rest:tt )*
480	) => {
481		$crate::benchmark_backend! {
482			{ $( $instance: $instance_bound )? }
483			$name
484			{ $( $where_clause )* }
485			{ }
486			{ $eval }
487			{ $( $code )* }
488			$postcode
489		}
490
491		#[cfg(test)]
492		$crate::impl_benchmark_test!(
493			{ $( $where_clause )* }
494			{ $( $instance: $instance_bound )? }
495			$name
496		);
497
498		$crate::benchmarks_iter!(
499			{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
500			{ $( $instance: $instance_bound )? }
501			{ $( $where_clause )* }
502			( $( $names )* { $( $instance )? } $name )
503			( $( $names_extra )* )
504			( $( $names_skip_meta )* )
505			( $( $pov_name: $( $storage = $pov_mode )*; )* )
506			$( $rest )*
507		);
508	};
509	// iteration-exit arm which generates a #[test] function for each case.
510	(
511		{ $bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )? }
512		{ $( $instance:ident: $instance_bound:tt )? }
513		{ $( $where_clause:tt )* }
514		( $( $names:tt )* )
515		( $( $names_extra:tt )* )
516		( $( $names_skip_meta:tt )* )
517		( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
518	) => {
519		$crate::selected_benchmark!(
520			{ $( $where_clause)* }
521			{ $( $instance: $instance_bound )? }
522			$( $names )*
523		);
524		$crate::impl_benchmark!(
525			{ $( $where_clause )* }
526			{ $( $instance: $instance_bound )? }
527			( $( $names )* )
528			( $( $names_extra ),* )
529			( $( $names_skip_meta ),* )
530			( $( $pov_name: $( $storage = $pov_mode )*; )* )
531		);
532		$crate::impl_test_function!(
533			( $( $names )* )
534			( $( $names_extra )* )
535			( $( $names_skip_meta )* )
536			$bench_module,
537			$new_test_ext,
538			$test
539			$(, $( $args )* )?
540		);
541	};
542	// iteration-exit arm which doesn't generate a #[test] function for all cases.
543	(
544		{ }
545		{ $( $instance:ident: $instance_bound:tt )? }
546		{ $( $where_clause:tt )* }
547		( $( $names:tt )* )
548		( $( $names_extra:tt )* )
549		( $( $names_skip_meta:tt )* )
550		( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
551	) => {
552		$crate::selected_benchmark!(
553			{ $( $where_clause)* }
554			{ $( $instance: $instance_bound )? }
555			$( $names )*
556		);
557		$crate::impl_benchmark!(
558			{ $( $where_clause )* }
559			{ $( $instance: $instance_bound )? }
560			( $( $names )* )
561			( $( $names_extra ),* )
562			( $( $names_skip_meta ),* )
563			( $( $pov_name: $( $storage = $pov_mode )*; )* )
564		);
565	};
566	// add verify block to _() format
567	(
568		{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
569		{ $( $instance:ident: $instance_bound:tt )? }
570		{ $( $where_clause:tt )* }
571		( $( $names:tt )* )
572		( $( $names_extra:tt )* )
573		( $( $names_skip_meta:tt )* )
574		( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
575		$name:ident { $( $code:tt )* }: _ $(<$origin_type:ty>)? ( $origin:expr $( , $arg:expr )* )
576		$( $rest:tt )*
577	) => {
578		$crate::benchmarks_iter! {
579			{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
580			{ $( $instance: $instance_bound )? }
581			{ $( $where_clause )* }
582			( $( $names )* )
583			( $( $names_extra )* )
584			( $( $names_skip_meta )* )
585			( $( $pov_name: $( $storage = $pov_mode )*; )* )
586			$name { $( $code )* }: _ $(<$origin_type>)? ( $origin $( , $arg )* )
587			verify { }
588			$( $rest )*
589		}
590	};
591	// add verify block to name() format
592	(
593		{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
594		{ $( $instance:ident: $instance_bound:tt )? }
595		{ $( $where_clause:tt )* }
596		( $( $names:tt )* )
597		( $( $names_extra:tt )* )
598		( $( $names_skip_meta:tt )* )
599		( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
600		$name:ident { $( $code:tt )* }: $dispatch:ident $(<$origin_type:ty>)? ( $origin:expr $( , $arg:expr )* )
601		$( $rest:tt )*
602	) => {
603		$crate::benchmarks_iter! {
604			{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
605			{ $( $instance: $instance_bound )? }
606			{ $( $where_clause )* }
607			( $( $names )* )
608			( $( $names_extra )* )
609			( $( $names_skip_meta )* )
610			( $( $pov_name: $( $storage = $pov_mode )*; )* )
611			$name { $( $code )* }: $dispatch $(<$origin_type>)? ( $origin $( , $arg )* )
612			verify { }
613			$( $rest )*
614		}
615	};
616	// add verify block to {} format
617	(
618		{ $($bench_module:ident, $new_test_ext:expr, $test:path $(, $( $args:tt )* )?)? }
619		{ $( $instance:ident: $instance_bound:tt )? }
620		{ $( $where_clause:tt )* }
621		( $( $names:tt )* )
622		( $( $names_extra:tt )* )
623		( $( $names_skip_meta:tt )* )
624		( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
625		$name:ident { $( $code:tt )* }: $(<$origin_type:ty>)? $eval:block
626		$( $rest:tt )*
627	) => {
628		$crate::benchmarks_iter!(
629			{ $($bench_module, $new_test_ext, $test $(, $( $args )* )?)? }
630			{ $( $instance: $instance_bound )? }
631			{ $( $where_clause )* }
632			( $( $names )* )
633			( $( $names_extra )* )
634			( $( $names_skip_meta )* )
635			( $( $pov_name: $( $storage = $pov_mode )*; )* )
636			$name { $( $code )* }: $(<$origin_type>)? $eval
637			verify { }
638			$( $rest )*
639		);
640	};
641}
642
643#[macro_export]
644#[doc(hidden)]
645macro_rules! to_origin {
646	($origin:expr) => {
647		$origin.into()
648	};
649	($origin:expr, $origin_type:ty) => {
650		<<T as pezframe_system::Config>::RuntimeOrigin as From<$origin_type>>::from($origin)
651	};
652}
653
654#[macro_export]
655#[doc(hidden)]
656macro_rules! benchmark_backend {
657	// parsing arms
658	(
659		{ $( $instance:ident: $instance_bound:tt )? }
660		$name:ident
661		{ $( $where_clause:tt )* }
662		{ $( PRE { $( $pre_parsed:tt )* } )* }
663		{ $eval:block }
664		{
665			let $pre_id:tt $( : $pre_ty:ty )? = $pre_ex:expr;
666			$( $rest:tt )*
667		}
668		$postcode:block
669	) => {
670		$crate::benchmark_backend! {
671			{ $( $instance: $instance_bound )? }
672			$name
673			{ $( $where_clause )* }
674			{
675				$( PRE { $( $pre_parsed )* } )*
676				PRE { $pre_id , $( $pre_ty , )? $pre_ex }
677			}
678			{ $eval }
679			{ $( $rest )* }
680			$postcode
681		}
682	};
683	(
684		{ $( $instance:ident: $instance_bound:tt )? }
685		$name:ident
686		{ $( $where_clause:tt )* }
687		{ $( $parsed:tt )* }
688		{ $eval:block }
689		{
690			let $param:ident in ( $param_from:expr ) .. $param_to:expr => $param_instancer:expr;
691			$( $rest:tt )*
692		}
693		$postcode:block
694	) => {
695		$crate::benchmark_backend! {
696			{ $( $instance: $instance_bound )? }
697			$name
698			{ $( $where_clause )* }
699			{
700				$( $parsed )*
701				PARAM { $param , $param_from , $param_to , $param_instancer }
702			}
703			{ $eval }
704			{ $( $rest )* }
705			$postcode
706		}
707	};
708	// mutation arm to look after a single tt for param_from.
709	(
710		{ $( $instance:ident: $instance_bound:tt )? }
711		$name:ident
712		{ $( $where_clause:tt )* }
713		{ $( $parsed:tt )* }
714		{ $eval:block }
715		{
716			let $param:ident in $param_from:tt .. $param_to:expr => $param_instancer:expr ;
717			$( $rest:tt )*
718		}
719		$postcode:block
720	) => {
721		$crate::benchmark_backend! {
722			{ $( $instance: $instance_bound )? }
723			$name
724			{ $( $where_clause )* }
725			{ $( $parsed )* }
726			{ $eval }
727			{
728				let $param in ( $param_from ) .. $param_to => $param_instancer;
729				$( $rest )*
730			}
731			$postcode
732		}
733	};
734	// mutation arm to look after the default tail of `=> ()`
735	(
736		{ $( $instance:ident: $instance_bound:tt )? }
737		$name:ident
738		{ $( $where_clause:tt )* }
739		{ $( $parsed:tt )* }
740		{ $eval:block }
741		{
742			let $param:ident in $param_from:tt .. $param_to:expr;
743			$( $rest:tt )*
744		}
745		$postcode:block
746	) => {
747		$crate::benchmark_backend! {
748			{ $( $instance: $instance_bound )? }
749			$name
750			{ $( $where_clause )* }
751			{ $( $parsed )* }
752			{ $eval }
753			{
754				let $param in $param_from .. $param_to => ();
755				$( $rest )*
756			}
757			$postcode
758		}
759	};
760	// actioning arm
761	(
762		{ $( $instance:ident: $instance_bound:tt )? }
763		$name:ident
764		{ $( $where_clause:tt )* }
765		{
766			$( PRE { $pre_id:tt , $( $pre_ty:ty , )? $pre_ex:expr } )*
767			$( PARAM { $param:ident , $param_from:expr , $param_to:expr , $param_instancer:expr } )*
768		}
769		{ $eval:block }
770		{ $( $post:tt )* }
771		$postcode:block
772	) => {
773		#[allow(non_camel_case_types)]
774		struct $name;
775		#[allow(unused_variables)]
776		impl<T: Config $( <$instance>, $instance: $instance_bound )? >
777			$crate::BenchmarkingSetup<T $(, $instance)? > for $name
778			where $( $where_clause )*
779		{
780			fn components(&self) -> $crate::__private::Vec<($crate::BenchmarkParameter, u32, u32)> {
781				$crate::__private::vec! [
782					$(
783						($crate::BenchmarkParameter::$param, $param_from, $param_to)
784					),*
785				]
786			}
787
788			fn instance(
789				&self,
790				recording: &mut impl $crate::Recording,
791				components: &[($crate::BenchmarkParameter, u32)],
792				verify: bool
793			) -> Result<(), $crate::BenchmarkError> {
794				$(
795					// Prepare instance
796					let $param = components.iter()
797						.find(|&c| c.0 == $crate::BenchmarkParameter::$param)
798						.ok_or("Could not find component in benchmark preparation.")?
799						.1;
800				)*
801				$(
802					let $pre_id $( : $pre_ty )? = $pre_ex;
803				)*
804				$( $param_instancer ; )*
805				$( $post )*
806
807				recording.start();
808				$eval;
809				recording.stop();
810
811				if verify {
812					$postcode;
813				}
814				Ok(())
815			}
816		}
817	};
818}
819
820// Creates #[test] functions for the given bench cases.
821#[macro_export]
822#[doc(hidden)]
823macro_rules! impl_bench_case_tests {
824	(
825		{ $module:ident, $new_test_exec:expr, $exec_name:ident, $test:path, $extra:expr }
826		{ $( $names_extra:tt )* }
827		$( { $( $bench_inst:ident )? } $bench:ident )*
828	)
829	=> {
830		$crate::impl_bench_name_tests!(
831			$module, $new_test_exec, $exec_name, $test, $extra,
832			{ $( $names_extra )* },
833			$( { $bench } )+
834		);
835	}
836}
837
838// Creates a #[test] function for the given bench name.
839#[macro_export]
840#[doc(hidden)]
841macro_rules! impl_bench_name_tests {
842	// recursion anchor
843	(
844		$module:ident, $new_test_exec:expr, $exec_name:ident, $test:path, $extra:expr,
845		{ $( $names_extra:tt )* },
846		{ $name:ident }
847	) => {
848		$crate::__private::paste::paste! {
849			#[test]
850			fn [<bench_ $name>] () {
851				$new_test_exec.$exec_name(|| {
852					// Skip all #[extra] benchmarks if $extra is false.
853					if !($extra) {
854						let disabled = $crate::__private::vec![ $( stringify!($names_extra).as_ref() ),* ];
855						if disabled.contains(&stringify!($name)) {
856							$crate::__private::log::debug!(
857								"extra benchmark skipped - {}",
858								stringify!($name),
859							);
860							return ();
861						}
862					}
863
864					// Same per-case logic as when all cases are run in the
865					// same function.
866					match std::panic::catch_unwind(|| {
867						$module::<$test>::[< test_benchmark_ $name >] ()
868					}) {
869						Err(err) => {
870							panic!("{}: {:?}", stringify!($name), err);
871						},
872						Ok(Err(err)) => {
873							match err {
874								$crate::BenchmarkError::Stop(err) => {
875									panic!("{}: {:?}", stringify!($name), err);
876								},
877								$crate::BenchmarkError::Override(_) => {
878									// This is still considered a success condition.
879									$crate::__private::log::error!(
880										"benchmark error overridden - {}",
881										stringify!($name),
882									);
883								},
884								$crate::BenchmarkError::Skip => {
885									// This is considered a success condition.
886									$crate::__private::log::debug!(
887										"benchmark skipped - {}",
888										stringify!($name),
889									);
890								},
891								$crate::BenchmarkError::Weightless => {
892									// This is considered a success condition.
893									$crate::__private::log::debug!(
894										"benchmark weightless skipped - {}",
895										stringify!($name),
896									);
897								}
898							}
899						},
900						Ok(Ok(())) => (),
901					}
902				});
903			}
904		}
905	};
906	// recursion tail
907    (
908		$module:ident, $new_test_exec:expr, $exec_name:ident, $test:path, $extra:expr,
909		{ $( $names_extra:tt )* },
910		{ $name:ident } $( { $rest:ident } )+
911	) => {
912		// car
913		$crate::impl_bench_name_tests!($module, $new_test_exec, $exec_name, $test, $extra,
914			{ $( $names_extra )* }, { $name });
915		// cdr
916		$crate::impl_bench_name_tests!($module, $new_test_exec, $exec_name, $test, $extra,
917			{ $( $names_extra )* }, $( { $rest } )+);
918	};
919}
920
921// Creates a `SelectedBenchmark` enum implementing `BenchmarkingSetup`.
922//
923// Every variant must implement [`BenchmarkingSetup`].
924//
925// ```nocompile
926//
927// struct Transfer;
928// impl BenchmarkingSetup for Transfer { ... }
929//
930// struct SetBalance;
931// impl BenchmarkingSetup for SetBalance { ... }
932//
933// selected_benchmark!({} Transfer {} SetBalance);
934// ```
935#[macro_export]
936#[doc(hidden)]
937macro_rules! selected_benchmark {
938	(
939		{ $( $where_clause:tt )* }
940		{ $( $instance:ident: $instance_bound:tt )? }
941		$( { $( $bench_inst:ident )? } $bench:ident )*
942	) => {
943		// The list of available benchmarks for this pezpallet.
944		#[allow(non_camel_case_types)]
945		enum SelectedBenchmark {
946			$( $bench, )*
947		}
948
949		// Allow us to select a benchmark from the list of available benchmarks.
950		impl<T: Config $( <$instance>, $instance: $instance_bound )? >
951			$crate::BenchmarkingSetup<T $(, $instance )? > for SelectedBenchmark
952			where $( $where_clause )*
953		{
954			fn components(&self) -> $crate::__private::Vec<($crate::BenchmarkParameter, u32, u32)> {
955				match self {
956					$(
957						Self::$bench => <
958							$bench as $crate::BenchmarkingSetup<T $(, $bench_inst)? >
959						>::components(&$bench),
960					)*
961				}
962			}
963
964			fn instance(
965				&self,
966				recording: &mut impl $crate::Recording,
967				components: &[($crate::BenchmarkParameter, u32)],
968				verify: bool
969			) -> Result<(), $crate::BenchmarkError> {
970				match self {
971					$(
972						Self::$bench => <
973							$bench as $crate::BenchmarkingSetup<T $(, $bench_inst)? >
974						>::instance(&$bench, recording, components, verify),
975					)*
976				}
977			}
978		}
979	};
980}
981
982#[macro_export]
983#[doc(hidden)]
984macro_rules! impl_benchmark {
985	(
986		{ $( $where_clause:tt )* }
987		{ $( $instance:ident: $instance_bound:tt )? }
988		( $( { $( $name_inst:ident )? } $name:ident )* )
989		( $( $name_extra:ident ),* )
990		( $( $name_skip_meta:ident ),* )
991		( $( $pov_name:ident: $( $storage:path = $pov_mode:ident )*; )* )
992	) => {
993		// We only need to implement benchmarks for the runtime-benchmarks feature or testing.
994		#[cfg(any(feature = "runtime-benchmarks", test))]
995		impl<T: Config $(<$instance>, $instance: $instance_bound )? >
996			$crate::Benchmarking for Pezpallet<T $(, $instance)? >
997			where T: pezframe_system::Config, $( $where_clause )*
998		{
999			fn benchmarks(extra: bool) -> $crate::__private::Vec<$crate::BenchmarkMetadata> {
1000				$($crate::validate_pov_mode!(
1001					$pov_name: $( $storage = $pov_mode )*;
1002				);)*
1003				let mut all_names = $crate::__private::vec![ $( stringify!($name).as_ref() ),* ];
1004				if !extra {
1005					let extra = [ $( stringify!($name_extra).as_ref() ),* ];
1006					all_names.retain(|x| !extra.contains(x));
1007				}
1008				let pov_modes: $crate::__private::Vec<($crate::__private::Vec<u8>, $crate::__private::Vec<($crate::__private::Vec<u8>, $crate::__private::Vec<u8>)>)> = $crate::__private::vec![
1009					$(
1010						(stringify!($pov_name).as_bytes().to_vec(),
1011						$crate::__private::vec![
1012							// Stringify sometimes includes spaces, depending on the Rust version.
1013							$( ( stringify!($storage).replace(" ", "").as_bytes().to_vec(),
1014								 stringify!($pov_mode).as_bytes().to_vec() ), )*
1015						]),
1016					)*
1017				];
1018				all_names.into_iter().map(|benchmark| {
1019					let selected_benchmark = match benchmark {
1020						$( stringify!($name) => SelectedBenchmark::$name, )*
1021						_ => panic!("all benchmarks should be selectable"),
1022					};
1023					let name = benchmark.as_bytes().to_vec();
1024					let components = <
1025						SelectedBenchmark as $crate::BenchmarkingSetup<T $(, $instance)?>
1026					>::components(&selected_benchmark);
1027
1028					$crate::BenchmarkMetadata {
1029						name: name.clone(),
1030						components,
1031						pov_modes: pov_modes.iter().find(|p| p.0 == name).map(|p| p.1.clone()).unwrap_or_default(),
1032					}
1033				}).collect::<$crate::__private::Vec<_>>()
1034			}
1035
1036			fn run_benchmark(
1037				extrinsic: &[u8],
1038				c: &[($crate::BenchmarkParameter, u32)],
1039				whitelist: &[$crate::__private::TrackedStorageKey],
1040				verify: bool,
1041				internal_repeats: u32,
1042			) -> Result<$crate::__private::Vec<$crate::BenchmarkResult>, $crate::BenchmarkError> {
1043				// Map the input to the selected benchmark.
1044				$crate::benchmarking::wipe_db();
1045				let extrinsic = $crate::__private::str::from_utf8(extrinsic)
1046					.map_err(|_| "`extrinsic` is not a valid utf8 string!")?;
1047				let selected_benchmark = match extrinsic {
1048					$( stringify!($name) => SelectedBenchmark::$name, )*
1049					_ => return Err("Could not find extrinsic.".into()),
1050				};
1051
1052				// Add whitelist to DB including whitelisted caller
1053				let mut whitelist = whitelist.to_vec();
1054				let whitelisted_caller_key =
1055					<pezframe_system::Account::<T> as $crate::__private::storage::StorageMap<_,_>>::hashed_key_for(
1056						$crate::whitelisted_caller::<T::AccountId>()
1057					);
1058				whitelist.push(whitelisted_caller_key.into());
1059				// Whitelist the transactional layer.
1060				let transactional_layer_key = $crate::__private::TrackedStorageKey::new(
1061					$crate::__private::storage::transactional::TRANSACTION_LEVEL_KEY.into()
1062				);
1063				whitelist.push(transactional_layer_key);
1064				// Whitelist the `:extrinsic_index`.
1065				let extrinsic_index = $crate::__private::TrackedStorageKey::new(
1066					$crate::__private::well_known_keys::EXTRINSIC_INDEX.into()
1067				);
1068				whitelist.push(extrinsic_index);
1069				// Whitelist the `:intrablock_entropy`.
1070				let intrablock_entropy = $crate::__private::TrackedStorageKey::new(
1071					$crate::__private::well_known_keys::INTRABLOCK_ENTROPY.into()
1072				);
1073				whitelist.push(intrablock_entropy);
1074
1075				$crate::benchmarking::set_whitelist(whitelist.clone());
1076
1077				let mut results: $crate::__private::Vec<$crate::BenchmarkResult> = $crate::__private::Vec::new();
1078				let on_before_start = || {
1079					// Set the block number to at least 1 so events are deposited.
1080					if $crate::__private::Zero::is_zero(&pezframe_system::Pezpallet::<T>::block_number()) {
1081						pezframe_system::Pezpallet::<T>::set_block_number(1u32.into());
1082					}
1083
1084					// Commit the externalities to the database, flushing the DB cache.
1085					// This will enable worst case scenario for reading from the database.
1086					$crate::benchmarking::commit_db();
1087
1088					// Access all whitelisted keys to get them into the proof recorder since the
1089					// recorder does now have a whitelist.
1090					for key in &whitelist {
1091						$crate::__private::storage::unhashed::get_raw(&key.key);
1092					}
1093
1094					// Reset the read/write counter so we don't count operations in the setup process.
1095					$crate::benchmarking::reset_read_write_count();
1096				};
1097
1098				// Always do at least one internal repeat...
1099				for _ in 0 .. internal_repeats.max(1) {
1100					// Always reset the state after the benchmark.
1101					$crate::__private::defer!($crate::benchmarking::wipe_db());
1102
1103					// Time the extrinsic logic.
1104					$crate::__private::log::trace!(
1105						target: "benchmark",
1106						"Start Benchmark: {} ({:?}) verify {}",
1107						extrinsic,
1108						c,
1109						verify
1110					);
1111
1112					// Set up the externalities environment for the setup we want to
1113					// benchmark.
1114					let mut recording = $crate::BenchmarkRecording::new(&on_before_start);
1115					<SelectedBenchmark as $crate::BenchmarkingSetup<T $(, $instance)?>>::instance(&selected_benchmark, &mut recording, c, verify)?;
1116
1117					// Calculate the diff caused by the benchmark.
1118					let elapsed_extrinsic = recording.elapsed_extrinsic().expect("elapsed time should be recorded");
1119					let diff_pov = recording.diff_pov().unwrap_or_default();
1120
1121					// Commit the changes to get proper write count
1122					$crate::benchmarking::commit_db();
1123					$crate::__private::log::trace!(
1124						target: "benchmark",
1125						"End Benchmark: {} ns", elapsed_extrinsic
1126					);
1127					let read_write_count = $crate::benchmarking::read_write_count();
1128					$crate::__private::log::trace!(
1129						target: "benchmark",
1130						"Read/Write Count {:?}", read_write_count
1131					);
1132					$crate::__private::log::trace!(
1133						target: "benchmark",
1134						"Proof sizes: before {:?} after {:?} diff {}", recording.start_pov(), recording.end_pov(), &diff_pov
1135					);
1136
1137					// Time the storage root recalculation.
1138					let start_storage_root = $crate::current_time();
1139					$crate::__private::storage_root($crate::__private::StateVersion::V1);
1140					let finish_storage_root = $crate::current_time();
1141					let elapsed_storage_root = finish_storage_root - start_storage_root;
1142
1143					let skip_meta = [ $( stringify!($name_skip_meta).as_ref() ),* ];
1144					let read_and_written_keys = if skip_meta.contains(&extrinsic) {
1145						$crate::__private::vec![(b"Skipped Metadata".to_vec(), 0, 0, false)]
1146					} else {
1147						$crate::benchmarking::get_read_and_written_keys()
1148					};
1149
1150					results.push($crate::BenchmarkResult {
1151						components: c.to_vec(),
1152						extrinsic_time: elapsed_extrinsic,
1153						storage_root_time: elapsed_storage_root,
1154						reads: read_write_count.0,
1155						repeat_reads: read_write_count.1,
1156						writes: read_write_count.2,
1157						repeat_writes: read_write_count.3,
1158						proof_size: diff_pov,
1159						keys: read_and_written_keys,
1160					});
1161				}
1162
1163				return Ok(results);
1164			}
1165		}
1166
1167		#[cfg(test)]
1168		impl<T: Config $(<$instance>, $instance: $instance_bound )? >
1169			Pezpallet<T $(, $instance)? >
1170		where T: pezframe_system::Config, $( $where_clause )*
1171		{
1172			/// Test a particular benchmark by name.
1173			///
1174			/// This isn't called `test_benchmark_by_name` just in case some end-user eventually
1175			/// writes a benchmark, itself called `by_name`; the function would be shadowed in
1176			/// that case.
1177			///
1178			/// This is generally intended to be used by child test modules such as those created
1179			/// by the `impl_benchmark_test_suite` macro. However, it is not an error if a pezpallet
1180			/// author chooses not to implement benchmarks.
1181			#[allow(unused)]
1182			fn test_bench_by_name(name: &[u8]) -> Result<(), $crate::BenchmarkError> {
1183				let name = $crate::__private::str::from_utf8(name)
1184					.map_err(|_| -> $crate::BenchmarkError { "`name` is not a valid utf8 string!".into() })?;
1185				match name {
1186					$( stringify!($name) => {
1187						$crate::__private::paste::paste! { Self::[< test_benchmark_ $name >]() }
1188					} )*
1189					_ => Err("Could not find test for requested benchmark.".into()),
1190				}
1191			}
1192		}
1193	};
1194}
1195
1196// This creates a unit test for one benchmark of the main benchmark macro.
1197// It runs the benchmark using the `high` and `low` value for each component
1198// and ensure that everything completes successfully.
1199// Instances each component with six values which can be controlled with the
1200// env variable `VALUES_PER_COMPONENT`.
1201#[macro_export]
1202#[doc(hidden)]
1203macro_rules! impl_benchmark_test {
1204	(
1205		{ $( $where_clause:tt )* }
1206		{ $( $instance:ident: $instance_bound:tt )? }
1207		$name:ident
1208	) => {
1209		$crate::__private::paste::item! {
1210			#[cfg(test)]
1211			impl<T: Config $(<$instance>, $instance: $instance_bound )? >
1212				Pezpallet<T $(, $instance)? >
1213			where T: pezframe_system::Config, $( $where_clause )*
1214			{
1215				#[allow(unused)]
1216				fn [<test_benchmark_ $name>] () -> Result<(), $crate::BenchmarkError> {
1217					let selected_benchmark = SelectedBenchmark::$name;
1218					let components = <
1219						SelectedBenchmark as $crate::BenchmarkingSetup<T, _>
1220					>::components(&selected_benchmark);
1221
1222					let execute_benchmark = |
1223						c: $crate::__private::Vec<($crate::BenchmarkParameter, u32)>
1224					| -> Result<(), $crate::BenchmarkError> {
1225						// Always reset the state after the benchmark.
1226						$crate::__private::defer!($crate::benchmarking::wipe_db());
1227
1228						let on_before_start = || {
1229							// Set the block number to at least 1 so events are deposited.
1230							if $crate::__private::Zero::is_zero(&pezframe_system::Pezpallet::<T>::block_number()) {
1231								pezframe_system::Pezpallet::<T>::set_block_number(1u32.into());
1232							}
1233						};
1234
1235						// Run execution + verification
1236						<SelectedBenchmark as $crate::BenchmarkingSetup<T, _>>::test_instance(&selected_benchmark, &c, &on_before_start)
1237					};
1238
1239					if components.is_empty() {
1240						execute_benchmark(Default::default())?;
1241					} else {
1242						let num_values: u32 = if let Ok(ev) = std::env::var("VALUES_PER_COMPONENT") {
1243							ev.parse().map_err(|_| {
1244								$crate::BenchmarkError::Stop(
1245									"Could not parse env var `VALUES_PER_COMPONENT` as u32."
1246								)
1247							})?
1248						} else {
1249							6
1250						};
1251
1252						if num_values < 2 {
1253							return Err("`VALUES_PER_COMPONENT` must be at least 2".into());
1254						}
1255
1256						for (name, low, high) in components.clone().into_iter() {
1257							// Test the lowest, highest (if its different from the lowest)
1258							// and up to num_values-2 more equidistant values in between.
1259							// For 0..10 and num_values=6 this would mean: [0, 2, 4, 6, 8, 10]
1260
1261							let mut values = $crate::__private::vec![low];
1262							let diff = (high - low).min(num_values - 1);
1263							let slope = (high - low) as f32 / diff as f32;
1264
1265							for i in 1..=diff {
1266								let value = ((low as f32 + slope * i as f32) as u32)
1267												.clamp(low, high);
1268								values.push(value);
1269							}
1270
1271							for component_value in values {
1272								// Select the max value for all the other components.
1273								let c: $crate::__private::Vec<($crate::BenchmarkParameter, u32)> = components
1274									.iter()
1275									.map(|(n, _, h)|
1276										if *n == name {
1277											(*n, component_value)
1278										} else {
1279											(*n, *h)
1280										}
1281									)
1282									.collect();
1283
1284								execute_benchmark(c)?;
1285							}
1286						}
1287					}
1288					Ok(())
1289				}
1290			}
1291		}
1292	};
1293}
1294
1295/// This creates a test suite which runs the module's benchmarks.
1296///
1297/// When called in `pezpallet_example_basic` as
1298///
1299/// ```rust,ignore
1300/// impl_benchmark_test_suite!(Pezpallet, crate::tests::new_test_ext(), crate::tests::Test);
1301/// ```
1302///
1303/// It expands to the equivalent of:
1304///
1305/// ```rust,ignore
1306/// #[cfg(test)]
1307/// mod tests {
1308/// 	use super::*;
1309/// 	use crate::tests::{new_test_ext, Test};
1310/// 	use pezframe_support::assert_ok;
1311///
1312/// 	#[test]
1313/// 	fn test_benchmarks() {
1314/// 		new_test_ext().execute_with(|| {
1315/// 			assert_ok!(test_benchmark_accumulate_dummy::<Test>());
1316/// 			assert_ok!(test_benchmark_set_dummy::<Test>());
1317/// 			assert_ok!(test_benchmark_sort_vector::<Test>());
1318/// 		});
1319/// 	}
1320/// }
1321/// ```
1322///
1323/// When called inside the `benchmarks` macro of the `pezpallet_example_basic` as
1324///
1325/// ```rust,ignore
1326/// benchmarks! {
1327/// 	// Benchmarks omitted for brevity
1328///
1329/// 	impl_benchmark_test_suite!(Pezpallet, crate::tests::new_test_ext(), crate::tests::Test);
1330/// }
1331/// ```
1332///
1333/// It expands to the equivalent of:
1334///
1335/// ```rust,ignore
1336/// #[cfg(test)]
1337/// mod benchmarking {
1338/// 	use super::*;
1339/// 	use crate::tests::{new_test_ext, Test};
1340/// 	use pezframe_support::assert_ok;
1341///
1342/// 	#[test]
1343/// 	fn bench_accumulate_dummy() {
1344/// 		new_test_ext().execute_with(|| {
1345/// 			assert_ok!(test_benchmark_accumulate_dummy::<Test>());
1346/// 		})
1347/// 	}
1348///
1349/// 	#[test]
1350/// 	fn bench_set_dummy() {
1351/// 		new_test_ext().execute_with(|| {
1352/// 			assert_ok!(test_benchmark_set_dummy::<Test>());
1353/// 		})
1354/// 	}
1355///
1356/// 	#[test]
1357/// 	fn bench_sort_vector() {
1358/// 		new_test_ext().execute_with(|| {
1359/// 			assert_ok!(test_benchmark_sort_vector::<Test>());
1360/// 		})
1361/// 	}
1362/// }
1363/// ```
1364///
1365/// ## Arguments
1366///
1367/// The first argument, `module`, must be the path to this crate's module.
1368///
1369/// The second argument, `new_test_ext`, must be a function call which returns either a
1370/// `pezsp_io::TestExternalities`, or some other type with a similar interface.
1371///
1372/// Note that this function call is _not_ evaluated at compile time, but is instead copied textually
1373/// into each appropriate invocation site.
1374///
1375/// The third argument, `test`, must be the path to the runtime. The item to which this must refer
1376/// will generally take the form:
1377///
1378/// ```rust,ignore
1379/// pezframe_support::construct_runtime!(
1380/// 	pub enum Test where ...
1381/// 	{ ... }
1382/// );
1383/// ```
1384///
1385/// There is an optional fourth argument, with keyword syntax: `benchmarks_path =
1386/// path_to_benchmarks_invocation`. In the typical case in which this macro is in the same module as
1387/// the `benchmarks!` invocation, you don't need to supply this. However, if the
1388/// `impl_benchmark_test_suite!` invocation is in a different module than the `benchmarks!`
1389/// invocation, then you should provide the path to the module containing the `benchmarks!`
1390/// invocation:
1391///
1392/// ```rust,ignore
1393/// mod benches {
1394/// 	benchmarks!{
1395/// 		...
1396/// 	}
1397/// }
1398///
1399/// mod tests {
1400/// 	// because of macro syntax limitations, neither Pezpallet nor benches can be paths, but both have
1401/// 	// to be idents in the scope of `impl_benchmark_test_suite`.
1402/// 	use crate::{benches, Pezpallet};
1403///
1404/// 	impl_benchmark_test_suite!(Pezpallet, new_test_ext(), Test, benchmarks_path = benches);
1405///
1406/// 	// new_test_ext and the Test item are defined later in this module
1407/// }
1408/// ```
1409///
1410/// There is an optional fifth argument, with keyword syntax: `extra = true` or `extra = false`.
1411/// By default, this generates a test suite which iterates over all benchmarks, including those
1412/// marked with the `#[extra]` annotation. Setting `extra = false` excludes those.
1413///
1414/// There is an optional sixth argument, with keyword syntax: `exec_name = custom_exec_name`.
1415/// By default, this macro uses `execute_with` for this parameter. This argument, if set, is subject
1416/// to these restrictions:
1417///
1418/// - It must be the name of a method applied to the output of the `new_test_ext` argument.
1419/// - That method must have a signature capable of receiving a single argument of the form `impl
1420///   FnOnce()`.
1421// ## Notes (not for rustdoc)
1422//
1423// The biggest challenge for this macro is communicating the actual test functions to be run. We
1424// can't just build an array of function pointers to each test function and iterate over it, because
1425// the test functions are parameterized by the `Test` type. That's incompatible with
1426// monomorphization: if it were legal, then even if the compiler detected and monomorphized the
1427// functions into only the types of the callers, which implementation would the function pointer
1428// point to? There would need to be some kind of syntax for selecting the destination of the pointer
1429// according to a generic argument, and in general it would be a huge mess and not worth it.
1430//
1431// Instead, we're going to steal a trick from `fn run_benchmark`: generate a function which is
1432// itself parametrized by `Test`, which accepts a `&[u8]` parameter containing the name of the
1433// benchmark, and dispatches based on that to the appropriate real test implementation. Then, we can
1434// just iterate over the `Benchmarking::benchmarks` list to run the actual implementations.
1435#[macro_export]
1436macro_rules! impl_benchmark_test_suite {
1437	(
1438		$bench_module:ident,
1439		$new_test_ext:expr,
1440		$test:path
1441		$(, $( $rest:tt )* )?
1442	) => {
1443		$crate::impl_test_function!(
1444			()
1445			()
1446			()
1447			$bench_module,
1448			$new_test_ext,
1449			$test
1450			$(, $( $rest )* )?
1451		);
1452	}
1453}
1454
1455/// Validates the passed `pov_mode`s.
1456///
1457/// Checks that:
1458/// - a top-level `ignored` is exclusive
1459/// - all modes are valid
1460#[macro_export]
1461macro_rules! validate_pov_mode {
1462	() => {};
1463	( $_bench:ident: ; ) => { };
1464	( $_bench:ident: $_car:path = Ignored ; ) => { };
1465	( $bench:ident: $_car:path = Ignored $( $storage:path = $_pov_mode:ident )+; ) => {
1466		compile_error!(
1467			concat!(concat!("`pov_mode = Ignored` is exclusive. Please remove the attribute from keys: ", $( stringify!($storage) )+), " on benchmark '", stringify!($bench), "'"));
1468	};
1469	( $bench:ident: $car:path = Measured $( $storage:path = $pov_mode:ident )*; ) => {
1470		$crate::validate_pov_mode!(
1471			$bench: $( $storage = $pov_mode )*;
1472		);
1473	};
1474	( $bench:ident: $car:path = MaxEncodedLen $( $storage:path = $pov_mode:ident )*; ) => {
1475		$crate::validate_pov_mode!(
1476			$bench: $( $storage = $pov_mode )*;
1477		);
1478	};
1479	( $bench:ident: $key:path = $unknown:ident $( $_storage:path = $_pov_mode:ident )*; ) => {
1480		compile_error!(
1481			concat!("Unknown pov_mode '", stringify!($unknown) ,"' for benchmark '", stringify!($bench), "' on key '", stringify!($key), "'. Must be one of: Ignored, Measured, MaxEncodedLen")
1482		);
1483	};
1484}
1485
1486// Takes all arguments from `impl_benchmark_test_suite` and three additional arguments.
1487//
1488// Can be configured to generate one #[test] fn per bench case or
1489// one #[test] fn for all bench cases.
1490// This depends on whether or not the first argument contains a non-empty list of bench names.
1491#[macro_export]
1492#[doc(hidden)]
1493macro_rules! impl_test_function {
1494	// user might or might not have set some keyword arguments; set the defaults
1495	//
1496	// The weird syntax indicates that `rest` comes only after a comma, which is otherwise optional
1497	(
1498		( $( $names:tt )* )
1499		( $( $names_extra:tt )* )
1500		( $( $names_skip_meta:tt )* )
1501
1502		$bench_module:ident,
1503		$new_test_ext:expr,
1504		$test:path
1505		$(, $( $rest:tt )* )?
1506	) => {
1507		$crate::impl_test_function!(
1508			@cases:
1509				( $( $names )* )
1510				( $( $names_extra )* )
1511				( $( $names_skip_meta )* )
1512			@selected:
1513				$bench_module,
1514				$new_test_ext,
1515				$test,
1516				benchmarks_path = super,
1517				extra = true,
1518				exec_name = execute_with,
1519			@user:
1520				$( $( $rest )* )?
1521		);
1522	};
1523	// pick off the benchmarks_path keyword argument
1524	(
1525		@cases:
1526			( $( $names:tt )* )
1527			( $( $names_extra:tt )* )
1528			( $( $names_skip_meta:tt )* )
1529		@selected:
1530			$bench_module:ident,
1531			$new_test_ext:expr,
1532			$test:path,
1533			benchmarks_path = $old:ident,
1534			extra = $extra:expr,
1535			exec_name = $exec_name:ident,
1536		@user:
1537			benchmarks_path = $benchmarks_path:ident
1538			$(, $( $rest:tt )* )?
1539	) => {
1540		$crate::impl_test_function!(
1541			@cases:
1542				( $( $names )* )
1543				( $( $names_extra )* )
1544				( $( $names_skip_meta )* )
1545			@selected:
1546				$bench_module,
1547				$new_test_ext,
1548				$test,
1549				benchmarks_path = $benchmarks_path,
1550				extra = $extra,
1551				exec_name = $exec_name,
1552			@user:
1553				$( $( $rest )* )?
1554		);
1555	};
1556	// pick off the extra keyword argument
1557	(
1558		@cases:
1559			( $( $names:tt )* )
1560			( $( $names_extra:tt )* )
1561			( $( $names_skip_meta:tt )* )
1562		@selected:
1563			$bench_module:ident,
1564			$new_test_ext:expr,
1565			$test:path,
1566			benchmarks_path = $benchmarks_path:ident,
1567			extra = $old:expr,
1568			exec_name = $exec_name:ident,
1569		@user:
1570			extra = $extra:expr
1571			$(, $( $rest:tt )* )?
1572	) => {
1573		$crate::impl_test_function!(
1574			@cases:
1575				( $( $names )* )
1576				( $( $names_extra )* )
1577				( $( $names_skip_meta )* )
1578			@selected:
1579				$bench_module,
1580				$new_test_ext,
1581				$test,
1582				benchmarks_path = $benchmarks_path,
1583				extra = $extra,
1584				exec_name = $exec_name,
1585			@user:
1586				$( $( $rest )* )?
1587		);
1588	};
1589	// pick off the exec_name keyword argument
1590	(
1591		@cases:
1592			( $( $names:tt )* )
1593			( $( $names_extra:tt )* )
1594			( $( $names_skip_meta:tt )* )
1595		@selected:
1596			$bench_module:ident,
1597			$new_test_ext:expr,
1598			$test:path,
1599			benchmarks_path = $benchmarks_path:ident,
1600			extra = $extra:expr,
1601			exec_name = $old:ident,
1602		@user:
1603			exec_name = $exec_name:ident
1604			$(, $( $rest:tt )* )?
1605	) => {
1606		$crate::impl_test_function!(
1607			@cases:
1608				( $( $names )* )
1609				( $( $names_extra )* )
1610				( $( $names_skip_meta )* )
1611			@selected:
1612				$bench_module,
1613				$new_test_ext,
1614				$test,
1615				benchmarks_path = $benchmarks_path,
1616				extra = $extra,
1617				exec_name = $exec_name,
1618			@user:
1619				$( $( $rest )* )?
1620		);
1621	};
1622	// iteration-exit arm which generates a #[test] function for each case.
1623	(
1624		@cases:
1625			( $( $names:tt )+ )
1626			( $( $names_extra:tt )* )
1627			( $( $names_skip_meta:tt )* )
1628		@selected:
1629			$bench_module:ident,
1630			$new_test_ext:expr,
1631			$test:path,
1632			benchmarks_path = $path_to_benchmarks_invocation:ident,
1633			extra = $extra:expr,
1634			exec_name = $exec_name:ident,
1635		@user:
1636			$(,)?
1637	) => {
1638		$crate::impl_bench_case_tests!(
1639			{ $bench_module, $new_test_ext, $exec_name, $test, $extra }
1640			{ $( $names_extra:tt )* }
1641			$($names)+
1642		);
1643	};
1644	// iteration-exit arm which generates one #[test] function for all cases.
1645	(
1646		@cases:
1647			()
1648			()
1649			()
1650		@selected:
1651			$bench_module:ident,
1652			$new_test_ext:expr,
1653			$test:path,
1654			benchmarks_path = $path_to_benchmarks_invocation:ident,
1655			extra = $extra:expr,
1656			exec_name = $exec_name:ident,
1657		@user:
1658			$(,)?
1659	) => {
1660		#[cfg(test)]
1661		mod benchmark_tests {
1662			use super::$bench_module;
1663
1664			#[test]
1665			fn test_benchmarks() {
1666				$new_test_ext.$exec_name(|| {
1667					use $crate::Benchmarking;
1668
1669					let mut anything_failed = false;
1670					println!("failing benchmark tests:");
1671					for benchmark_metadata in $bench_module::<$test>::benchmarks($extra) {
1672						let benchmark_name = &benchmark_metadata.name;
1673						match std::panic::catch_unwind(|| {
1674							$bench_module::<$test>::test_bench_by_name(benchmark_name)
1675						}) {
1676							Err(err) => {
1677								println!(
1678									"{}: {:?}",
1679									$crate::__private::str::from_utf8(benchmark_name)
1680										.expect("benchmark name is always a valid string!"),
1681									err,
1682								);
1683								anything_failed = true;
1684							},
1685							Ok(Err(err)) => {
1686								match err {
1687									$crate::BenchmarkError::Stop(err) => {
1688										println!(
1689											"{}: {:?}",
1690											$crate::__private::str::from_utf8(benchmark_name)
1691												.expect("benchmark name is always a valid string!"),
1692											err,
1693										);
1694										anything_failed = true;
1695									},
1696									$crate::BenchmarkError::Override(_) => {
1697										// This is still considered a success condition.
1698										$crate::__private::log::error!(
1699											"WARNING: benchmark error overridden - {}",
1700												$crate::__private::str::from_utf8(benchmark_name)
1701													.expect("benchmark name is always a valid string!"),
1702											);
1703									},
1704									$crate::BenchmarkError::Skip => {
1705										// This is considered a success condition.
1706										$crate::__private::log::error!(
1707											"WARNING: benchmark error skipped - {}",
1708											$crate::__private::str::from_utf8(benchmark_name)
1709												.expect("benchmark name is always a valid string!"),
1710										);
1711									}
1712									$crate::BenchmarkError::Weightless => {
1713										// This is considered a success condition.
1714										$crate::__private::log::error!(
1715											"WARNING: benchmark weightless skipped - {}",
1716											$crate::__private::str::from_utf8(benchmark_name)
1717												.expect("benchmark name is always a valid string!"),
1718										);
1719									}
1720								}
1721							},
1722							Ok(Ok(())) => (),
1723						}
1724					}
1725					assert!(!anything_failed);
1726				});
1727			}
1728		}
1729	};
1730}
1731
1732/// show error message and debugging info for the case of an error happening
1733/// during a benchmark
1734pub fn show_benchmark_debug_info(
1735	instance_string: &[u8],
1736	benchmark: &[u8],
1737	components: &[(BenchmarkParameter, u32)],
1738	verify: &bool,
1739	error_message: &str,
1740) -> alloc::string::String {
1741	alloc::format!(
1742		"\n* Pezpallet: {}\n\
1743		* Benchmark: {}\n\
1744		* Components: {:?}\n\
1745		* Verify: {:?}\n\
1746		* Error message: {}",
1747		alloc::str::from_utf8(instance_string)
1748			.expect("it's all just strings ran through the wasm interface. qed"),
1749		alloc::str::from_utf8(benchmark)
1750			.expect("it's all just strings ran through the wasm interface. qed"),
1751		components,
1752		verify,
1753		error_message,
1754	)
1755}
1756
1757/// This macro adds pezpallet benchmarks to a `Vec<BenchmarkBatch>` object.
1758///
1759/// First create an object that holds in the input parameters for the benchmark:
1760///
1761/// ```ignore
1762/// let params = (&config, &whitelist);
1763/// ```
1764///
1765/// The `whitelist` is a parameter you pass to control the DB read/write tracking.
1766/// We use a vector of [TrackedStorageKey](./struct.TrackedStorageKey.html), which is a simple
1767/// struct used to set if a key has been read or written to.
1768///
1769/// For values that should be skipped entirely, we can just pass `key.into()`. For example:
1770///
1771/// ```
1772/// use pezsp_storage::TrackedStorageKey;
1773/// let whitelist: Vec<TrackedStorageKey> = vec![
1774/// 	// Block Number
1775/// 	array_bytes::hex_into_unchecked("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac"),
1776/// 	// Total Issuance
1777/// 	array_bytes::hex_into_unchecked("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80"),
1778/// 	// Execution Phase
1779/// 	array_bytes::hex_into_unchecked("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a"),
1780/// 	// Event Count
1781/// 	array_bytes::hex_into_unchecked("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850"),
1782/// ];
1783/// ```
1784///
1785/// Then define a mutable local variable to hold your `BenchmarkBatch` object:
1786///
1787/// ```ignore
1788/// let mut batches = Vec::<BenchmarkBatch>::new();
1789/// ````
1790///
1791/// Then add the pallets you want to benchmark to this object, using their crate name and generated
1792/// module struct:
1793///
1794/// ```ignore
1795/// add_benchmark!(params, batches, pezpallet_balances, Balances);
1796/// add_benchmark!(params, batches, pezpallet_session, SessionBench::<Runtime>);
1797/// add_benchmark!(params, batches, pezframe_system, SystemBench::<Runtime>);
1798/// ...
1799/// ```
1800///
1801/// At the end of `dispatch_benchmark`, you should return this batches object.
1802///
1803/// In the case where you have multiple instances of a pezpallet that you need to separately
1804/// benchmark, the name of your module struct will be used as a suffix to your outputted weight
1805/// file. For example:
1806///
1807/// ```ignore
1808/// add_benchmark!(params, batches, pezpallet_balances, Balances); // pezpallet_balances.rs
1809/// add_benchmark!(params, batches, pezpallet_collective, Council); // pezpallet_collective_council.rs
1810/// add_benchmark!(params, batches, pezpallet_collective, TechnicalCommittee); // pezpallet_collective_technical_committee.rs
1811/// ```
1812///
1813/// You can manipulate this suffixed string by using a type alias if needed. For example:
1814///
1815/// ```ignore
1816/// type Council2 = TechnicalCommittee;
1817/// add_benchmark!(params, batches, pezpallet_collective, Council2); // pezpallet_collective_council_2.rs
1818/// ```
1819#[macro_export]
1820macro_rules! add_benchmark {
1821	( $params:ident, $batches:ident, $name:path, $location:ty ) => {
1822		let pezpallet_string = stringify!($name).replace(" ", "").into_bytes();
1823		let instance_string = stringify!($location).replace(" ", "").into_bytes();
1824		let (config, whitelist) = $params;
1825		let $crate::BenchmarkConfig {
1826			pezpallet,
1827			instance,
1828			benchmark,
1829			selected_components,
1830			verify,
1831			internal_repeats,
1832		} = config;
1833		if &pezpallet[..] == &pezpallet_string[..] && &instance[..] == &instance_string[..] {
1834			let benchmark_result = <$location as $crate::Benchmarking>::run_benchmark(
1835				&benchmark[..],
1836				&selected_components[..],
1837				whitelist,
1838				*verify,
1839				*internal_repeats,
1840			);
1841
1842			let final_results = match benchmark_result {
1843				Ok(results) => Some(results),
1844				Err($crate::BenchmarkError::Override(mut result)) => {
1845					// Insert override warning as the first storage key.
1846					$crate::__private::log::error!(
1847						"WARNING: benchmark error overridden - {}",
1848						$crate::__private::str::from_utf8(benchmark)
1849							.expect("benchmark name is always a valid string!")
1850					);
1851					result.keys.insert(0, (b"Benchmark Override".to_vec(), 0, 0, false));
1852					Some($crate::__private::vec![result])
1853				},
1854				Err($crate::BenchmarkError::Stop(e)) => {
1855					$crate::show_benchmark_debug_info(
1856						&instance_string,
1857						benchmark,
1858						selected_components,
1859						verify,
1860						e,
1861					);
1862					return Err(e.into());
1863				},
1864				Err($crate::BenchmarkError::Skip) => {
1865					$crate::__private::log::error!(
1866						"WARNING: benchmark error skipped - {}",
1867						$crate::__private::str::from_utf8(benchmark)
1868							.expect("benchmark name is always a valid string!")
1869					);
1870					None
1871				},
1872				Err($crate::BenchmarkError::Weightless) => {
1873					$crate::__private::log::error!(
1874						"WARNING: benchmark weightless skipped - {}",
1875						$crate::__private::str::from_utf8(benchmark)
1876							.expect("benchmark name is always a valid string!")
1877					);
1878					Some($crate::__private::vec![$crate::BenchmarkResult {
1879						components: selected_components.clone(),
1880						..Default::default()
1881					}])
1882				},
1883			};
1884
1885			if let Some(final_results) = final_results {
1886				$batches.push($crate::BenchmarkBatch {
1887					pezpallet: pezpallet_string,
1888					instance: instance_string,
1889					benchmark: benchmark.clone(),
1890					results: final_results,
1891				});
1892			}
1893		}
1894	};
1895}
1896
1897/// This macro allows users to easily generate a list of benchmarks for the pallets configured
1898/// in the runtime.
1899///
1900/// To use this macro, first create an object to store the list:
1901///
1902/// ```ignore
1903/// let mut list = Vec::<BenchmarkList>::new();
1904/// ```
1905///
1906/// Then pass this `list` to the macro, along with the `extra` boolean, the pezpallet crate, and
1907/// pezpallet struct:
1908///
1909/// ```ignore
1910/// list_benchmark!(list, extra, pezpallet_balances, Balances);
1911/// list_benchmark!(list, extra, pezpallet_session, SessionBench::<Runtime>);
1912/// list_benchmark!(list, extra, pezframe_system, SystemBench::<Runtime>);
1913/// ```
1914///
1915/// This should match what exists with the `add_benchmark!` macro.
1916#[macro_export]
1917macro_rules! list_benchmark {
1918	( $list:ident, $extra:ident, $name:path, $location:ty ) => {
1919		let pezpallet_string = stringify!($name).replace(" ", "").into_bytes();
1920		let instance_string = stringify!($location).replace(" ", "").into_bytes();
1921		let benchmarks = <$location as $crate::Benchmarking>::benchmarks($extra);
1922		let pezpallet_benchmarks = $crate::BenchmarkList {
1923			pezpallet: pezpallet_string,
1924			instance: instance_string,
1925			benchmarks: benchmarks.to_vec(),
1926		};
1927		$list.push(pezpallet_benchmarks)
1928	};
1929}
1930
1931/// Defines pezpallet configs that `add_benchmarks` and `list_benchmarks` use.
1932/// Should be preferred instead of having a repetitive list of configs
1933/// in `add_benchmark` and `list_benchmark`.
1934#[macro_export]
1935macro_rules! define_benchmarks {
1936	( $([ $names:path, $locations:ty ])* ) => {
1937		/// Calls `list_benchmark` with all configs from `define_benchmarks`
1938		/// and passes the first two parameters on.
1939		///
1940		/// Use as:
1941		/// ```ignore
1942		/// list_benchmarks!(list, extra);
1943		/// ```
1944		#[macro_export]
1945		macro_rules! list_benchmarks {
1946			( $list:ident, $extra:ident ) => {
1947				$( $crate::list_benchmark!( $list, $extra, $names, $locations); )*
1948			}
1949		}
1950
1951		/// Calls `add_benchmark` with all configs from `define_benchmarks`
1952		/// and passes the first two parameters on.
1953		///
1954		/// Use as:
1955		/// ```ignore
1956		/// add_benchmarks!(params, batches);
1957		/// ```
1958		#[macro_export]
1959		macro_rules! add_benchmarks {
1960			( $params:ident, $batches:ident ) => {
1961				$( $crate::add_benchmark!( $params, $batches, $names, $locations ); )*
1962			}
1963		}
1964	}
1965}
1966
1967pub use add_benchmark;
1968pub use benchmark_backend;
1969pub use benchmarks;
1970pub use benchmarks_instance;
1971pub use benchmarks_instance_pallet;
1972pub use benchmarks_iter;
1973pub use define_benchmarks;
1974pub use impl_bench_case_tests;
1975pub use impl_bench_name_tests;
1976pub use impl_benchmark;
1977pub use impl_benchmark_test;
1978pub use impl_benchmark_test_suite;
1979pub use impl_test_function;
1980pub use list_benchmark;
1981pub use selected_benchmark;
1982pub use to_origin;
1983pub use whitelist;