bench_matrix is a Rust utility crate designed to simplify the creation and execution of parameterized benchmarks, especially when using the Criterion benchmarking harness. It allows you to define a matrix of input parameters and automatically run your benchmark logic for every combination of these parameters.
Core Concepts:
- Parameter Axis: A list of possible values for a single dimension of your benchmark configuration. For example, an axis could represent different buffer sizes
[64, 128, 256]or different algorithms["AlgorithmA", "AlgorithmB"]. - Parameter Names: A list of human-readable names corresponding to each parameter axis, used for generating descriptive benchmark IDs.
MatrixCellValue: An enum representing a single value within a parameter axis (e.g., a specific tag, string, integer, or boolean).AbstractCombination: A struct representing one unique combination ofMatrixCellValues, one from each defined axis. This forms a single "row" in your conceptual parameter matrix.- Configuration Extraction (
ExtractorFn): A user-provided function that takes anAbstractCombinationand translates it into a concrete, strongly-typed configuration struct (defined by the user) that the benchmark logic will use. - Benchmark Suites (
SyncBenchmarkSuite,AsyncBenchmarkSuite): The primary structures for defining and running a set of parameterized benchmarks. They orchestrate combination generation, configuration extraction, and integration with Criterion.SyncBenchmarkSuite: For benchmarking synchronous code.AsyncBenchmarkSuite: For benchmarking asynchronous code, typically with a Tokio runtime.
- Benchmark Lifecycle Functions: Users provide several callback functions to the suites to define the benchmark behavior:
- Setup: Prepares the necessary state and context for a benchmark sample.
- Logic: Contains the actual code to be measured.
- Teardown: Cleans up resources after a benchmark sample.
- Global Setup/Teardown: Run once per concrete configuration, before and after all benchmarks for that configuration are defined.
Main Entry Points:
The primary way to interact with bench_matrix is by:
- Defining your parameter axes using
Vec<Vec<MatrixCellValue>>and their corresponding names usingVec<String>. - Creating an instance of either
SyncBenchmarkSuiteorAsyncBenchmarkSuite. - Providing the necessary callback functions (extractor, setup, logic, teardown) to the suite.
- Optionally configuring the suite further using its builder methods (e.g.,
.global_setup(),.throughput()). - Calling the
run()method on the suite instance within your Criterion benchmark functions. This will create a single benchmark group named after your suite, with each parameter combination registered as a separate benchmark within that group (e.g.,MySuite/ParamA-Val1_ParamB-Val2).
Pervasive Types and Patterns:
MatrixCellValueandAbstractCombination: These are fundamental for defining and working with parameter combinations.- Function Pointers/Closures: The library extensively uses function pointers (e.g.,
fn(...) -> ...) andBox<dyn Fn(...)>for user-provided callbacks. This allows for flexible and type-safe customization of the benchmarking process. - User-Defined Configuration (
Cfg), State (S), and Context (CtxT): The benchmark suites are generic over these types, which are defined by the user to match the specific needs of their benchmarks.Cfg: Your concrete configuration struct derived from anAbstractCombination.S: The state that is set up before benchmarking and potentially modified by it.CtxT: An optional context that can be passed through benchmark iterations within a sample.
- Error Handling: User-provided functions like the
ExtractorFnorGlobalSetupFntypically returnResult<T, UserErrorType>. The suites will report these errors and skip benchmark variants accordingly.
This reference is organized by the public modules of the bench_matrix crate.
These are items re-exported at the top level of the bench_matrix crate for convenience.
Common Type Aliases:
pub type ExtractorFn<Cfg, ExtErr = String> = Box<dyn Fn(&AbstractCombination) -> Result<Cfg, ExtErr>>;pub type GlobalSetupFn<Cfg> = Box<dyn FnMut(&Cfg) -> Result<(), String>>;pub type GlobalTeardownFn<Cfg> = Box<dyn FnMut(&Cfg) -> Result<(), String>>;
Async Suite Type Aliases:
pub type AsyncSetupFn<S, Cfg, CtxT, SetupErr = String> = fn(&Runtime, &Cfg) -> Pin<Box<dyn Future<Output = Result<(CtxT, S), SetupErr>> + Send>>;pub type AsyncBenchmarkLogicFn<S, Cfg, CtxT> = fn(CtxT, S, &Cfg) -> Pin<Box<dyn Future<Output = (CtxT, S, Duration)> + Send>>;pub type AsyncTeardownFn<S, Cfg, CtxT> = fn(CtxT, S, &Runtime, &Cfg) -> Pin<Box<dyn Future<Output = ()> + Send>>;
Sync Suite Type Aliases:
pub type SyncSetupFn<S, Cfg, CtxT, SetupErr = String> = fn(&Cfg) -> Result<(CtxT, S), SetupErr>;pub type SyncBenchmarkLogicFn<S, Cfg, CtxT> = fn(CtxT, S, &Cfg) -> (CtxT, S, Duration);pub type SyncTeardownFn<S, Cfg, CtxT> = fn(CtxT, S, &Cfg) -> ();
Structs (Async Suite Specific):
pub use criterion_runner::async_suite::AsyncBenchmarkSuite;(Seebench_matrix::criterion_runner::async_suitemodule for details)
Structs (Sync Suite Specific):
pub use criterion_runner::sync_suite::SyncBenchmarkSuite;(Seebench_matrix::criterion_runner::sync_suitemodule for details)
Structs (Parameter Definition):
pub use params::AbstractCombination;(Seebench_matrix::paramsmodule for details)
Enums (Parameter Definition):
pub use params::MatrixCellValue;(Seebench_matrix::paramsmodule for details)
Functions (Combination Generation):
pub use generator::generate_combinations;(Seebench_matrix::generatormodule for details)
This module provides types for defining individual parameter values and combinations of them.
Enum MatrixCellValue:
Represents a single value that can be part of a parameter axis.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
(Also implements Display, and various From<T> traits for ergonomic construction.)
- Variants:
Tag(String),String(String),Int(i64),Unsigned(u64),Bool(bool).
Struct AbstractCombination:
Represents one specific combination of abstract parameter values.
#[derive(Debug, Clone)]
- Public Fields:
pub cells: Vec<MatrixCellValue>
- Public Methods:
pub fn id_suffix(&self) -> String- Generates a string suffix for benchmark IDs (e.g.,
_StdTokio_Uint4096_Booltrue). ForStringvalues, it sanitizes non-alphanumeric characters to underscores.
- Generates a string suffix for benchmark IDs (e.g.,
pub fn id_suffix_with_names(&self, param_names: &[String]) -> String- Generates a descriptive string suffix, incorporating parameter names (e.g.,
_Backend-Uring_BlockSize-512). If the length ofparam_namesdoes not match the number of cells, it prints a warning and falls back toid_suffix().
- Generates a descriptive string suffix, incorporating parameter names (e.g.,
pub fn get_tag(&self, index: usize) -> Result<&str, String>pub fn get_string(&self, index: usize) -> Result<&str, String>pub fn get_i64(&self, index: usize) -> Result<i64, String>pub fn get_u64(&self, index: usize) -> Result<u64, String>pub fn get_bool(&self, index: usize) -> Result<bool, String>- Helpers to get a cell by index and interpret it as a specific type. Returns a
Resultto handle index-out-of-bounds or type mismatch errors.
- Helpers to get a cell by index and interpret it as a specific type. Returns a
This module provides utilities for generating parameter combinations.
Struct CombinationIterator:
An iterator that lazily generates the Cartesian product of benchmark parameter axes.
#[derive(Debug, Clone)]
- Description: This struct is highly memory-efficient as it generates each
AbstractCombinationon the fly. It implementsExactSizeIterator, allowing the use of.len()to get the total number of combinations without consuming the iterator. - Implementation Details:
impl<'a> Iterator for CombinationIterator<'a>impl<'a> ExactSizeIterator for CombinationIterator<'a>
Function generate_combinations:
Creates a CombinationIterator over a set of parameter axes.
- Signature:
pub fn generate_combinations(axes: &[Vec<MatrixCellValue>]) -> CombinationIterator - Parameters:
axes: A slice ofVec<MatrixCellValue>. Each innerVecrepresents one parameter axis.
- Returns:
- A
CombinationIteratorthat will lazily yield all generated combinations. Ifaxesis empty or if any individual axis is empty, the returned iterator will have a length of 0.
- A
Provides the SyncBenchmarkSuite for orchestrating synchronous benchmarks.
Struct SyncBenchmarkSuite:
Orchestrates a suite of synchronous benchmarks.
- Signature:
pub struct SyncBenchmarkSuite<'s, S, Cfg, CtxT, ExtErr = String, SetupErr = String> - Public Methods:
pub fn new(criterion: &'s mut Criterion<WallTime>, suite_base_name: String, parameter_names: Option<Vec<String>>, parameter_axes: Vec<Vec<MatrixCellValue>>, extractor_fn: ExtractorFn<Cfg, ExtErr>, setup_fn: SyncSetupFn<S, Cfg, CtxT, SetupErr>, benchmark_logic_fn: SyncBenchmarkLogicFn<S, Cfg, CtxT>, teardown_fn: SyncTeardownFn<S, Cfg, CtxT>) -> Self- Constructs a new
SyncBenchmarkSuite. All parameters are required to build the suite.
- Constructs a new
pub fn parameter_names(self, names: Vec<String>) -> Self- Builder method to set or override the parameter names.
pub fn global_setup(self, f: impl FnMut(&Cfg) -> Result<(), String> + 'static) -> Self- Sets the global setup function, a closure that runs once per unique concrete configuration (
Cfg).
- Sets the global setup function, a closure that runs once per unique concrete configuration (
pub fn global_teardown(self, f: impl FnMut(&Cfg) -> Result<(), String> + 'static) -> Self- Sets the global teardown function.
pub fn configure_criterion_group(self, f: impl for<'g> Fn(&mut BenchmarkGroup<'g, WallTime>) + 'static) -> Self- Provides a closure to customize the
criterion::BenchmarkGroup(e.g., to set plot configurations, sample sizes, etc.).
- Provides a closure to customize the
pub fn throughput(self, f: impl Fn(&Cfg) -> Throughput + 'static) -> Self- Provides a closure to calculate
criterion::Throughputfor each benchmark variant based on its concrete configurationCfg.
- Provides a closure to calculate
pub fn run(mut self)- Executes the benchmark suite. This creates a single benchmark group (named
suite_base_name) and registers each parameter combination as a benchmark within it.
- Executes the benchmark suite. This creates a single benchmark group (named
Provides the AsyncBenchmarkSuite for orchestrating asynchronous benchmarks.
Struct AsyncBenchmarkSuite:
Orchestrates a suite of asynchronous benchmarks.
- Signature:
pub struct AsyncBenchmarkSuite<'s, S, Cfg, CtxT, ExtErr = String, SetupErr = String> - Public Methods:
pub fn new(criterion: &'s mut Criterion<WallTime>, runtime: &'s Runtime, suite_base_name: String, parameter_names: Option<Vec<String>>, parameter_axes: Vec<Vec<MatrixCellValue>>, extractor_fn: ExtractorFn<Cfg, ExtErr>, setup_fn: AsyncSetupFn<S, Cfg, CtxT, SetupErr>, benchmark_logic_fn: AsyncBenchmarkLogicFn<S, Cfg, CtxT>, teardown_fn: AsyncTeardownFn<S, Cfg, CtxT>) -> Self- Constructs a new
AsyncBenchmarkSuite. Requires a reference to a TokioRuntimein addition to the parameters required by the sync suite.
- Constructs a new
pub fn parameter_names(self, names: Vec<String>) -> Self- Builder method to set or override the parameter names.
pub fn global_setup(self, f: impl FnMut(&Cfg) -> Result<(), String> + 'static) -> Self- Sets the global setup function.
pub fn global_teardown(self, f: impl FnMut(&Cfg) -> Result<(), String> + 'static) -> Self- Sets the global teardown function.
pub fn configure_criterion_group(self, f: impl for<'g> Fn(&mut BenchmarkGroup<'g, WallTime>) + 'static) -> Self- Provides a closure to customize the
criterion::BenchmarkGroup.
- Provides a closure to customize the
pub fn throughput(self, f: impl Fn(&Cfg) -> Throughput + 'static) -> Self- Provides a closure to calculate
criterion::Throughputfor each benchmark variant.
- Provides a closure to calculate
pub fn run(mut self)- Executes the asynchronous benchmark suite, creating a single benchmark group and registering each parameter combination as a benchmark within it.
bench_matrix itself does not define a global error enum. Instead, error handling relies on:
- User-Provided Error Types:
- The
ExtractorFnandSetupFns have generic error types (ExtErr,SetupErr) that default toString.
- The
- Panics: If a setup function (e.g.,
AsyncSetupFnorSyncSetupFncalled within Criterion's sampling loop) fails with an error, the benchmark suites willpanic!with a descriptive message. - Reporting: The benchmark suites print error messages to
stderrwhen:- Combination extraction fails (variant skipped).
- Global setup for a configuration fails (variant skipped).
- A mismatch occurs between the length of
parameter_namesandparameter_axes(warning).
Users are responsible for handling errors within their benchmark_logic_fn and teardown_fn implementations.