CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pytest-benchmark

A pytest fixture for benchmarking code that automatically calibrates test runs for accurate performance measurements.

Pending
Overview
Eval results
Files

configuration.mddocs/

Configuration and Customization

Overview

pytest-benchmark provides extensive configuration options through pytest command-line arguments, configuration files, and test markers. You can control timing parameters, output formats, storage options, and benchmark behavior.

Test Markers

@pytest.mark.benchmark

@pytest.mark.benchmark(**kwargs)
def test_function(benchmark):
    """
    Mark a test with custom benchmark settings.
    
    Supported kwargs:
        max_time (float): Maximum time per test in seconds
        min_rounds (int): Minimum number of rounds
        min_time (float): Minimum time per round in seconds  
        timer (callable): Timer function to use
        group (str): Benchmark group name
        disable_gc (bool): Disable garbage collection
        warmup (bool): Enable warmup rounds
        warmup_iterations (int): Number of warmup iterations
        calibration_precision (int): Calibration precision factor
        cprofile (bool): Enable cProfile integration
    """

Command-Line Options

Timing Control

# Timing parameters
--benchmark-min-time SECONDS        # Minimum time per round (default: 0.000005)
--benchmark-max-time SECONDS        # Maximum time per test (default: 1.0)  
--benchmark-min-rounds NUM          # Minimum rounds (default: 5)
--benchmark-timer FUNC              # Timer function (default: platform default)
--benchmark-calibration-precision NUM  # Calibration precision (default: 10)

Warmup Options

# Warmup configuration
--benchmark-warmup KIND             # Warmup mode: auto/on/off (default: auto)
--benchmark-warmup-iterations NUM   # Max warmup iterations (default: 100000)

Execution Control

# Benchmark execution
--benchmark-disable-gc              # Disable GC during benchmarks
--benchmark-skip                    # Skip benchmark tests
--benchmark-disable                 # Disable benchmarking (run once)
--benchmark-enable                  # Force enable benchmarks
--benchmark-only                    # Only run benchmark tests

Display Options

# Result display
--benchmark-sort COL                # Sort column: min/max/mean/stddev/name/fullname
--benchmark-group-by LABEL          # Grouping: group/name/fullname/func/fullfunc/param
--benchmark-columns LABELS          # Comma-separated column list
--benchmark-name FORMAT             # Name format: short/normal/long/trial
--benchmark-verbose                 # Verbose output
--benchmark-quiet                   # Quiet mode

Storage and Persistence

# Storage options
--benchmark-storage URI             # Storage URI (default: file://./.benchmarks)
--benchmark-netrc FILE              # Netrc file for credentials
--benchmark-save NAME               # Save results with name
--benchmark-autosave                # Auto-save with timestamp
--benchmark-save-data               # Include timing data in saves

Output Formats

# Export formats  
--benchmark-json PATH               # Export to JSON
--benchmark-csv FILENAME            # Export to CSV
--benchmark-histogram FILENAME      # Generate histograms

Performance Analysis

# Profiling
--benchmark-cprofile COLUMN         # Enable cProfile with sort column
--benchmark-cprofile-loops LOOPS    # cProfile iteration count
--benchmark-cprofile-top COUNT      # Number of profile rows to show
--benchmark-cprofile-dump PREFIX    # Save cProfile dumps

Comparison

# Result comparison
--benchmark-compare NUM             # Compare against run number
--benchmark-compare-fail EXPR       # Fail on performance regression

Usage Examples

Basic Marker Usage

@pytest.mark.benchmark(group="string_ops", min_rounds=10)
def test_string_processing(benchmark):
    def process_text(text):
        return text.upper().replace(' ', '_')
    
    result = benchmark(process_text, "hello world")
    assert result == "HELLO_WORLD"

Timing Customization

@pytest.mark.benchmark(
    max_time=2.0,           # Run for up to 2 seconds
    min_rounds=5,           # At least 5 rounds
    min_time=0.01           # Each round at least 10ms
)
def test_slow_operation(benchmark):
    def slow_function():
        time.sleep(0.01)
        return sum(range(1000))
    
    result = benchmark(slow_function)
    assert result == 499500

Custom Timer

import time

@pytest.mark.benchmark(timer=time.process_time)
def test_cpu_intensive(benchmark):
    def cpu_work():
        return sum(x**2 for x in range(10000))
    
    result = benchmark(cpu_work)
    assert result == 333283335000

Grouping and Organization

@pytest.mark.benchmark(group="database")
def test_db_insert(benchmark):
    def insert_data():
        # Simulate database insert
        return "inserted"
    
    result = benchmark(insert_data)
    assert result == "inserted"

