Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
sam0x17 committed Jan 8, 2023
1 parent 1db7acf commit 914b473
Showing 1 changed file with 158 additions and 2 deletions.
160 changes: 158 additions & 2 deletions frame/support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2747,23 +2747,179 @@ pub mod pallet_macros {
};
}

/// Contains macros, structs, and traits associated with v2 of the pallet benchmarking syntax.
/// This module contains macros, structs, and traits associated with v2 of the pallet
/// benchmarking syntax.
///
/// The [`benchmarking::benchmarks`] and [`benchmarking::instance_benchmarks`] macros can be
/// used to designate a module as a benchmarking module that can contain benchmarks and
/// benchmark tests. The `#[benchmarks]` variant will set up a regular, non-instance
/// benchmarking module, and the `#[instance_benchmarks]` variant will set up the module in
/// instance benchmarking mode.
///
/// Benchmarking modules should be gated behind a `#[cfg(feature = "runtime-benchmarks")]`
/// feature gate to ensure benchmarking code that is only compiled when the
/// `runtime-benchmarks` feature is enabled is not referenced.
///
/// The following is the general syntax for a benchmarks (or instance benchmarks) module:
///
/// ## General Syntax
///
/// ```
/// #![cfg(feature = "runtime-benchmarks")]
///
/// use super::{mock_helpers::*, Pallet as MyPallet};
/// use frame_support::benchmarking::*;
/// use frame_benchmarking::whitelisted_caller;
///
/// #[benchmarks]
/// mod benchmarks {
/// use super::*;
///
/// #[benchmark]
/// fn bench_name_1(x: Linear<7, 1_000>, y: Linear<1_000, 100_0000>) {
/// // setup code
/// let z = x + y;
/// let caller = whitelisted_caller();
///
/// #[extrinsic_call]
/// extrinsic_name(SystemOrigin::Signed(caller), other, arguments);
///
/// // verification code
/// assert_eq!(MyPallet::<T>::my_var(), z);
/// }
///
/// #[benchmark]
/// fn bench_name_2() {
/// // setup code
/// let caller = whitelisted_caller();
///
/// #[extrinsic_call]
/// {
/// something(some, thing);
/// my_extrinsic(RawOrigin::Signed(caller), some, argument);
/// something_else(foo, bar);
/// }
///
/// // verification_code
/// assert_eq!(MyPallet::<T>::something(), 37);
/// }
/// }
/// ```
///
/// ## Benchmark Definitions
///
/// Within a `#[benchmarks]` or `#[instance_benchmarks]` module, you can define individual
/// benchmarks using the `#[benchmark]` attribute, as shown in the example above.
///
/// The `#[benchmark]` attribute expects a function definition with a blank return type and
/// zero or more arguments whose names are valid `frame_benchmarking::BenchmarkParamater`
/// parameters, such as `x`, `y`, `a`, `b`, etc., and whose param types must implement
/// [`benchmarking::ParamRange`]. At the moment the only valid type that implements
/// [`benchmarking::ParamRange`] is [`benchmarking::Linear`].
///
/// The valid syntax for defining a `Linear` is `Linear<A, B>` where `A`, and `B` are
/// valid integer literals (that fit in a `u32`), such that `B` > `A`.
///
/// Note that the benchmark function definition does not actually expand as a function
/// definition, but rather is used to automatically create a number of impls and structs
/// required by the benchmarking engine. For this reason, the visibility of the function
/// definition as well as the return type are not used for any purpose and are discarded by the
/// expansion code.
///
/// ### `#[extrinsic_call]`
///
/// Within the benchmark function body, an `#[extrinsic_call]` annotation is required. This
/// attribute should be attached to a block (shown in `bench_name_2` above) or a one-line
/// function call (shown in `bench_name_1` above, in `syn` parlance this should be an
/// `ExprCall`). The block syntax can contain any code but should have an extrinsic call
/// somewhere inside it. The one-line, `ExprCall` syntax must consist of a function call to an
/// extrinsic, where the first argument is the origin. If `#[extrinsic_call]` is attached to an
/// item that doesn't meet these requirements, a compiler error will be emitted.
///
/// The `#[extrinsic_call]` attribute also serves the purpose of designating the boundary
/// between the setup code portion of the benchmark (everything before the `#[extrinsic_call]`)
/// and the verification stage (everything after the item that `#[extrinsic_call]`) is attached
/// to. The setup code section should contain any code that needs to execute before the
/// measured portion of the benchmark executes. The verification section is where you can
/// perform assertions to verify that the extrinsic call (or whatever is happening in your
/// `#[extrinsic_call]` block, if you used a block) executed successfully.
///
/// Note that `#[extrinsic_call]` is not a real attribute macro and is consumed by the outer
/// macro pattern as part of the enclosing benchmark function definition. This is why we are
/// able to use `#[extrinsic_call]` within a function definition even though this behavior has
/// not been stabilized yet—`#[extrinsic_call]` is parsed and consumed as part of the benchmark
/// definition parsing code so it never expands as its own macro.
///
/// ### `#[extra]`
///
/// The optional `#[extra]` attribute can be applied to benchmark function definitions. This
/// attribute follows the semantics and behavior it did in the old benchmarking syntax in
/// `frame_benchmarking`.
///
/// ## `#[skip_meta]`
///
/// The optional `#[skip_meta]` attribute can be applied to benchmark function definitions.
/// This attribute follows the semantics and behavior it did in the old benchmarking syntax in
/// `frame_benchmarking`.
///
/// ## Where Clause
///
/// Some pallets require a where clause specifying constraints on their generics to make
/// writing benchmarks feasible. To accomodate this situation, you can provide such a where
/// clause as the (only) argument to the `#[benchmarks]` or `#[instance_benchmarks]` attribute
/// macros. Below is an example of this taken from the `message-queue` pallet.
///
/// ```
/// #[benchmarks(
/// where
/// <<T as Config>::MessageProcessor as ProcessMessage>::Origin: From<u32> + PartialEq,
/// <T as Config>::Size: From<u32>,
/// )]
/// mod benchmarks {
/// use super::*;
/// // ...
/// }
/// ```
///
/// ## Benchmark Tests
///
/// Benchmark tests can be generated using the old syntax in `frame_benchmarking`,
/// including the `frame_benchmarking::impl_benchmark_test_suite` macro.
///
/// An example is shown below (taken from the `message-queue` pallet's `benchmarking` module):
/// ```
/// #[benchmarks]
/// mod benchmarks {
/// use super::*;
/// // ...
/// impl_benchmark_test_suite!(
/// MessageQueue,
/// crate::mock::new_test_ext::<crate::integration_test::Test>(),
/// crate::integration_test::Test
/// );
/// }
/// ```
pub mod benchmarking {
pub use frame_support_procedural::{benchmark, benchmarks, instance_benchmarks};

// Used in #[benchmark] to ensure that benchmark function arguments implement [`ParamRange`].
// Used in #[benchmark] implementation to ensure that benchmark function arguments
// implement [`ParamRange`].
#[doc(hidden)]
pub use static_assertions::assert_impl_all;

/// Used by the new benchmarking code to specify that a benchmarking variable is linear
/// over some specified range, i.e. `Linear<0, 1_000>` means that the corresponding variable
/// is allowed to range from `0` to `1000`, inclusive.
///
/// See [`frame_support::benchmarking`] for more info.
pub struct Linear<const A: u32, const B: u32>;

/// Trait that must be implemented by all structs that can be used as parameter range types
/// in the new benchmarking code (i.e. `Linear<0, 1_000>`). Right now there is just
/// [`Linear`] but this could later be extended to support additional non-linear parameter
/// ranges.
///
/// See [`frame_support::benchmarking`] for more info.
pub trait ParamRange {
/// Represents the (inclusive) starting number of this [`ParamRange`].
fn start(&self) -> u32;
Expand Down

0 comments on commit 914b473

Please sign in to comment.