Benchmarking Guide

February 26, 2026 · View on GitHub

Performance Tracking and Regression Detection


Quick Start

# Run benchmark suite
./naab/build/naab-lang benchmark.naab vessels/

# Generate HTML report
./naab/build/naab-lang benchmark.naab vessels/ --format html > report.html

# Regression detection
./naab/build/naab-lang benchmark.naab vessels/ \
  --baseline baseline.json \
  --regression-threshold 5

Benchmark Specifications

File: compute.bench.json

{
  "name": "compute_benchmark",
  "vessel": "vessels/compute_vessel",
  "iterations": 100,
  "warmup": 10,
  "timeout_ms": 10000,
  "inputs": [
    {"n": 1000000},
    {"n": 10000000},
    {"n": 100000000}
  ]
}

Running Benchmarks

Single Benchmark

use benchmark

main {
    let result = benchmark.run_single_benchmark("compute.bench.json")

    io.write("Mean: ", result["mean"], "ms\n")
    io.write("Median: ", result["median"], "ms\n")
    io.write("P95: ", result["p95"], "ms\n")
    io.write("P99: ", result["p99"], "ms\n")
}

Benchmark Suite

use benchmark

main {
    let report = benchmark.run_suite("./vessels/")

    for result in report["results"] {
        io.write(result["benchmark"], ": ", result["mean"], "ms\n")
    }
}

Statistical Analysis

Metrics Collected

  • Mean: Average execution time
  • Median: Middle value (50th percentile)
  • Min/Max: Fastest/slowest execution
  • Standard Deviation: Variability measure
  • P95/P99: 95th/99th percentile (tail latency)

Example Output

{
  "benchmark": "heavy_computation",
  "iterations": 100,
  "statistics": {
    "mean": 812.34,
    "median": 812.00,
    "min": 810.00,
    "max": 815.00,
    "stddev": 1.42,
    "p95": 814.50,
    "p99": 815.00
  }
}

Regression Detection

Setup Baseline

# First run - establish baseline
./naab/build/naab-lang benchmark.naab vessels/ --save-baseline baseline.json

Compare Against Baseline

# Subsequent runs - detect regressions
./naab/build/naab-lang benchmark.naab vessels/ \
  --baseline baseline.json \
  --regression-threshold 10

Output:

  [BENCHMARK] Comparing against baseline...
    compute_vessel: 812ms (baseline: 800ms) → +1.5% ✓
    process_vessel: 1234ms (baseline: 1100ms) → +12.2% ⚠ REGRESSION

Exit code 6 if regression detected


Report Formats

JSON Report

./naab/build/naab-lang benchmark.naab vessels/ --format json > report.json

Output:

{
  "timestamp": 1234567890,
  "results": [...],
  "baseline": {...},
  "regressions": []
}

HTML Report

./naab/build/naab-lang benchmark.naab vessels/ --format html > report.html

Includes:

  • Interactive charts (Chart.js)
  • Performance trends
  • Regression highlights
  • Comparison tables

CSV Report

./naab/build/naab-lang benchmark.naab vessels/ --format csv > report.csv

Format:

benchmark,mean,median,min,max,stddev,p95,p99
compute,812.34,812.00,810.00,815.00,1.42,814.50,815.00

SARIF Report

./naab/build/naab-lang benchmark.naab vessels/ --format sarif > report.sarif

Upload to GitHub Code Scanning for regression tracking.


CI/CD Integration

GitHub Actions

name: Performance Benchmarks

on: [push, pull_request]

jobs:
  benchmark:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          submodules: recursive

      - name: Build NAAb
        run: bash build.sh

      - name: Run Benchmarks
        run: |
          ./naab/build/naab-lang benchmark.naab vessels/ \
            --baseline baseline.json \
            --regression-threshold 5 \
            --format sarif > benchmark.sarif

      - name: Upload Results
        if: always()
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: benchmark.sarif

Best Practices

1. Sufficient Iterations

Use at least 100 iterations for statistical significance:

{
  "iterations": 100,
  "warmup": 10
}

2. Control Environment

Run benchmarks on consistent hardware:

# Disable CPU frequency scaling
sudo cpupower frequency-set --governor performance

# Run benchmarks
./naab/build/naab-lang benchmark.naab vessels/

# Re-enable scaling
sudo cpupower frequency-set --governor powersave

3. Isolate Workloads

Close other applications during benchmarking:

# Check CPU usage
top -b -n 1 | head -20

# Run benchmarks when system is idle
./naab/build/naab-lang benchmark.naab vessels/

4. Track Historical Data

Store benchmark results over time:

# Timestamp results
DATE=$(date +%Y-%m-%d)
./naab/build/naab-lang benchmark.naab vessels/ \
  --format json > "benchmark-history/$DATE.json"

5. Set Realistic Thresholds

Allow some variance (5-10%):

# Too strict (may have false positives)
--regression-threshold 1

# Recommended
--regression-threshold 10

Advanced Features

Custom Test Inputs

{
  "name": "matrix_multiply",
  "inputs": [
    {"size": 100, "density": 0.1},
    {"size": 500, "density": 0.5},
    {"size": 1000, "density": 1.0}
  ]
}

Memory Profiling

# Track memory usage
/usr/bin/time -v ./vessels/compute_vessel 10000000 2>&1 | grep "Maximum resident"

Parallel Benchmarking

// Run multiple benchmarks in parallel
use benchmark

main {
    let bench_files = ["compute.bench.json", "process.bench.json", "transform.bench.json"]

    // Run in parallel (if supported)
    let results = []
    for bench_file in bench_files {
        let result = benchmark.run_single_benchmark(bench_file)
        results.push(result)
    }
}

Next: Plugins Guide | Troubleshooting