Parameterized Benchmarkπ
This tutorial demonstrates how to create a parameterized benchmark using SimpleBench, run it, and generate a report.
Parameterized benchmarks allow you to run the same benchmark function multiple times with different input parameters.
The key components of a parameterized benchmark are:
Benchmark Function: A function decorated with @simplebench.benchmark that contains the code to be benchmarked. The functionβs signature should explicitly define the parameters that will be varied. SimpleBench will automatically pass the values from the kwargs_variations to these parameters.
Parameters: Defined as arguments for the @simplebench.benchmark decorator, which specifies different values to be used as inputs to the benchmark function.
kwargs_variationsA dictionary where the keys are parameter names that match the arguments of the benchmarked function and values are lists of possible values for those parameters.
The benchmark will be executed for every combination of the provided parameter values.
Example
kwargs_variations={ 'arg1': [1, 2], 'arg2': ['a', 'b'] }
will result in the following combinations being tested:
{'arg1': 1, 'arg2': 'a'} {'arg1': 1, 'arg2': 'b'} {'arg1': 2, 'arg2': 'a'} {'arg1': 2, 'arg2': 'b'}
variation_colsA dictionary where keys are parameter names and values are display names for reporting. Fields not included here will usually not display in a report. Fields specified here must be a subset of the keys in
kwargs_variations.Example
variation_cols={ 'arg1': 'Argument 1', 'arg2': 'Argument 2' }
This will result in the report displaying columns/fields labeled βArgument 1β and βArgument 2β corresponding to the values of βarg1β and βarg2β used in each benchmark run.
use_field_for_nA string specifying a parameter to use as the βNβ field in reports, which is often used to indicate input size for complexity analysis. This parameter should be one of the keys in
kwargs_variations. It is optional; if not specified, the βNβ field will default to the value β1.0β.This is useful when you want to analyze how the performance of the benchmarked function scales with different input sizes or configurations. It is not required that the field be defined in
variation_colsto be used as the βNβ field.
Minimal Exampleπ
The minimal code required to create and run a parameterized benchmark using SimpleBench is creating a script that defines a function to be benchmarked with @simplebench.benchmark, specifying parameters using the @simplebench.benchmark decorator, and that calls simplebench.main()
1"""A basic parameterized benchmark."""
2import simplebench
3
4
5@simplebench.benchmark(kwargs_variations={'size': [1, 5, 10, 50, 100, 500, 1000]},
6 variation_cols={'size': 'Input Size'},
7 use_field_for_n='size')
8def addition_benchmark(size: int) -> None:
9 """A simple addition benchmark of Python's built-in sum function."""
10 sum(range(size))
11
12
13if __name__ == "__main__":
14 simplebench.main()
Save this code to a file, for example minimal_parameterized_benchmark.py, and then run it from
your terminal:
python minimal_parameterized_benchmark.py --rich-table.ops --progress
This will produce output similar to the following:
addition_benchmark
operations per second
A simple addition benchmark of Python's built-in sum function.
ββββββββββββββ³βββββββββ³βββββββββββββ³βββββββββ³ββββββββββ³ββββββββββββββ³ββββββββββββββββ³βββββββββββββ³βββββββββββββ³βββββββββββββ³ββββββββββββββ³βββββββββββββββββ³βββββββββ
β β β β β Elapsed β β β β β β β β β
β Input Size β N β Iterations β Rounds β Seconds β mean kOps/s β median kOps/s β min kOps/s β max kOps/s β 5th kOps/s β 95th kOps/s β std dev kOps/s β rsd% β
β‘βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β 1 β 1.0 β 1010264 β 1 β 0.22 β 4710.00 β 4810.00 β 46.50 β 12000.00 β 4000.00 β 5990.00 β 483.00 β 10.30% β
β 5 β 5.0 β 792381 β 1 β 0.18 β 4500.00 β 4780.00 β 40.10 β 12000.00 β 4000.00 β 4810.00 β 426.00 β 9.48% β
β 10 β 10.0 β 626015 β 1 β 0.15 β 4170.00 β 4000.00 β 26.40 β 8000.00 β 4000.00 β 4810.00 β 388.00 β 9.30% β
β 50 β 50.0 β 481444 β 1 β 0.19 β 2600.00 β 2670.00 β 42.20 β 4000.00 β 2400.00 β 2670.00 β 195.00 β 7.51% β
β 100 β 100.0 β 358702 β 1 β 0.20 β 1840.00 β 1850.00 β 48.10 β 2400.00 β 1720.00 β 2000.00 β 116.00 β 6.28% β
β 500 β 500.0 β 38035 β 1 β 0.11 β 340.00 β 343.00 β 47.70 β 358.00 β 333.00 β 348.00 β 20.90 β 6.15% β
β 1000 β 1000.0 β 13805 β 1 β 0.09 β 147.00 β 149.00 β 11.50 β 152.00 β 144.00 β 150.00 β 8.38 β 5.69% β
ββββββββββββββ΄βββββββββ΄βββββββββββββ΄βββββββββ΄ββββββββββ΄ββββββββββββββ΄ββββββββββββββββ΄βββββββββββββ΄βββββββββββββ΄βββββββββββββ΄ββββββββββββββ΄βββββββββββββββββ΄βββββββββ
A detailed explanation of the output format and displayed statistics shown in this example report can be found in the Rich Table Report section of the documentation.
Note
The command shown above includes the --progress option to
display a progress bar while the benchmark is running. This option is not
required to run the benchmark, and can be omitted if you do not wish to see
the progress bar. It is not included in the expected output file since it
produces dynamic output that changes as the benchmark runs and is removed
from the terminal once the benchmark completes.
Multi-dimensional Parametersπ
You can define multiple parameters for a benchmark function by defining multiple parameters for the kwargs_variations.
For example, to benchmark a function with two parameters, size and mode, you can define the benchmark as follows:
1"""A multidimensional parameterized benchmark."""
2import simplebench
3
4
5@simplebench.benchmark(
6 kwargs_variations={
7 'size': [10, 100, 1000],
8 'mode': ['fast', 'slow']
9 },
10 variation_cols={
11 'size': 'Input Size',
12 'mode': 'Mode'
13 },
14 use_field_for_n='size')
15def my_benchmark(size: int, mode: str) -> None:
16 """A benchmark for summing a range of numbers that varies by size and mode."""
17 match mode:
18 case 'fast':
19 sum(range(size))
20 case 'slow':
21 total = 0
22 for i in range(size):
23 total += i
24
25
26if __name__ == "__main__":
27 simplebench.main()
Save this code to a file, for example
multidimensional_parameterized_benchmark.py,
and then run it from your terminal:
python multidimensional_parameterized_benchmark.py --rich-table.ops --progress
This will run the benchmark for all combinations of size and mode, resulting in six different benchmark runs (3 sizes x 2 modes). The report will include columns for both βInput Sizeβ and βModeβ, allowing you to analyze the performance across these different dimensions.
And you will see output similar to the following:
my_benchmark
operations per second
A benchmark for summing a range of numbers that varies by size and mode.
ββββββββββββββ³βββββββ³βββββββββ³βββββββββββββ³βββββββββ³ββββββββββ³ββββββββββββββ³ββββββββββββββββ³βββββββββββββ³βββββββββββββ³βββββββββββββ³ββββββββββββββ³βββββββββββββββββ³βββββββββ
β β β β β β Elapsed β β β β β β β β β
β Input Size β Mode β N β Iterations β Rounds β Seconds β mean kOps/s β median kOps/s β min kOps/s β max kOps/s β 5th kOps/s β 95th kOps/s β std dev kOps/s β rsd% β
β‘ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β 10 β fast β 10.0 β 927749 β 1 β 0.25 β 3800.00 β 4000.00 β 28.70 β 8000.00 β 3420.00 β 4000.00 β 392.00 β 10.30% β
β 10 β slow β 10.0 β 728337 β 1 β 0.32 β 2330.00 β 2400.00 β 35.00 β 3440.00 β 2180.00 β 2670.00 β 161.00 β 6.92% β
β 100 β fast β 100.0 β 537489 β 1 β 0.31 β 1740.00 β 1720.00 β 24.70 β 2400.00 β 1600.00 β 1850.00 β 116.00 β 6.65% β
β 100 β slow β 100.0 β 139185 β 1 β 0.33 β 425.00 β 428.00 β 26.20 β 471.00 β 414.00 β 444.00 β 25.50 β 5.99% β
β 1000 β fast β 1000.0 β 22429 β 1 β 0.16 β 140.00 β 141.00 β 27.60 β 149.00 β 138.00 β 146.00 β 8.45 β 6.03% β
β 1000 β slow β 1000.0 β 7963 β 1 β 0.20 β 40.50 β 40.80 β 9.17 β 43.50 β 39.10 β 42.10 β 2.20 β 5.44% β
ββββββββββββββ΄βββββββ΄βββββββββ΄βββββββββββββ΄βββββββββ΄ββββββββββ΄ββββββββββββββ΄ββββββββββββββββ΄βββββββββββββ΄βββββββββββββ΄βββββββββββββ΄ββββββββββββββ΄βββββββββββββββββ΄βββββββββ
You can customize the parameter values and names as needed for your specific benchmarking scenarios.