@pytest.mark.benchmark(group="database") 
def test_db_select(benchmark):
    def select_data():
        # Simulate database select
        return ["row1", "row2"]
    
    result = benchmark(select_data)
    assert len(result) == 2

Command-Line Usage Examples

Basic Benchmarking

# Run all tests with benchmarks
pytest --benchmark-only

# Skip benchmark tests
pytest --benchmark-skip

# Run with custom timing
pytest --benchmark-min-rounds=10 --benchmark-max-time=2.0

Result Display

# Sort by mean time, show specific columns
pytest --benchmark-sort=mean --benchmark-columns=min,max,mean,stddev

# Group by test function name
pytest --benchmark-group-by=func

# Verbose output with detailed timing
pytest --benchmark-verbose

Saving and Comparison

# Save baseline results
pytest --benchmark-save=baseline

# Compare against baseline
pytest --benchmark-compare=baseline

# Auto-save with timestamp
pytest --benchmark-autosave

# Fail if performance regresses by more than 5%
pytest --benchmark-compare-fail=mean:5%

Export Formats

# Export to multiple formats
pytest --benchmark-json=results.json \
       --benchmark-csv=results.csv \
       --benchmark-histogram=charts

# Generate cProfile data
pytest --benchmark-cprofile=cumtime \
       --benchmark-cprofile-top=10 \
       --benchmark-cprofile-dump=profiles

Configuration Files

pytest.ini Configuration

[tool:pytest]
addopts = 
    --benchmark-min-rounds=5
    --benchmark-sort=min
    --benchmark-group-by=group
    --benchmark-columns=min,max,mean,stddev,median,ops,rounds

# Storage configuration
benchmark_storage = file://.benchmarks
benchmark_autosave = true

pyproject.toml Configuration

[tool.pytest.ini_options]
addopts = [
    "--benchmark-min-rounds=5",
    "--benchmark-sort=min", 
    "--benchmark-group-by=group"
]

benchmark_storage = "file://.benchmarks"
benchmark_autosave = true

Advanced Configuration

Custom Timer Functions

import time

def custom_timer():
    """Custom high-precision timer."""
    return time.perf_counter()

@pytest.mark.benchmark(timer=custom_timer)
def test_with_custom_timer(benchmark):
    result = benchmark(lambda: sum(range(1000)))
    assert result == 499500

Storage URI Formats

# File storage (default)
--benchmark-storage=file://.benchmarks
--benchmark-storage=file:///absolute/path/benchmarks

# Elasticsearch storage  
--benchmark-storage=elasticsearch+http://localhost:9200/benchmarks/pytest
--benchmark-storage=elasticsearch+https://user:pass@host:9200/index/type

# With authentication
--benchmark-storage=elasticsearch+https://host:9200/index \
--benchmark-netrc=~/.netrc

Environment Variables

# Override via environment
export PYTEST_BENCHMARK_DISABLE=1
export PYTEST_BENCHMARK_STORAGE="file:///tmp/benchmarks"

pytest  # Uses environment settings

Programmatic Configuration

# conftest.py
def pytest_configure(config):
    # Programmatic configuration
    config.option.benchmark_min_rounds = 10
    config.option.benchmark_sort = 'mean'
    config.option.benchmark_group_by = 'group'

Performance Regression Detection

Threshold Expressions

# Fail if mean increases by more than 5%
--benchmark-compare-fail=mean:5%

# Fail if minimum time increases by more than 100ms
--benchmark-compare-fail=min:0.1

# Multiple thresholds
--benchmark-compare-fail=mean:10% --benchmark-compare-fail=max:20%

Expression Formats

# Supported comparison expressions:
"mean:5%"          # Percentage increase in mean
"min:0.001"        # Absolute increase in seconds  
"max:10%"          # Percentage increase in max
"stddev:50%"       # Percentage increase in stddev

Integration with CI/CD

GitHub Actions Example

- name: Run benchmarks
  run: |
    pytest --benchmark-only \
           --benchmark-json=benchmark.json \
           --benchmark-compare-fail=mean:10%

- name: Upload benchmark results
  uses: actions/upload-artifact@v2
  with:
    name: benchmark-results
    path: benchmark.json

Jenkins Example

# Save baseline in master branch
pytest --benchmark-save=master --benchmark-json=master.json

# Compare feature branch
pytest --benchmark-compare=master \
       --benchmark-compare-fail=mean:15% \
       --benchmark-json=feature.json

Install with Tessl CLI

npx tessl i tessl/pypi-pytest-benchmark

docs

analysis-reporting.md

aspect-benchmarking.md

cli-tools.md

configuration.md

core-benchmarking.md

index.md

storage-comparison.md

tile.json