referrerpolicy=no-referrer-when-downgrade

frame_benchmarking/
v1.rs

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