Skip to content

[codex] Add parse benchmark watchdog - #6

Merged
tinovyatkin merged 5 commits into
mainfrom
tino/parse-benchmark-watchdog
May 23, 2026
Merged

[codex] Add parse benchmark watchdog#6
tinovyatkin merged 5 commits into
mainfrom
tino/parse-benchmark-watchdog

Conversation

@tinovyatkin

@tinovyatkin tinovyatkin commented May 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a parse-performance benchmark harness for the Rust runtime against Python and Go ANTLR4 runtimes plus tree-sitter parser baselines.

What changed

  • Added tools/parse-bench/run.py, which regenerates Kotlin and C# ANTLR parsers from pinned grammars-v4 inputs, builds Rust and Go timing runners, and runs Python ANTLR plus tree-sitter baselines.
  • Added 4 Kotlin and 4 C# compact fixtures with upstream source references in fixtures/manifest.json.
  • Added tools/parse-bench/compare.py to fail CI when rust-antlr regresses past a configurable threshold.
  • Added documentation and Python requirements for local benchmark setup.
  • Added a GitHub Actions workflow that runs quick benchmarks on PRs, compares against base once the workflow exists there, and uploads JSON reports.

Why

This gives the runtime a repeatable performance signal that can be run locally and wired into PRs as a regression watchdog, while still showing how the Rust runtime lines up against established reference parsers.

Validation

  • python3 -m py_compile tools/parse-bench/run.py tools/parse-bench/compare.py
  • /tmp/antlr-bench-probe/venv/bin/python tools/parse-bench/run.py --quick --python /tmp/antlr-bench-probe/venv/bin/python --json target/parse-bench/quick-final.json
  • tools/parse-bench/compare.py --baseline target/parse-bench/quick-final.json --current target/parse-bench/quick-final.json

Summary by CodeRabbit

  • New Features

    • Added parse-benchmarking infrastructure to measure ANTLR and tree-sitter parser performance across Kotlin and C# fixtures.
    • Implemented CI/CD workflow for automated benchmark comparisons with regression detection.
  • Documentation

    • Added comprehensive documentation for parse-bench tool covering setup, usage modes, and CI integration.
  • Chores

    • Updated dependencies and build configuration to support benchmarking tools.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@tinovyatkin has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 49 minutes and 13 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, 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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e0e59630-6537-402c-b203-aea936c001fd

📥 Commits

Reviewing files that changed from the base of the PR and between 0e4975f and 75636aa.

📒 Files selected for processing (3)
  • .github/workflows/parse-bench.yml
  • tools/parse-bench/compare.py
  • tools/parse-bench/run.py
📝 Walkthrough

Walkthrough

This PR introduces a standalone parse-benchmark tool for comparing ANTLR-generated parsers against tree-sitter across Kotlin and C# fixtures, integrated with GitHub Actions to detect performance regressions in pull requests.

Changes

Parse Benchmark Tool

