Skip to content

feat: add regex perf benchmarking command - #641

Open
fzipi wants to merge 19 commits into
mainfrom
feat/regex-perf
Open

feat: add regex perf benchmarking command#641
fzipi wants to merge 19 commits into
mainfrom
feat/regex-perf

Conversation

@fzipi

@fzipi fzipi commented Jun 9, 2026

Copy link
Copy Markdown
Member

Summary

Adds a ftw regex perf command that benchmarks the runtime performance of a regular expression against a set of input subjects.

  • Compiles a regex from an OWASP CRS regex-assembly (.ra) file via the crs-toolchain assembler, or takes a raw --pattern directly.
  • Sources subjects from the existing quantitative corpus (--corpus leipzig/raw and related flags) or a single inline --subject.
  • Times each subject with Go's regexp engine (RE2), keeping the minimum of --repeat matches, and reports total, mean, median, p99, max, throughput, and the top-N slowest subjects in normal or json output.

Because it uses RE2 (linear time), it measures Coraza-realistic performance and is not a ReDoS detector; this is stated in the command help and README.

Implementation

  • New package internal/regexperf: compile.go (assembler integration + Go compile), stats.go (aggregation, percentiles, bounded top-N heap, normal/JSON output), benchmark.go (orchestration and min-of-K timing).
  • New cmd/regex package with the regex parent group and perf subcommand, registered on the root command.
  • Reuses the existing internal/corpus loaders by calling the leipzig/raw constructors directly, so the Coraza engine is not pulled into this package.
  • Adds dependency github.com/coreruleset/crs-toolchain/v2 v2.9.0. go mod verify passes; govulncheck reports no new vulnerabilities introduced by this change.

Notes

  • The crs-toolchain assembler calls os.Exit when an include fragment cannot be opened. A preflight step validates that each top-level include referenced by the .ra file exists under <crs-path>/regex-assembly/include (or /exclude) and returns an actionable error instead. Includes referenced transitively by other fragments are not validated and remain a documented limitation.
  • The raw corpus path is validated before the run to avoid the corpus layer's os.Exit on a missing file.

Test Plan

  • go test -race ./... passes
  • go build ./... and go vet ./... clean
  • ftw regex perf --pattern '(?i)union\s+select' --subject "' UNION SELECT 1,2,3" -o json returns a report with subjectCount:1, matchCount:1
  • ftw regex perf --file <some>.ra -C <coreruleset> -s 10K compiles and benchmarks against the corpus

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added ftw regex perf CLI to benchmark regexes (from CRS assembly or raw pattern) against a corpus or single subject; reports total/mean/median/p99/max, throughput, and top‑N slowest subjects; JSON output supported and wired into the CLI.
  • Documentation

    • Added user guidance, design spec, planning doc, and repository usage notes.
  • Tests

    • Added comprehensive tests for CLI validation, assembler/compile behavior, benchmarking, stats, and edge cases.
  • Chores

    • Updated module dependencies.

fzipi and others added 16 commits June 8, 2026 14:07
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the preflightAssembly stub with a real implementation that
detects `include`/`include-except` directives and returns an actionable
error when the crsRoot has no regex-assembly/ directory, preventing the
crs-toolchain assembler from calling logger.Fatal (os.Exit).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add Params struct, Run orchestrator, resolveRegex, runCorpus, newCorpus,
and timeMatch helpers to internal/regexperf; all 19 package tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@fzipi, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 29 minutes and 13 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bfe571cb-dd34-40f6-b524-da23fe0f7f3b

📥 Commits

Reviewing files that changed from the base of the PR and between 75d7237 and cc1d2a3.

📒 Files selected for processing (4)
  • cmd/regex/perf.go
  • cmd/regex/perf_test.go
  • cmd/regex/regex.go
  • cmd/root.go
📝 Walkthrough

Walkthrough

Adds a new ftw regex command with a perf subcommand, implements internal regexperf (compile, benchmark, stats), wires CLI/root, updates dependencies, and adds comprehensive tests and documentation.

Changes

Regex Performance Benchmarking Feature

