Skip to content

ci: add performance regression gate with criterion benchmarks #151

@membphis

Description

@membphis

Background

qjson positions itself as a high-performance JSON parser, but currently lacks automated performance regression detection. Benchmarks exist (benches/lua_bench.lua) but run manually without CI enforcement.

Goal

Prevent unintentional performance degradation by adding automated benchmark comparison to CI.

Scope

In Scope

  • Add Rust criterion benchmarks for core parse paths (eager/lazy, field access)
  • Integrate benchmark comparison into PR CI using benchmark-action/github-action-benchmark
  • Set regression threshold: >5% degradation triggers warning (not blocking)
  • Store baseline results in gh-pages branch

Out of Scope

  • Lua-level benchmarks in CI (keep manual due to OpenResty setup complexity)
  • Micro-benchmarks for every function (focus on user-facing parse/access paths)

Design

1. Criterion Benchmarks

File: benches/rust_bench.rs

Benchmark groups:

  • parse_eager - eager mode parsing (full validation)
  • parse_lazy - lazy mode parsing (structural scan only)
  • field_access - field access operations (get_str, get_f64, nested paths)

Fixtures (based on manifest.json ci tags):

  • PR level: rest_api_small (2KB), wide_object (3KB), deep_nesting (0.5KB)
  • Full level: additionally rest_api_medium (60KB), unicode_heavy_twitter (631KB)

Cargo.toml changes:

[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }

[[bench]]
name = "rust_bench"
harness = false

2. CI Workflow

New file: .github/workflows/bench.yml

Triggers:

  • push to main → run benchmarks, update gh-pages baseline
  • pull_request → run benchmarks, compare against main baseline, post PR comment

Job structure:

jobs:
  benchmark:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    steps:
      - checkout (with submodules for fixtures)
      - install stable rust
      - cargo bench --bench rust_bench -- --output-format bencher
      - benchmark-action/github-action-benchmark:
          tool: cargo
          output-file-path: target/criterion/output.txt
          github-token: ${{ secrets.GITHUB_TOKEN }}
          auto-push: true (main only)
          comment-on-alert: true
          alert-threshold: "105%"  # >5% regression triggers warning
          fail-on-alert: false     # non-blocking, reviewer decides
          gh-pages-branch: gh-pages
          benchmark-data-dir-path: dev/bench

3. Makefile Integration

bench-rust:  ## Run Rust criterion benchmarks
	cargo bench --bench rust_bench

4. Initialization

  • First merge to main auto-creates baseline in gh-pages
  • PR comments show comparison table with regression highlighting
  • 5% regression marked yellow/red but does not block merge

Acceptance Criteria

  • cargo bench runs criterion benchmarks covering parse_eager, parse_lazy, field access patterns
  • CI job compares PR benchmarks against main branch baseline
  • PRs with >5% regression on any benchmark are flagged (not auto-blocked, but visible in PR comment)
  • Baseline artifacts stored in gh-pages branch

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions