Skip to content

feat: add replay/parser performance guardrails - #259

Open
Korupt-virus wants to merge 9 commits into
mainfrom
throughput-benchmarks
Open

feat: add replay/parser performance guardrails#259
Korupt-virus wants to merge 9 commits into
mainfrom
throughput-benchmarks

Conversation

@Korupt-virus

@Korupt-virus Korupt-virus commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add reproducible Mitata guardrails for 20,000-frame raw lap parsing and semantic resolver/canonical envelope transformation
  • preload and decompress deterministic capture input before CPU timing; exclude SQLite and raw file I/O from measured CPU paths
  • add separate isolated replay I/O benchmark for SQLite, file read, gzip, parser/cache, and canonical replay behavior
  • show existing parser/pipeline microbenchmarks as judgment-free informational measurements while retaining median, p99, and allocation deltas for enforced replay/* benchmarks
  • keep initial-landing bootstrap behavior when base lacks either new benchmark

Benchmark boundaries

CPU guardrails

bun run bench runs existing parser/pipeline suite plus:

  • replay/parse 20,000 raw lap frames
  • replay/resolve 20,000 canonical envelopes

Capture file reading and gzip decompression finish before Mitata starts. Both cases use preloaded deterministic inputs, retain 20,000-frame/output assertions, and use Mitata warmup and repeated sampling.

Legacy nanosecond/microsecond parser and pipeline rows remain report-only because shared-runner jitter produces large percentage swings from tiny absolute changes. CI enforcement filters to replay/*, gates median/allocation at 10% and p99 at 25%, and treats missing base replay rows as initial-landing bootstrap. Guardrails begin enforcing after this benchmark exists on base.

Replay I/O

bun run bench:replay-io runs in temporary isolated SQLite state and measures:

  • SQLite + capture identity + cached packets
  • SQLite + file + gzip + parse + canonical replay

I/O results remain report-only with 25% tolerance because filesystem and cache behavior varies more than CPU-only work. Workflow uploads both base/current reports and starts comparison after benchmark lands on base.

Review changes

  • removed custom worker, result schema, comparator, local worktree runner, hard RSS budgets, and platform-sensitive maxRSS conversion
  • moved parser/replay CPU work into shared Mitata harness
  • changed existing comparator to median, p99, and allocation statistics with separate steady-state and tail tolerances
  • added optional benchmark-prefix filtering so enforcement targets only intended guardrails
  • generate and publish comparison reports before enforcement so real regressions retain diagnostics
  • replace each previous benchmark bot comment with a fresh marker-tagged report so current results appear at the bottom
  • split the PR report into informational microbenchmark and replay CPU guardrail tables
  • added comparator coverage for tolerance enforcement, prefix filtering, and initial landing
  • extracted production pure boundaries for preloaded buffer parsing and canonical replay transformation

Verification

  • bun test test/tooling/bench-compare.test.ts test/tooling/changelog.test.ts --timeout 60000 — passed
  • bun test test/games/shared/semantic-replay-native.test.ts test/games/ac-evo/ac-evo-mid-session.test.ts test/session-capture/parse-bin-vs-gz.test.ts --timeout 120000 — 11 passed, 141 assertions
  • bun run bench
    • parser median 64.02 ms, p99 67.89 ms
    • canonical replay median 50.71 ms, p99 54.54 ms
  • bun run bench:replay-io
    • cached replay median 274.73 ms, p99 309.19 ms
    • full I/O replay median 557.90 ms, p99 610.79 ms
  • replayed latest failed CI artifacts with --include=replay/ --threshold=10 --p99-threshold=25 --fail-on-regression — passed bootstrap
  • bun run typecheck — passed
  • bun run lint — 0 warnings, 0 errors

@Snazzie Snazzie left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Request changes: This benchmark should not include SQLite or raw file I/O in its measured path; those make results non-reproducible. Please move the parser and semantic replay work into the existing Mitata harness using preloaded deterministic inputs:

  • raw lap-frame parsing
  • semantic resolver/canonical envelope transformation

Keep frame-count assertions, but replace custom report/comparison logic with Mitata JSON output and the existing benchmark comparator. Also fix or remove custom RSS measurements: current macOS output reports hundreds of GiB because maxRSS is multiplied by 1024 despite already being bytes.

@Snazzie

Snazzie commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Additional issue: the custom worker performs one timed run per scenario with no warmup or repeated samples. Mitata should own warmup/sampling so comparison uses stable statistics (median/p99 and variance/tolerance), rather than a single cold-process measurement.

@Korupt-virus

Copy link
Copy Markdown
Contributor Author

@Snazzie Addressed both benchmark review points in 5cfcaf0b.

  • Raw lap parsing and semantic resolver/canonical envelope transformation now run inside the existing Mitata suite with preloaded deterministic inputs.
  • File read, gzip, and SQLite work finish outside those CPU measurements.
  • 20,000-frame packet/envelope assertions remain.
  • Custom worker, report schema, comparator, hard RSS budgets, and platform-sensitive maxRSS conversion are removed.
  • Mitata now owns warmup and repeated sampling; comparison uses median, p99, allocation, and explicit tolerance instead of one cold-process duration.
  • End-to-end SQLite/file behavior remains available only as a separate isolated, report-only replay I/O benchmark with wider tolerance, so storage noise cannot fail the CPU guardrail.

Local verification passed: CPU benchmark, replay I/O benchmark, comparator tests, 11 parser/replay contract tests, typecheck, lint, and changelog contract.

@github-actions

Copy link
Copy Markdown
Contributor

Informational microbenchmarks

Runtime: bun on AMD EPYC

Report-only. Small timings can vary between runs.

Bench Baseline median / p99 Current median / p99 Baseline alloc / current alloc
ac-evo/parse 2.63 µs / 8.35 µs 2.09 µs / 6.30 µs 437 b / 0 b
ac-evo/pipeline 28.24 µs / 30.73 µs 23.34 µs / 28.91 µs 30.29 kb / 17.92 kb
acc/parse 3.16 µs / 5.20 µs 3.44 µs / 4.78 µs 437 b / 874 b
acc/pipeline 40.80 µs / 64.70 µs 23.79 µs / 28.62 µs 0 b / 16.21 kb
f1/parse 246 ns / 1.67 µs 229 ns / 893 ns 0 b / 0 b
f1/pipeline 84.32 µs / 178.18 µs 77.98 µs / 154.33 µs 68.27 kb / 11.64 kb
fm/parse 1.10 µs / 2.54 µs 1.05 µs / 3.29 µs 0 b / 0 b
fm/pipeline 56.49 µs / 81.09 µs 23.81 µs / 37.17 µs 17.07 kb / 7.68 kb

Replay CPU guardrails

Runtime: bun on AMD EPYC
Thresholds: median/allocation ±10%; p99 ±25%
Included benchmarks: replay/*

Bench Baseline median / p99 Current median / p99 Δ median Δ p99 Δ alloc
replay/parse 20,000 raw lap frames 71.30 ms / 74.64 ms Baseline pending
replay/resolve 20,000 canonical envelopes 48.61 ms / 50.53 ms Baseline pending

Baseline pending. Regression assessment starts after matching results exist on the base branch.

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.

2 participants