Layer / File(s) Summary
Design specification and dependency updates
docs/superpowers/plans/2026-06-08-regex-perf.md, docs/superpowers/specs/2026-06-08-regex-perf-design.md, go.mod
Architecture plan and design spec (CLI, data flow, outputs, testing), plus go.mod updates adding github.com/coreruleset/crs-toolchain/v2 v2.9.0 and related indirect dependencies.
Regex assembly and compilation
internal/regexperf/compile.go, internal/regexperf/compile_test.go
Reads .ra files with a preflight include check and invokes the CRS toolchain assembler, then compiles the assembled regex with Go's RE2 and tests assembly, compile errors, and include handling.
Performance statistics framework
internal/regexperf/stats.go, internal/regexperf/stats_test.go
Accumulates per-subject min-timings and match counts, computes mean/median/P99/max/throughput, retains top‑N slowest subjects using a heap, and emits JSON or human-readable summaries with truncation and tests.
Benchmark orchestration and execution
internal/regexperf/benchmark.go, internal/regexperf/benchmark_test.go
Defines Params and Run to resolve/compile regex, benchmark inline subject or corpus (repeat/min timing semantics), enforce subject limits, and populate Stats; includes integration-style tests for inline and corpus modes and error cases.
CLI command hierarchy and wiring
cmd/regex/regex.go, cmd/regex/perf.go, cmd/regex/perf_test.go, cmd/regex_wiring_test.go, cmd/root.go
Adds regex parent and perf subcommand, registers flags and validates mutual exclusions (--file vs --pattern, --subject vs corpus flags), validates raw corpus path, supports --out-file, and registers the command on the root CLI; includes CLI validation and wiring tests.
User and contributor documentation
README.md, CLAUDE.md
Documents the new ftw regex perf feature with usage examples and JSON output, and adds CLAUDE.md with repository and contributor guidance including testing patterns and configuration notes.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as CLI
  participant PerfCmd as cmd/regex/perf.runPerfE
  participant Assembler as crs-toolchain
  participant Compiler as regexp.Compile
  participant Corpus as CorpusIterator
  participant Stats as regexperf.Stats
  participant Output as output.Output

  CLI->>PerfCmd: invoke ftw regex perf (--file/--pattern, --subject/--corpus)
  PerfCmd->>Assembler: Assemble .ra (if --file)
  PerfCmd->>Compiler: Compile regex (assembled or raw)
  PerfCmd->>Corpus: create iterator (corpus or raw)
  Corpus->>PerfCmd: provide subject strings
  PerfCmd->>Compiler: Match subject N times (timeMatch)
  PerfCmd->>Stats: Add(subject, minNs, matched)
  Stats->>Output: printSummary (json/plain)
  PerfCmd->>Output: write to stdout or --out-file
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

enhancement

Suggested reviewers

  • theseion

Poem

🐰 I hop through patterns, timing each thread,
From assembled rules to the subjects I tread.
Min-times and percentiles, the slowest I keep,
I print them in JSON, then tumble to sleep.
Benchmarked and boxed — now carrots instead.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 74.07% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add regex perf benchmarking command' is a concise, clear summary that directly aligns with the main change—adding a new CLI command for regex performance benchmarking.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/regex-perf

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (1)
CLAUDE.md (1)

84-84: ⚡ Quick win

Add languages to fenced code blocks to satisfy markdown linting.

These fences are unlabeled and trigger MD040; add text (or another appropriate language) after the opening backticks.

Suggested patch
-```
+```text
 CLI Layer (cmd/)
     ↓ orchestrates
 Runner Layer (runner/)
@@
-```
+```text
 YAML Test File
   ↓ Unmarshal (test package)
 schema.Test with stages

Also applies to: 140-140

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CLAUDE.md` at line 84, The unlabeled fenced code blocks in CLAUDE.md are
triggering MD040; update each opening triple-backtick to include a language
(e.g., change ``` to ```text) for the code examples shown (the block containing
"CLI Layer (cmd/)"→"Runner Layer (runner/)" and the block containing "YAML Test
File"→"schema.Test with stages") so both fences are labeled (use `text` or
another appropriate language).

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CLAUDE.md`:
- Line 100: Update the documented CLI subcommand list to include the new
regex-related commands by adding `regex` (and `regex perf` if applicable)
alongside the existing `run`, `check`, `quantitative`, and `self_update` entries
so the README reflects the PR changes and contributor guidance stays current;
reference the new subcommands `regex` and `regex perf` in the same list format
where the CLI subcommands are enumerated.
- Line 254: Update the platform name to the official capitalization "GitHub" in
the sentence containing "CI runs tests on Ubuntu and Windows" in CLAUDE.md;
locate the sentence "CI runs tests on Ubuntu and Windows (see
`.github/workflows/test.yml`)" and replace any occurrence of "Github" or
"github" with "GitHub" so the docs use the correct branding.