Layer / File(s) Summary
CI Workflow and Infrastructure
.github/workflows/parse-bench.yml, .gitignore, tools/parse-bench/requirements.txt
GitHub Actions workflow orchestrates benchmark runs on PR and manual trigger, sets up toolchains (Java, Go, Python, Rust), downloads ANTLR jar, runs base/head benchmarks conditionally, compares results with --max-regression 1.15, and uploads JSON artifacts. Python cache directories are ignored.
Documentation and Benchmark Guide
tools/parse-bench/README.md
Comprehensive guide covering standalone harness design, environment setup (ANTLR jar, grammars-v4, sparse checkout), quick vs. full benchmark modes, CI workflow integration with compare.py, and fixture metadata organization.
Test Fixtures and Manifest
tools/parse-bench/fixtures/csharp/*, tools/parse-bench/fixtures/kotlin/*, tools/parse-bench/fixtures/manifest.json
Eight benchmark fixtures from upstream Kotlin and C# codebases (Compose desktop, Collections samples, Coroutines flow tests, Android Ktor, System.Boolean, Teleprompter, Newtonsoft JsonConvert, Roslyn SyntaxKind) with source URLs and license metadata in manifest.json.
Regression Comparison Tool
tools/parse-bench/compare.py
CLI tool loads baseline and current JSON reports, matches results by (language, fixture, runtime), computes slowdown ratios, and fails with detailed error output if any ratio exceeds the --max-regression threshold (default 1.15).
Core Harness: Data Models and Orchestration
tools/parse-bench/run.py (sections 1–6)
Defines LanguageSpec, Fixture, and Measurement dataclasses; provides subprocess execution, input validation, and fixture loading utilities; orchestrates grammar copying, C# grammar transformations per runtime, ANTLR code generation, and safe work directory management.
Rust Runtime Code Generation
tools/parse-bench/run.py (sections 7–8)
Generates Rust modules via cargo-based codegen, writes benchmark runner with warmup/timed parse loops tracking min/avg nanoseconds, and emits per-language parse function templates.
Python and Tree-sitter Runners
tools/parse-bench/run.py (sections 9–10)
Writes Python ANTLR runner lazily importing generated parsers and executing timed benchmarks, and writes tree-sitter runner with language validation and parse-error node checking.
Go Runtime Code Generation
tools/parse-bench/run.py (sections 11–12)
Generates standalone Go benchmark runner with main.go and go.mod, embeds per-language parse dispatch, runs warmups and timed iterations, and copies generated parser sources into working directory.
Execution, Measurement, and Reporting
tools/parse-bench/run.py (sections 13–16)
Executes runtime runners with standardized CLI arguments, parses output for min/avg nanoseconds, formats terminal table with per-fixture Rust baseline comparisons, emits JSON/Markdown reports with git revision metadata, and wires CLI argument parsing and validation into main entry point.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

A rabbit built a benchmark race,
where parsers parse with measured pace,
Rust and Python, Go and tree,
ANTLR powers all three!
JSON reports the winner's trace. 🐰⚡

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 '[codex] Add parse benchmark watchdog' clearly describes the main change: introducing a new parse benchmark watchdog system. It's concise and directly relates to the primary objective of adding a performance monitoring harness.
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 tino/parse-benchmark-watchdog

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.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a comprehensive benchmarking suite in tools/parse-bench to evaluate the parse throughput of ANTLR and tree-sitter parsers across Rust, Python, and Go runtimes. The implementation includes Kotlin and C# fixtures, automated parser generation, and a regression comparison script. Feedback from the review focused on adding safety checks to prevent accidental directory deletion and ensuring compatibility with older Python versions by adjusting the UTC timezone reference.

Comment thread tools/parse-bench/run.py Outdated
Comment thread tools/parse-bench/run.py Outdated
@tinovyatkin
tinovyatkin marked this pull request as ready for review May 22, 2026 21:49
@greptile-apps

greptile-apps Bot commented May 22, 2026

Copy link
Copy Markdown

Confidence Score: 5/5

Safe to merge — this is an additive benchmarking harness with no changes to runtime or library code.

The three previously flagged issues (silent watchdog pass, missing if: always() on artifact upload, Go ANTLR version mismatch) are all addressed. The only remaining finding is the missing SHA check on the ANTLR jar download, which is a hardening suggestion with no impact on correctness or functionality.

.github/workflows/parse-bench.yml — the ANTLR jar fetch lacks integrity verification; worth adding a sha256sum check consistent with the pinned grammars-v4 commit.

Security Review

  • The ANTLR jar (antlr-4.13.2-complete.jar) is downloaded via curl over HTTPS without a SHA/hash check. The jar is executed by java -jar in CI to generate source code that is subsequently compiled and run. A server-side compromise of antlr.org or a CDN cache poisoning attack could substitute a malicious jar, leading to arbitrary code execution in the CI runner. The grammars-v4 dependency is pinned to a specific commit hash, so adding an equivalent sha256sum check for the jar would close this inconsistency.

Fix All in Codex Fix All in Claude Code

Reviews (2): Last reviewed commit: "Harden parse benchmark workflow" | Re-trigger Greptile

Comment thread tools/parse-bench/run.py
Comment thread tools/parse-bench/compare.py
Comment thread .github/workflows/parse-bench.yml
Comment thread tools/parse-bench/run.py Outdated

@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: 4

🧹 Nitpick comments (2)
.github/workflows/parse-bench.yml (1)

1-10: ⚡ Quick win

Declare explicit workflow permissions (least privilege).

Add an explicit permissions block (for example, contents: read) to avoid inheriting broader defaults.

Suggested patch
 name: Parse Benchmark

 on:
   pull_request:
   workflow_dispatch:

+permissions:
+  contents: read
+
 jobs:
   parse-bench:
🤖 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 @.github/workflows/parse-bench.yml around lines 1 - 10, The workflow
currently lacks an explicit permissions block which may grant
broader-than-needed access; add a top-level permissions key (for example
permissions: contents: read) to the workflow YAML (near the existing name: Parse
Benchmark / on: pull_request entries) to declare least-privilege access for this
workflow and ensure the parse-bench job runs with only the necessary
permissions.
tools/parse-bench/fixtures/manifest.json (1)

6-56: ⚡ Quick win

Use commit-pinned source permalinks for fixture provenance.

The source URLs point to mutable branch heads (main/master). Please switch these to commit-specific blob URLs so fixture attribution and provenance remain stable over time.

🤖 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 `@tools/parse-bench/fixtures/manifest.json` around lines 6 - 56, Replace
mutable branch-head URLs in the "source" fields with commit-pinned blob URLs in
tools/parse-bench/fixtures/manifest.json: for each entry (e.g., paths
kotlin/kotlinx-coroutines-flow.kt, kotlin/ktor-android-client.kt,
kotlin/compose-window.kt, csharp/dotnet-runtime-boolean.cs,
csharp/roslyn-syntax-kind.cs, csharp/newtonsoft-jsonconvert.cs,
csharp/dotnet-samples-teleprompter.cs) find the current canonical commit SHA on
the upstream repo and update the "source" value from a branch URL (…/blob/main
or …/blob/master/...) to the commit-specific form
…/blob/<commit-sha>/<file-path>; ensure every "source" key in the manifest is
replaced so provenance is stable.
🤖 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 @.github/workflows/parse-bench.yml:
- Line 14: Replace the mutable action tags with immutable commit SHAs: update
each `uses:` entry that currently uses moving tags (`actions/checkout@v4`,
`actions/checkout@v5`, `actions/setup-java@v4`, `actions/setup-go@v4`,
`actions/setup-python@v4`, `actions/upload-artifact@v4`) to the corresponding
full commit SHA for that action release; locate the `uses:` lines in the
workflow and substitute the tag (e.g., `@vX`) with the action's pinned commit
SHA so the workflow references a fixed immutable revision.
- Around line 13-17: The checkout steps (e.g., the step named "Checkout head"
that uses actions/checkout@v4 and the other actions/checkout@v4 step in the same
workflow) are missing persist-credentials: false; update both checkout steps to
add persist-credentials: false under their with: block so the GITHUB_TOKEN is
not persisted into the repository git config during the job.

In `@tools/parse-bench/compare.py`:
- Around line 68-76: The code currently prints a success message even when no
rows were comparable (variable compared == 0); update the block after computing
compared in compare.py (the code that prints the "parse benchmark compare
passed" message) to detect compared == 0 and fail closed: write a clear error
message indicating "no comparable benchmark rows" and exit with a non-zero
status (e.g., call sys.exit(1) or raise SystemExit(1)) instead of reporting
success; keep the existing success/threshold print for compared > 0.
- Around line 20-23: The current load_results function uses a dict comprehension
that overwrites duplicate keys; update load_results to iterate over
data["results"] and for each result compute the key with result_key(result),
check if that key already exists in the accumulator dict, and if so raise a
ValueError (or otherwise fail fast) listing the duplicate (language, fixture,
runtime) key and the offending entries; otherwise insert the entry. This ensures
duplicate (language, fixture, runtime) rows are rejected instead of silently
overwritten.

---

Nitpick comments:
In @.github/workflows/parse-bench.yml:
- Around line 1-10: The workflow currently lacks an explicit permissions block
which may grant broader-than-needed access; add a top-level permissions key (for
example permissions: contents: read) to the workflow YAML (near the existing
name: Parse Benchmark / on: pull_request entries) to declare least-privilege
access for this workflow and ensure the parse-bench job runs with only the
necessary permissions.

In `@tools/parse-bench/fixtures/manifest.json`:
- Around line 6-56: Replace mutable branch-head URLs in the "source" fields with
commit-pinned blob URLs in tools/parse-bench/fixtures/manifest.json: for each
entry (e.g., paths kotlin/kotlinx-coroutines-flow.kt,
kotlin/ktor-android-client.kt, kotlin/compose-window.kt,
csharp/dotnet-runtime-boolean.cs, csharp/roslyn-syntax-kind.cs,
csharp/newtonsoft-jsonconvert.cs, csharp/dotnet-samples-teleprompter.cs) find
the current canonical commit SHA on the upstream repo and update the "source"
value from a branch URL (…/blob/main or …/blob/master/...) to the
commit-specific form …/blob/<commit-sha>/<file-path>; ensure every "source" key
in the manifest is replaced so provenance is stable.
🪄 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

Run ID: 59770980-6c1f-46c0-9d47-10e9ad833ba5

📥 Commits

Reviewing files that changed from the base of the PR and between a8f5c7c and 0e4975f.

📒 Files selected for processing (15)
  • .github/workflows/parse-bench.yml
  • .gitignore
  • tools/parse-bench/README.md
  • tools/parse-bench/compare.py
  • tools/parse-bench/fixtures/csharp/dotnet-runtime-boolean.cs
  • tools/parse-bench/fixtures/csharp/dotnet-samples-teleprompter.cs
  • tools/parse-bench/fixtures/csharp/newtonsoft-jsonconvert.cs
  • tools/parse-bench/fixtures/csharp/roslyn-syntax-kind.cs
  • tools/parse-bench/fixtures/kotlin/compose-window.kt
  • tools/parse-bench/fixtures/kotlin/jetbrains-kotlin-collections.kt
  • tools/parse-bench/fixtures/kotlin/kotlinx-coroutines-flow.kt
  • tools/parse-bench/fixtures/kotlin/ktor-android-client.kt
  • tools/parse-bench/fixtures/manifest.json
  • tools/parse-bench/requirements.txt
  • tools/parse-bench/run.py

Comment thread .github/workflows/parse-bench.yml
Comment thread .github/workflows/parse-bench.yml Outdated
Comment thread tools/parse-bench/compare.py
Comment thread tools/parse-bench/compare.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 75636aa5d8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +56 to +57
- name: Install Python benchmark dependencies
run: python -m pip install -r head/tools/parse-bench/requirements.txt

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Install dependencies for the base benchmark checkout

The workflow installs Python packages only from head/tools/parse-bench/requirements.txt and then executes base/tools/parse-bench/run.py; this makes the base run depend on head’s dependency set rather than the base commit’s own requirements. On PRs that add/remove benchmark dependencies, the base step can fail with import errors or run under different package versions, producing spurious failures or invalid baseline comparisons. Install dependencies separately per checkout (or use isolated envs) so each script runs with its own pinned requirements.

Useful? React with 👍 / 👎.

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