In `@cmd/regex/perf_test.go`:
- Line 4: The test file declares the wrong package; change the package
declaration in perf_test.go from "package cmd" to "package regex" so the tests
live in and can access the regex package (ensure any package-level test
utilities or imports still compile after changing the package name, e.g.,
references in perf_test.go to functions/types from regex).

In `@cmd/regex/perf.go`:
- Line 4: The file cmd/regex/perf.go currently declares the wrong package;
change its package declaration from "cmd" to "regex" so the file belongs to the
regex package and can be imported by cmd/root.go; update the top-level package
line in perf.go (the file containing perf-related code) to "package regex".

In `@cmd/regex/regex.go`:
- Line 4: The package declaration at the top of this file is incorrect — change
the package line from `package cmd` to `package regex` so it matches the import
alias and usage elsewhere (see import `regex
"github.com/coreruleset/go-ftw/v2/cmd/regex"` and the call to
`regex.New(cmdContext)` in root.go); update only the package name in this file
to `regex` to resolve the compilation error.

In `@docs/superpowers/plans/2026-06-08-regex-perf.md`:
- Line 13: The heading "Resolved spec open-items (verified against crs-toolchain
`main`)" is using H3 (###) and creates a level jump; change that heading to the
correct level (e.g., ##) to continue the H1/H2 flow so it satisfies
MD001/markdown-lint and remove the level jump introduced by the "### Resolved
spec open-items (verified against crs-toolchain `main`)" line.

In `@docs/superpowers/specs/2026-06-08-regex-perf-design.md`:
- Around line 65-69: The doc currently uses two different flag names
(`--file-out` in the table and `--out-file` elsewhere), causing confusion;
update all occurrences to use the single canonical flag `--out-file` (the same
long flag used by the implemented command and referenced in the `quantitative`
command) — change the table entry label, the note text that mentions
`--file-out`, and any other mentions in the spec so every reference consistently
uses `--out-file`.
- Line 39: Several fenced code blocks in the spec file are unlabeled (triggering
MD040); locate the unlabeled triple-backtick fences (examples around the blocks
referenced) and add appropriate language identifiers (e.g., text, bash, go) to
each opening fence so markdownlint stops flagging them—ensure you update the
fences at the mentioned locations (around lines 39, 73, 81, 134, 165) by
replacing ``` with ```text, ```bash, or ```go as appropriate for the snippet
contents.

---

Nitpick comments:
In `@CLAUDE.md`:
- Line 84: The unlabeled fenced code blocks in CLAUDE.md are triggering MD040;
update each opening triple-backtick to include a language (e.g., change ``` to
```text) for the code examples shown (the block containing "CLI Layer
(cmd/)"→"Runner Layer (runner/)" and the block containing "YAML Test
File"→"schema.Test with stages") so both fences are labeled (use `text` or
another appropriate language).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2af42fde-ddf2-48db-ad8f-a938229d07fe

📥 Commits

Reviewing files that changed from the base of the PR and between 2483899 and c10a4f3.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (16)
  • CLAUDE.md
  • README.md
  • cmd/regex/perf.go
  • cmd/regex/perf_test.go
  • cmd/regex/regex.go
  • cmd/regex_wiring_test.go
  • cmd/root.go
  • docs/superpowers/plans/2026-06-08-regex-perf.md
  • docs/superpowers/specs/2026-06-08-regex-perf-design.md
  • go.mod
  • internal/regexperf/benchmark.go
  • internal/regexperf/benchmark_test.go
  • internal/regexperf/compile.go
  • internal/regexperf/compile_test.go
  • internal/regexperf/stats.go
  • internal/regexperf/stats_test.go

Comment thread CLAUDE.md Outdated
Comment thread CLAUDE.md
Comment thread cmd/regex/perf_test.go Outdated
Comment thread cmd/regex/perf.go Outdated
Comment thread cmd/regex/regex.go Outdated
Comment thread docs/superpowers/plans/2026-06-08-regex-perf.md Outdated
Comment thread docs/superpowers/specs/2026-06-08-regex-perf-design.md Outdated
Comment thread docs/superpowers/specs/2026-06-08-regex-perf-design.md Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant