Skip to content

Unify benchmark CI suites behind a matrix workflow#3528

Merged
alexeyr-ci2 merged 8 commits into
mainfrom
alexeyr/3459-unify-suites
Jun 2, 2026
Merged

Unify benchmark CI suites behind a matrix workflow#3528
alexeyr-ci2 merged 8 commits into
mainfrom
alexeyr/3459-unify-suites

Conversation

@alexeyr-ci2

@alexeyr-ci2 alexeyr-ci2 commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

First of two PRs splitting the benchmark-workflow work (#3459) to keep review noise down. This one is the CI infrastructure refactor; the regression-reporting feature follows in a stacked PR.

  • Unifies the Core, Pro, and Pro Node Renderer benchmark jobs behind a single matrix generated by benchmarks/generate_matrix.rb — gating, sharding, naming, and Bencher attribution now live in one place instead of duplicated per-suite jobs.
  • Avoids sharding small manual (workflow_dispatch) route sets.
  • Generates the skipped-suite placeholder matrix row from a real suite, so it can't drift from a real row's key shape (no parallel literal to maintain).
  • Hardening / fail-loud: routes matrix.* / github.* values through env: in run: steps; validates BENCHMARK_APP_VERSION and the PR-label JSON (raises instead of silently selecting nothing); makes the same-repo fork check fail closed.
  • Adds a BENCHMARKS_CHANGED category to script/ci-changes-detector (+ bash tests) and a rubocop lint step for benchmarks/ (these scripts live outside the gem, so the package run didn't see them).
  • Adds specs for matrix generation and route discovery.

Measurement note: inlining setup-benchmark-runner drops the nice -n priority prefixes it used alongside taskset. Negative nice values need privileges the current GitHub-hosted runners don't grant (they were failing there), so only taskset CPU-pinning is kept.

The regression-reporting feature (per-suite regression detection, a single serialized report-regressions job, and GitHub issue filing) lands in a follow-up PR stacked on this one.

Pull Request checklist

  • Add/update test to cover these changes
  • Update documentation
  • Update CHANGELOG file (internal CI tooling, not a user-visible change)

Other Information

  • bundle exec rspec benchmarks/spec → 19 examples, 0 failures; bash script/ci-changes-detector-test.bash → 34 tests, 0 failures; rubocop clean (pinned 1.61.0).
  • Carries the benchmark label so CI exercises the new matrix workflow on this PR.

Summary by CodeRabbit

  • Tests

    • Added comprehensive tests for benchmark matrix generation, route-based sharding, event/label gating, and input validation; included lightweight spec helpers for isolated benchmark testing.
  • Chores

    • Reworked benchmark CI to use a unified, dynamic matrix and generic execution flow; removed legacy composite action and shard-count script.
    • CI detector updated to recognize benchmark changes and empty diffs; linting extended to include benchmark scripts.

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8e3dba74-455c-4b7c-8c60-af1b6ce48e30

📥 Commits

Reviewing files that changed from the base of the PR and between fbaf37a and 85cae02.

📒 Files selected for processing (1)
  • .github/workflows/benchmark.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/benchmark.yml

Walkthrough

Generates a unified benchmark matrix (Ruby), drives a single matrix-parameterized benchmark job in the workflow, consolidates toolchain/bootstrap per matrix row, adds RuboCop for benchmarks, updates CI change detection for benchmarks, and adds specs and detector tests.

Changes

Benchmark Workflow Matrix-Driven Refactoring

Layer / File(s) Summary
Matrix generation - core logic
benchmarks/generate_matrix.rb
New Ruby script builds benchmark matrix payloads from suite configuration, event type, PR labels, app-version filters, and optional route-based sharding; emits per-shard rows or a sentinel none row.
Matrix generation - comprehensive specs
benchmarks/spec/spec_helper.rb, benchmarks/spec/benchmark_matrix_spec.rb, benchmarks/spec/benchmark_routes_spec.rb
RSpec tests and stdlib spec helper (BenchmarkEnvHelper) validate event/label gating, fork safety, app-version filtering, sharding/naming, route-based collapse, and input validation.
Benchmark workflow - matrix-driven execution
.github/workflows/benchmark.yml
Runs generate_matrix.rb in detect-changes, uses benchmark_matrix to drive a single parameterized benchmark job; consolidates Bencher/toolchain installs, chooses server kind (node-renderer vs rails), runs benchmark scripts, validates results, uploads artifacts, and reports to Bencher using matrix metadata.
Lint integration
.github/workflows/lint-js-and-ruby.yml
Adds a bundle exec rubocop benchmarks step (with BUNDLE_GEMFILE=react_on_rails/Gemfile) to lint benchmark scripts in CI.
CI changes detection and flags
script/ci-changes-detector
Detects benchmarks/* changes, sets BENCHMARKS_CHANGED, ignores blank file entries, updates non_runtime_only logic, and exports benchmarks_changed for workflow gating and lint selection.
Change detection - benchmark coverage
script/ci-changes-detector-test.bash
Adds benchmark fixture and tests asserting benchmark-source changes enable lint and set benchmarks_changed, comment-only changes are non-runtime-only but still linted, and empty diffs behave as allowed-with-skip.
Minor path and cleanup updates
benchmarks/spec/benchmark_routes_spec.rb, .github/workflows/benchmark.yml
Adjusts require paths and minor workflow comment updates; removes an older per-shard helper script in favor of unified generate_matrix.rb (file removal observed).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • AbanoubGhadban
  • justin808

Poem

🐰 I hopped through matrices, rows in tow,

Replaced the fixed with rows that grow;
Routes now shard, tests keep score,
Lint checks hops where code will soar,
CI gardens bloom—benchmarks glow!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% 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 'Unify benchmark CI suites behind a matrix workflow' directly matches the main objective: refactoring benchmark CI to use a unified matrix workflow.
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 alexeyr/3459-unify-suites

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.

@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: 9759d01e4b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread .github/workflows/benchmark.yml Outdated
BENCHMARK_ROUTES: ${{ github.event.inputs.routes || '' }}
BENCHMARK_NON_RUNTIME_ONLY: ${{ steps.detect.outputs.non_runtime_only }}
BENCHMARK_PULL_REQUEST_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name || '' }}
BENCHMARK_PULL_REQUEST_LABELS: ${{ toJSON(github.event.pull_request.labels.*.name) }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Default missing PR labels before matrix generation

On push and workflow_dispatch events there is no github.event.pull_request, so this expression can pass null as BENCHMARK_PULL_REQUEST_LABELS; generate_matrix.rb always calls pull_request_labels and rejects anything other than a JSON array, which makes detect-changes fail before it emits benchmark_matrix and prevents main/manual benchmark runs from starting. Please default the value to [] here or teach the script to treat JSON null as no labels.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 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/benchmark.yml:
- Around line 181-185: Replace tag-only action pins with immutable commit SHAs
for all third-party actions mentioned: ruby/setup-ruby@v1, actions/checkout@v6,
bencherdev/bencher@v0.6.2, grafana/setup-k6-action@v1, actions/cache@v5,
pnpm/action-setup@v6, actions/setup-node@v6, and actions/upload-artifact@v7; for
each uses: entry in the workflow file, look up the corresponding official action
repository, find a recent stable commit SHA and replace the tag (e.g. *`@v1`* or
*`@v6`*) with the full commit SHA (e.g. *@<commit-sha>*), keeping any existing
with: inputs unchanged, and verify the workflow syntax and run the workflow to
ensure the pinned SHAs are valid.

In `@benchmarks/generate_matrix.rb`:
- Around line 105-111: The early return using
truthy_env?(suite.fetch(:run_output)) can bypass the
pull_request_from_same_repository? guard for event_name == "pull_request";
change the logic so RUN_*_BENCHMARKS envs cannot short-circuit the PR same-repo
check: either move the truthy_env? check after the pull_request branch or make
it conditional (e.g., only return true for truthy_env?(...) when event_name !=
"pull_request" OR when pull_request_from_same_repository? is true); update the
block that uses event_name, truthy_env?(...),
pull_request_from_same_repository?, and suite.fetch(:labels) accordingly so fork
PRs cannot skip the same-repo gate.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 09783f5f-ad50-48d6-bc57-88dbbd1ed3aa

📥 Commits

Reviewing files that changed from the base of the PR and between d6f907c and 9759d01.

📒 Files selected for processing (10)
  • .github/actions/setup-benchmark-runner/action.yml
  • .github/workflows/benchmark.yml
  • .github/workflows/lint-js-and-ruby.yml
  • benchmarks/count_benchmark_shards.rb
  • benchmarks/generate_matrix.rb
  • benchmarks/spec/benchmark_matrix_spec.rb
  • benchmarks/spec/benchmark_routes_spec.rb
  • benchmarks/spec/spec_helper.rb
  • script/ci-changes-detector
  • script/ci-changes-detector-test.bash
💤 Files with no reviewable changes (2)
  • benchmarks/count_benchmark_shards.rb
  • .github/actions/setup-benchmark-runner/action.yml

Comment on lines +181 to +185
- name: Setup Ruby
if: steps.benchmark-matrices.outputs.run_benchmark_suites == 'true' || steps.detect.outputs.benchmarks_changed == 'true'
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ env.RUBY_VERSION }}

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/benchmark.yml"
echo "== File: $FILE =="
test -f "$FILE"
echo

echo "== Showing lines ~160-210 =="
nl -ba "$FILE" | sed -n '150,220p'

echo
echo "== Showing lines ~220-320 =="
nl -ba "$FILE" | sed -n '220,330p'

echo
echo "== Showing lines ~450-520 =="
nl -ba "$FILE" | sed -n '450,520p'

echo
echo "== Enumerating all uses: entries (with their line numbers) =="
rg -n "^\s*uses:\s*" "$FILE"

Repository: shakacode/react_on_rails

Length of output: 204


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/benchmark.yml"
echo "== File: $FILE =="
test -f "$FILE"
echo

echo "== Lines 150-220 =="
cat -n "$FILE" | sed -n '150,220p'

echo
echo "== Lines 220-340 =="
cat -n "$FILE" | sed -n '220,340p'

echo
echo "== Lines 450-520 =="
cat -n "$FILE" | sed -n '450,520p'

echo
echo "== Enumerating all 'uses:' entries (line numbers) =="
# Print: <line_no>: uses: <value>
rg -n '^\s*uses:\s*' "$FILE" || true

Repository: shakacode/react_on_rails

Length of output: 13525


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/benchmark.yml"

echo "== Lines 330-390 =="
cat -n "$FILE" | sed -n '330,390p'

Repository: shakacode/react_on_rails

Length of output: 2681


Pin third-party GitHub Actions to commit SHAs (no tag-only uses:).
In .github/workflows/benchmark.yml, the following uses: entries are currently tag-pinned and should be switched to full commit SHAs: ruby/setup-ruby@v1, actions/checkout@v6, bencherdev/bencher@v0.6.2, grafana/setup-k6-action@v1, actions/cache@v5, pnpm/action-setup@v6, actions/setup-node@v6, actions/upload-artifact@v7 (applies to the corresponding uses: lines around 183, 232, 241, 255, 262, 276, 286, 296, 303, and 484).

🧰 Tools
🪛 zizmor (1.25.2)

[error] 183-183: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 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/benchmark.yml around lines 181 - 185, Replace tag-only
action pins with immutable commit SHAs for all third-party actions mentioned:
ruby/setup-ruby@v1, actions/checkout@v6, bencherdev/bencher@v0.6.2,
grafana/setup-k6-action@v1, actions/cache@v5, pnpm/action-setup@v6,
actions/setup-node@v6, and actions/upload-artifact@v7; for each uses: entry in
the workflow file, look up the corresponding official action repository, find a
recent stable commit SHA and replace the tag (e.g. *`@v1`* or *`@v6`*) with the full
commit SHA (e.g. *@<commit-sha>*), keeping any existing with: inputs unchanged,
and verify the workflow syntax and run the workflow to ensure the pinned SHAs
are valid.

Comment thread benchmarks/generate_matrix.rb Outdated
@greptile-apps

greptile-apps Bot commented Jun 1, 2026

Copy link
Copy Markdown

Greptile Summary

This PR unifies the three benchmark CI jobs (Core, Pro, Pro Node Renderer) behind a single matrix-driven benchmark job generated by benchmarks/generate_matrix.rb, moving all gating/sharding/naming logic into one place. It also adds a BENCHMARKS_CHANGED category to the change detector, rubocop coverage for the benchmarks/ directory, and spec coverage for the new matrix generator.

  • generate_matrix.rb — new single source of truth for benchmark suite definitions; handles event gating, label filtering, explicit-route sharding, and placeholder rows for skipped runs.
  • benchmark.yml — three job definitions replaced with one matrix job; detect-changes now emits a unified benchmark_matrix output; early-exit-on-empty-diff bug in ci-changes-detector corrected.
  • benchmarks/spec/ — 19 new examples covering matrix generation (event gating, app_version filtering, sharding, naming, validation) and the existing route-discovery spec relocated here.

Confidence Score: 3/5

The matrix script can crash on push-to-main if GitHub Actions serializes absent PR labels as null rather than an empty array, breaking every benchmark run on main.

The pull_request_labels function raises an unhandled RuntimeError for non-Array JSON, which toJSON may produce on push and workflow_dispatch events where there is no associated PR. Because build_matrix calls pull_request_labels unconditionally before any event-type check, this aborts the detect-changes job on every push to main. The spec suite never tests with BENCHMARK_PULL_REQUEST_LABELS explicitly set to a non-array value.

benchmarks/generate_matrix.rb (pull_request_labels) and benchmarks/spec/benchmark_matrix_spec.rb (missing push/workflow_dispatch coverage with explicit env var)

Important Files Changed

Filename Overview
.github/workflows/benchmark.yml Core refactor: three separate jobs merged into one matrix-driven benchmark job; detect-changes emits a unified benchmark_matrix; injection hardening applied to most matrix values but inconsistently in two steps.
benchmarks/generate_matrix.rb New matrix generator: pull_request_labels raises RuntimeError for non-array JSON (e.g. null) which toJSON may produce on push/workflow_dispatch events; spec tests don't cover the case where the env var is explicitly set to a non-array value.
benchmarks/spec/benchmark_matrix_spec.rb Solid spec coverage for gating, sharding, naming, and validation; push/workflow_dispatch tests omit BENCHMARK_PULL_REQUEST_LABELS, missing the GHA non-array JSON case.
script/ci-changes-detector Added BENCHMARKS_CHANGED category; fixed early-exit bug when CHANGED_FILES is empty; blank-line guard added to the file-classification loop.
script/ci-changes-detector-test.bash New tests for BENCHMARKS_CHANGED flag, comment-only benchmark change, and empty-diff edge case; correctly validates the ci-changes-detector fix.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Push / PR / workflow_dispatch] --> B[detect-changes job]
    B --> C[ci-changes-detector script]
    C --> D{non_runtime_only?}
    D -- yes --> E[generate_matrix.rb returns empty placeholder row]
    D -- no --> F[generate_matrix.rb evaluates SUITES vs event/labels/app_version]
    F --> G{Any suite enabled?}
    G -- no --> E
    G -- yes --> H[Expand each enabled suite into shard rows]
    E --> I[run_benchmark_suites = false]
    H --> J[run_benchmark_suites = true]
    I --> K[benchmark job SKIPPED]
    J --> L[benchmark job matrix: Core / Pro shards / Pro Node Renderer]
    L --> M[Install tools per matrix.benchmark_tool]
    M --> N{matrix.server_kind}
    N -- rails --> O[Start Rails server]
    N -- node-renderer --> P[Pre-seed cache + Start node renderer]
    O --> Q[Execute benchmark suite]
    P --> Q
    Q --> R[Validate / Upload / Track with Bencher]
Loading

Comments Outside Diff (2)

  1. benchmarks/spec/benchmark_matrix_spec.rb, line 1242-1247 (link)

    P2 Spec gap: push/workflow_dispatch events tested without the explicit env var

    The push and workflow_dispatch tests omit BENCHMARK_PULL_REQUEST_LABELS entirely, so they exercise the ENV.fetch(..., "[]") default — but the workflow always sets this key explicitly via toJSON(...). A case worth adding is "BENCHMARK_PULL_REQUEST_LABELS" => "null" (what GHA can produce when there is no associated PR). This would catch the RuntimeError in pull_request_labels that the current spec passes silently.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

  2. .github/workflows/benchmark.yml, line 460-476 (link)

    P2 Inconsistent env routing in Validate benchmark results

    This step directly interpolates ${{ matrix.summary_file }} in a [ ! -f ... ] test and in column -t -s $'\t' "${{ matrix.summary_file }}", while neighbouring steps (Execute benchmark suite, Benchmark workflow summary) explicitly route matrix values through env: to prevent shell injection. matrix.summary_file comes from the repository's own static SUITES constant so the practical risk is low, but the inconsistency undermines the stated hardening goal. ${{ matrix.summary_title }} in the same step has the same issue at the echo level.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Reviews (1): Last reviewed commit: "Generate the skipped benchmark matrix ro..." | Re-trigger Greptile

Comment on lines +86 to +92
parsed = JSON.parse(raw_labels)
raise "BENCHMARK_PULL_REQUEST_LABELS must be a JSON array (got #{parsed.class})" unless parsed.is_a?(Array)

parsed
rescue JSON::ParserError => e
raise "BENCHMARK_PULL_REQUEST_LABELS must be JSON array: #{e.message}"
end

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 pull_request_labels raises a RuntimeError when BENCHMARK_PULL_REQUEST_LABELS is valid JSON but not an Array. On push and workflow_dispatch events, github.event.pull_request is absent, so toJSON(github.event.pull_request.labels.*.name) can evaluate to "null"JSON.parse("null") returns nil, which fails the is_a?(Array) guard and crashes the matrix script before any event-gating check runs. The spec tests don't exercise this path because they omit the key entirely (relying on the ENV.fetch default of "[]"), but the workflow always sets it explicitly. Returning [] for non-array JSON is the safe fallback here, since labels is only consulted for pull_request events anyway.

Suggested change
parsed = JSON.parse(raw_labels)
raise "BENCHMARK_PULL_REQUEST_LABELS must be a JSON array (got #{parsed.class})" unless parsed.is_a?(Array)
parsed
rescue JSON::ParserError => e
raise "BENCHMARK_PULL_REQUEST_LABELS must be JSON array: #{e.message}"
end
parsed = JSON.parse(raw_labels)
# On push/workflow_dispatch, toJSON(github.event.pull_request.labels.*.name) can
# produce "null" (no associated PR). Treat any non-Array as an empty label set
# rather than crashing — labels are only consulted for pull_request events anyway.
return [] unless parsed.is_a?(Array)
parsed
rescue JSON::ParserError => e
raise "BENCHMARK_PULL_REQUEST_LABELS must be JSON array: #{e.message}"
end

@claude

claude Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

PR Review: Unify benchmark CI suites behind a matrix workflow

Overall assessment: Solid refactor that meaningfully reduces duplication and adds proper security hardening. The fork-safety check, injection hardening via env blocks, empty matrix row approach, and new specs are all good engineering. One likely regression needs fixing before this can safely land on main.

Bug: BENCHMARK_PULL_REQUEST_LABELS receives a non-array value on push events (High priority)

When generate_matrix.rb runs on a push or workflow_dispatch event, BENCHMARK_PULL_REQUEST_LABELS receives the literal string "null" rather than "[]". This is because github.event.pull_request is absent for non-PR events, so toJSON(github.event.pull_request.labels.*.name) evaluates as toJSON(null), producing the 4-character string null.

The pull_request_labels guard return [] if raw_labels.empty? does not catch this string, and JSON.parse("null") returns Ruby nil (not an Array), so the function raises:

BENCHMARK_PULL_REQUEST_LABELS must be a JSON array (got NilClass)

This would break every post-merge benchmark run on main.

The specs do not catch it because with_env deletes the key (triggering the ENV.fetch default of "[]"), while in production the key is always explicitly set by the workflow.

Fix options:

  1. Ruby side: add || raw_labels == "null" to the empty guard in pull_request_labels
  2. Workflow side: conditionally emit label JSON only for PR events and fall back to an empty array otherwise
  3. Add a spec that exercises BENCHMARK_PULL_REQUEST_LABELS set to the string "null" to pin this path

Minor issues

Inconsistent injection hardening in "Validate benchmark results": matrix.summary_file and matrix.summary_title are interpolated directly into the shell run script in that step, while "Execute benchmark suite" and "Benchmark workflow summary" route their matrix values through env: blocks. Low actual risk (values come from internal code), but inconsistent with the stated hardening goal.

REACT_ON_RAILS_PRO_LICENSE now available to Core benchmarks: Previously scoped only to Pro jobs; the consolidated job exposes it to all matrix rows including Core. GitHub masks secrets in logs so the practical risk is low, but the scope is broader than strictly necessary.

Job name change may affect branch protection rules: benchmark-core, benchmark-pro, and benchmark-pro-node-renderer are replaced by the single benchmark job. Any required status checks referencing the old job IDs by name would need updating before landing.

Positive highlights

  • Fork-safety via pull_request_from_same_repository? is fail-closed: an absent/empty head repo is never treated as same-repo. Good.
  • Empty matrix row derived from a real suite row prevents key-shape drift. Clever.
  • Consolidating all gating/sharding/naming into one Ruby script with specs is a real improvement over duplicated per-suite YAML.
  • The BENCHMARKS_CHANGED category is cleanly integrated; removing the early exit 0 on empty diffs is a good catch.
  • runner.arch added to the foreman gem cache key -- was missing before, correct now.
  • Dropping nice -n with a clear explanation is the right call; the measurement note documents the reasoning well.

Comment on lines +82 to +84
def pull_request_labels
raw_labels = ENV.fetch("BENCHMARK_PULL_REQUEST_LABELS", "[]")
return [] if raw_labels.empty?

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.

Bug: "null" is not caught here for non-PR events.

On push and workflow_dispatch events, github.event.pull_request is absent, so toJSON(github.event.pull_request.labels.*.name) evaluates to toJSON(null) = the 4-character string "null". The env var is explicitly set to that string, so ENV.fetch never falls back to the default "[]".

raw_labels.empty? is false for "null", and JSON.parse("null") returns Ruby nil (not an Array), so the raise on line 87 fires:

BENCHMARK_PULL_REQUEST_LABELS must be a JSON array (got NilClass)

The specs don't exercise this path because with_env deletes the key (exposing the default), while in production the key is always set.

Suggested change
def pull_request_labels
raw_labels = ENV.fetch("BENCHMARK_PULL_REQUEST_LABELS", "[]")
return [] if raw_labels.empty?
def pull_request_labels
raw_labels = ENV.fetch("BENCHMARK_PULL_REQUEST_LABELS", "[]")
return [] if raw_labels.empty? || raw_labels == "null"

Comment thread .github/workflows/benchmark.yml Outdated
BENCHMARK_ROUTES: ${{ github.event.inputs.routes || '' }}
BENCHMARK_NON_RUNTIME_ONLY: ${{ steps.detect.outputs.non_runtime_only }}
BENCHMARK_PULL_REQUEST_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name || '' }}
BENCHMARK_PULL_REQUEST_LABELS: ${{ toJSON(github.event.pull_request.labels.*.name) }}

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.

This is the workflow-side root cause of the "null" bug noted in pull_request_labels. For non-PR events, github.event.pull_request.labels.*.name evaluates to null, and toJSON(null) produces the literal string "null" — not "[]".

One workflow-side fix:

Suggested change
BENCHMARK_PULL_REQUEST_LABELS: ${{ toJSON(github.event.pull_request.labels.*.name) }}
BENCHMARK_PULL_REQUEST_LABELS: ${{ github.event_name == 'pull_request' && toJSON(github.event.pull_request.labels.*.name) || '[]' }}

Alternatively, add || raw_labels == "null" in the Ruby pull_request_labels function (suggested there). Either fix is sufficient; doing both is belt-and-suspenders.

Comment thread .github/workflows/benchmark.yml Outdated
Comment on lines +465 to +470
if [ ! -f "${{ matrix.summary_file }}" ]; then
echo "❌ ERROR: benchmark summary file not found"
exit 1
fi
echo "📊 Node Renderer Benchmark Summary:"
column -t -s $'\t' "bench_results/node_renderer_summary.txt"
echo "📊 ${{ matrix.summary_title }}:"
column -t -s $'\t' "${{ matrix.summary_file }}"

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.

This step injects matrix.summary_file and matrix.summary_title directly into the shell script, inconsistent with the injection hardening applied in the adjacent "Execute benchmark suite" and "Benchmark workflow summary" steps. The actual risk is low (values originate from internal generate_matrix.rb code), but it undermines the explicit rationale stated in those other steps' comments.

Consider routing through env: for consistency:

Suggested change
if [ ! -f "${{ matrix.summary_file }}" ]; then
echo "❌ ERROR: benchmark summary file not found"
exit 1
fi
echo "📊 Node Renderer Benchmark Summary:"
column -t -s $'\t' "bench_results/node_renderer_summary.txt"
echo "📊 ${{ matrix.summary_title }}:"
column -t -s $'\t' "${{ matrix.summary_file }}"
- name: Validate benchmark results
env:
SUMMARY_FILE: ${{ matrix.summary_file }}
SUMMARY_TITLE: ${{ matrix.summary_title }}
SUITE_NAME: ${{ matrix.suite_name }}
run: |
set -e
echo "🔍 Validating $SUITE_NAME benchmark results..."
if [ ! -f "$SUMMARY_FILE" ]; then
echo "❌ ERROR: benchmark summary file not found"
exit 1
fi
echo "📊 $SUMMARY_TITLE:"
column -t -s $'\t' "$SUMMARY_FILE"

alexeyr and others added 7 commits June 2, 2026 14:55
- Remove the unused run_*_benchmarks detect-changes outputs; after the matrix
  unification no downstream job consumes them (only step-local env does).
- Route matrix/context values through env: in the Execute and Summary steps so
  the shell treats them as data, not code (GitHub Actions injection hardening).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Build the no-suite-selected placeholder via suite_row (overriding only
suite_id and a friendly job_name) instead of hand-maintaining a parallel
EMPTY_MATRIX_ROW literal. This guarantees the placeholder shares a real
row's exact key set (the matrix include: requires it, and the workflow
reads matrix.<field> on the skipped path too) and emits the same string
pro_env/generate_packs values real rows produce.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@alexeyr-ci2 alexeyr-ci2 force-pushed the alexeyr/3459-unify-suites branch from 9759d01 to fbaf37a Compare June 2, 2026 12:02
@claude

claude Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Code Review — PR #3528: Unify benchmark CI suites behind a matrix workflow

Overall: This is a well-engineered refactor. Centralizing three parallel jobs into a single Ruby-driven matrix eliminates significant duplication, and the injection-hardening (env: routing for matrix/context values in run: steps), fail-loud validation, and fork-PR gating are all good defensive practice. The test coverage for generate_matrix.rb is thorough and env-isolation in BenchmarkEnvHelper is solid. A few minor issues below.


Issues

1. pull_request_labels silently drops non-array valid JSON (benchmarks/generate_matrix.rb:87)

parsed = JSON.parse(raw_labels)
parsed.is_a?(Array) ? parsed : []   # ← silent fallback

If BENCHMARK_PULL_REQUEST_LABELS is valid JSON but not an array (e.g. "true", null, or {}), this returns [] without raising. The PR description frames this as "raises instead of silently selecting nothing", but that only holds for malformed JSON. A non-array value would cause benchmark suites to be silently skipped. Either raise here (consistent with the stated design), or add a # comment acknowledging the silent fallback is intentional. The spec has no test for this path.


2. Vegeta download URL hardcodes linux_amd64 while cache key is arch-aware (.github/workflows/benchmark.yml:271)

key: vegeta-${{ runner.os }}-${{ runner.arch }}-${{ env.VEGETA_VERSION }}
# ...
wget -q ".../vegeta_${VEGETA_VERSION}_linux_amd64.tar.gz"

The cache key is architecture-parameterized (good forward-compatibility thinking), but the download URL is locked to linux_amd64. If GitHub ever provisions arm64 runners for this workflow, the cache will miss on every run but keep downloading the wrong binary anyway. Either remove ${{ runner.arch }} from the cache key (since the binary is always amd64), or make the URL dynamic so the two stay in sync.


3. pull_request_labels is called before the BENCHMARK_NON_RUNTIME_ONLY early-out (benchmarks/generate_matrix.rb:208-214)

def build_matrix
  labels = pull_request_labels          # ← can raise for malformed JSON
  rows = if truthy_env?("BENCHMARK_NON_RUNTIME_ONLY")
           []                           # ← early-out, but labels already fetched

If BENCHMARK_NON_RUNTIME_ONLY=true and BENCHMARK_PULL_REQUEST_LABELS happens to be malformed, build_matrix raises instead of emitting the skipped-placeholder row. Moving the BENCHMARK_NON_RUNTIME_ONLY check before pull_request_labels would match the fail-loud intent (labels are irrelevant in that branch) and give a cleaner empty-matrix path.


4. Set benchmark outputs step still uses inline expressions (.github/workflows/benchmark.yml:121-136)

The benchmark-matrices step carefully routes all context values through env: to prevent injection. The earlier benchmark-outputs step (which feeds into benchmark-matrices via steps.benchmark-outputs.outputs.*) still interpolates ${{ steps.detect.outputs.* }} values directly inside the run: shell. Those values come from ci-changes-detector (trusted), so this is not a practical security risk, but it's inconsistent with the hardening posture applied elsewhere in the same job.


Nits

  • suite_rows({ id: "fake", shard_total: 0 }) in the validation spec uses a bare hash with positional fetch calls that will KeyError on missing keys before reaching the shard validation — consider making the fake suite a complete stub or using fetch with a default in shard_total_for_suite for keys the test omits.
  • The "Start Pro node renderer" step now also handles bundle-cache pre-seeding; the step name could reflect both responsibilities (e.g. "Pre-seed cache and start Pro node renderer").

Summary

No blockers. Issues 1 and 2 are the most worth fixing before merge; 3 and 4 are low-priority. The architecture is solid and the test coverage is a genuine improvement.

return [] if raw_labels.empty?

parsed = JSON.parse(raw_labels)
parsed.is_a?(Array) ? parsed : []

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.

Silent fallback inconsistent with the stated "fail loud" goal. If BENCHMARK_PULL_REQUEST_LABELS is valid JSON but not an array (e.g. "true", null, {}), this returns [] without any error, causing all benchmark suites to be silently skipped. The rescue block below only covers malformed JSON.

Either make this consistent:

Suggested change
parsed.is_a?(Array) ? parsed : []
raise "BENCHMARK_PULL_REQUEST_LABELS must be a JSON array (got #{parsed.class})" unless parsed.is_a?(Array)
parsed

Or add a comment making the intentional silent-fallback explicit, and add a spec for it.

suite_rows(SUITES.first).first.merge(suite_id: "none", job_name: "Benchmark suites skipped")
end

def build_matrix

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.

pull_request_labels can raise (malformed JSON) before the BENCHMARK_NON_RUNTIME_ONLY early-out is reached. Since labels are irrelevant when that flag is set, consider checking it first:

Suggested change
def build_matrix
def build_matrix
rows = if truthy_env?("BENCHMARK_NON_RUNTIME_ONLY")
[]
else
labels = pull_request_labels
SUITES.select { |suite| suite_enabled?(suite, labels) }.flat_map { |suite| suite_rows(suite) }
end

This avoids a noisy JSON-parse failure on the non-runtime-only path and aligns with the intent of the guard.

with:
persist-credentials: false
path: ~/bin/vegeta
key: vegeta-${{ runner.os }}-${{ runner.arch }}-${{ env.VEGETA_VERSION }}

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.

Cache key is architecture-parameterized (runner.arch) but the download URL on line 271 is hardcoded to linux_amd64. These need to stay in sync — if arm64 runners are ever used the cache will miss every run and keep fetching the wrong binary.

Either drop ${{ runner.arch }} from the key (the binary is always amd64), or make the URL dynamic:

ARCH=$(dpkg --print-architecture)  # amd64 / arm64
wget -q ".../vegeta_${VEGETA_VERSION}_linux_${ARCH}.tar.gz"

@alexeyr-ci2 alexeyr-ci2 merged commit d8327e8 into main Jun 2, 2026
45 of 46 checks passed
@alexeyr-ci2 alexeyr-ci2 deleted the alexeyr/3459-unify-suites branch June 2, 2026 12:29
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchalexeyr/3459-unify-suites
Testbedgithub-actions
Click to view all benchmark results
Benchmarkfailed_pct%p50_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
p90_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
p99_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
rpsBenchmark Result
req/s
(Result Δ%)
Lower Boundary
req/s
(Limit %)
Pro Node Renderer: react_ssr (non-RSC)📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
4.77
(-12.33%)Baseline: 5.44
6.88
(69.37%)
📈 view plot
🚷 view threshold
6.16
(-40.79%)Baseline: 10.40
17.41
(35.39%)
📈 view plot
🚷 view threshold
9.54
(-41.00%)Baseline: 16.17
26.71
(35.71%)
📈 view plot
🚷 view threshold
1,886.10
(+21.04%)Baseline: 1,558.24
978.47
(51.88%)
Pro Node Renderer: simple_eval (non-RSC)📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
4.12
(-14.60%)Baseline: 4.82
6.32
(65.19%)
📈 view plot
🚷 view threshold
5.22
(-51.84%)Baseline: 10.84
19.19
(27.21%)
📈 view plot
🚷 view threshold
8.27
(-48.99%)Baseline: 16.21
27.84
(29.70%)
📈 view plot
🚷 view threshold
2,190.03
(+32.17%)Baseline: 1,657.01
915.97
(41.82%)
🐰 View full continuous benchmarking report in Bencher

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchalexeyr/3459-unify-suites
Testbedgithub-actions

🚨 5 Alerts

BenchmarkMeasure
Units
ViewBenchmark Result
(Result Δ%)
Lower Boundary
(Limit %)
Upper Boundary
(Limit %)
/pure_component: Corerps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
18.77
(-21.10%)Baseline: 23.79
19.29
(102.77%)

/pure_component: Corep90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
488.38
(+22.87%)Baseline: 397.49
454.41
(107.48%)

/server_side_hello_world_shared_store: Corep90_latency
ms x 1e3
📈 plot
🚷 threshold
🚨 alert (🔔)
1.07 x 1e3
(+25.44%)Baseline: 0.85 x 1e3
1.00 x 1e3
(106.50%)

/server_side_log_throw: Corep99_latency
ms x 1e3
📈 plot
🚷 threshold
🚨 alert (🔔)
7.31 x 1e3
(+77.82%)Baseline: 4.11 x 1e3
5.75 x 1e3
(126.97%)

/turbo_frame_tag_hello_world: Corep99_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
209.67
(+68.02%)Baseline: 124.79
206.10
(101.73%)

Click to view all benchmark results
Benchmarkfailed_pct%p50_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
p90_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
p99_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
rpsBenchmark Result
req/s
(Result Δ%)
Lower Boundary
req/s
(Limit %)
/: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
2,913.60
(+5.91%)Baseline: 2,751.14
3,394.94
(85.82%)
📈 view plot
🚷 view threshold
3,747.16
(+3.69%)Baseline: 3,613.93
4,372.00
(85.71%)
📈 view plot
🚷 view threshold
32,912.45
(+13.04%)Baseline: 29,116.81
43,754.43
(75.22%)
📈 view plot
🚷 view threshold
2.80
(+3.39%)Baseline: 2.71
2.33
(83.05%)
/broken_app: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
350.33
(+6.54%)Baseline: 328.83
396.81
(88.29%)
📈 view plot
🚷 view threshold
406.68
(+1.81%)Baseline: 399.45
460.80
(88.26%)
📈 view plot
🚷 view threshold
3,878.87
(-2.87%)Baseline: 3,993.59
5,475.46
(70.84%)
📈 view plot
🚷 view threshold
24.07
(+3.90%)Baseline: 23.17
19.11
(79.40%)
/client_side_hello_world: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
7.96
(-15.27%)Baseline: 9.39
12.52
(63.56%)
📈 view plot
🚷 view threshold
19.63
(-18.98%)Baseline: 24.23
40.56
(48.40%)
📈 view plot
🚷 view threshold
82.83
(-47.68%)Baseline: 158.31
232.78
(35.58%)
📈 view plot
🚷 view threshold
790.77
(+28.38%)Baseline: 615.94
429.58
(54.32%)
/client_side_hello_world_shared_store: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
10.85
(+5.83%)Baseline: 10.25
13.43
(80.78%)
📈 view plot
🚷 view threshold
19.16
(-23.17%)Baseline: 24.94
39.38
(48.65%)
📈 view plot
🚷 view threshold
77.83
(-53.72%)Baseline: 168.16
255.74
(30.43%)
📈 view plot
🚷 view threshold
722.88
(+26.10%)Baseline: 573.27
395.96
(54.78%)
/client_side_hello_world_shared_store_controller: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
11.54
(+14.05%)Baseline: 10.12
13.05
(88.42%)
📈 view plot
🚷 view threshold
15.82
(-38.22%)Baseline: 25.61
38.92
(40.65%)
📈 view plot
🚷 view threshold
131.16
(-17.47%)Baseline: 158.92
250.26
(52.41%)
📈 view plot
🚷 view threshold
497.18
(-14.40%)Baseline: 580.79
414.55
(83.38%)
/client_side_hello_world_shared_store_defer: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
8.38
(-19.58%)Baseline: 10.42
13.66
(61.35%)
📈 view plot
🚷 view threshold
21.05
(-15.42%)Baseline: 24.89
39.09
(53.85%)
📈 view plot
🚷 view threshold
118.93
(-23.99%)Baseline: 156.46
239.61
(49.63%)
📈 view plot
🚷 view threshold
711.53
(+22.48%)Baseline: 580.96
405.65
(57.01%)
/client_side_log_throw: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
8.41
(-9.48%)Baseline: 9.29
12.31
(68.32%)
📈 view plot
🚷 view threshold
17.34
(-17.28%)Baseline: 20.96
31.64
(54.80%)
📈 view plot
🚷 view threshold
140.77
(-11.46%)Baseline: 159.00
248.20
(56.72%)
📈 view plot
🚷 view threshold
744.38
(+16.34%)Baseline: 639.81
441.78
(59.35%)
/client_side_manual_render: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
8.08
(-19.37%)Baseline: 10.02
12.86
(62.83%)
📈 view plot
🚷 view threshold
19.70
(-0.16%)Baseline: 19.73
27.22
(72.37%)
📈 view plot
🚷 view threshold
111.58
(-25.61%)Baseline: 149.98
250.78
(44.49%)
📈 view plot
🚷 view threshold
750.81
(+22.98%)Baseline: 610.54
423.77
(56.44%)
/client_side_rescript_hello_world: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
8.10
(-14.70%)Baseline: 9.50
12.91
(62.73%)
📈 view plot
🚷 view threshold
19.57
(-16.23%)Baseline: 23.36
38.85
(50.37%)
📈 view plot
🚷 view threshold
81.15
(-50.92%)Baseline: 165.36
257.82
(31.48%)
📈 view plot
🚷 view threshold
792.74
(+30.72%)Baseline: 606.45
410.15
(51.74%)
/context_function_return_jsx: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
7.68
(-17.45%)Baseline: 9.30
12.64
(60.76%)
📈 view plot
🚷 view threshold
12.93
(-33.28%)Baseline: 19.38
25.95
(49.82%)
📈 view plot
🚷 view threshold
129.44
(-14.50%)Baseline: 151.39
262.19
(49.37%)
📈 view plot
🚷 view threshold
781.42
(+20.32%)Baseline: 649.44
463.38
(59.30%)
/css_modules_images_fonts_example: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
258.80
(-20.70%)Baseline: 326.37
396.73
(65.23%)
📈 view plot
🚷 view threshold
383.26
(-5.94%)Baseline: 407.47
468.93
(81.73%)
📈 view plot
🚷 view threshold
4,051.35
(+3.40%)Baseline: 3,918.12
5,259.72
(77.03%)
📈 view plot
🚷 view threshold
24.68
(+4.59%)Baseline: 23.60
18.75
(75.98%)
/image_example: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
370.52
(+12.31%)Baseline: 329.90
395.92
(93.58%)
📈 view plot
🚷 view threshold
407.53
(+0.57%)Baseline: 405.23
456.34
(89.30%)
📈 view plot
🚷 view threshold
2,582.15
(-33.71%)Baseline: 3,895.38
5,438.44
(47.48%)
📈 view plot
🚷 view threshold
24.39
(+5.40%)Baseline: 23.14
18.60
(76.28%)
/manual_render_test: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
8.19
(-10.59%)Baseline: 9.16
11.69
(70.07%)
📈 view plot
🚷 view threshold
19.50
(-4.31%)Baseline: 20.38
27.21
(71.65%)
📈 view plot
🚷 view threshold
110.46
(-13.66%)Baseline: 127.94
196.09
(56.33%)
📈 view plot
🚷 view threshold
751.19
(+10.41%)Baseline: 680.38
516.97
(68.82%)
/pure_component: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
327.84
(+1.32%)Baseline: 323.58
396.73
(82.64%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
488.38
(+22.87%)Baseline: 397.49
454.41
(107.48%)

📈 view plot
🚷 view threshold
3,580.41
(-7.83%)Baseline: 3,884.49
5,272.01
(67.91%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
18.77
(-21.10%)Baseline: 23.79
19.29
(102.77%)

/pure_component_wrapped_in_function: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
7.61
(-20.29%)Baseline: 9.55
11.98
(63.52%)
📈 view plot
🚷 view threshold
13.17
(-34.45%)Baseline: 20.09
28.47
(46.26%)
📈 view plot
🚷 view threshold
134.04
(+1.27%)Baseline: 132.35
206.86
(64.80%)
📈 view plot
🚷 view threshold
780.52
(+16.40%)Baseline: 670.55
502.33
(64.36%)
/react_helmet: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
295.92
(-7.69%)Baseline: 320.58
387.99
(76.27%)
📈 view plot
🚷 view threshold
449.05
(+11.96%)Baseline: 401.09
456.26
(98.42%)
📈 view plot
🚷 view threshold
3,216.25
(-16.34%)Baseline: 3,844.41
5,124.17
(62.77%)
📈 view plot
🚷 view threshold
19.76
(-15.40%)Baseline: 23.36
19.26
(97.48%)
/react_helmet_broken: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
274.56
(-18.88%)Baseline: 338.45
420.66
(65.27%)
📈 view plot
🚷 view threshold
406.46
(-2.47%)Baseline: 416.76
459.27
(88.50%)
📈 view plot
🚷 view threshold
4,311.04
(+6.69%)Baseline: 4,040.58
5,431.87
(79.37%)
📈 view plot
🚷 view threshold
23.28
(+2.06%)Baseline: 22.81
19.71
(84.65%)
/react_router: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
356.06
(+2.79%)Baseline: 346.40
415.13
(85.77%)
📈 view plot
🚷 view threshold
414.20
(-1.50%)Baseline: 420.51
472.68
(87.63%)
📈 view plot
🚷 view threshold
4,010.59
(-5.02%)Baseline: 4,222.43
5,715.93
(70.17%)
📈 view plot
🚷 view threshold
23.65
(+7.11%)Baseline: 22.08
17.11
(72.33%)
/render_js: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
325.22
(+4.77%)Baseline: 310.42
386.07
(84.24%)
📈 view plot
🚷 view threshold
369.00
(-3.13%)Baseline: 380.94
430.97
(85.62%)
📈 view plot
🚷 view threshold
3,745.05
(+0.07%)Baseline: 3,742.33
5,386.14
(69.53%)
📈 view plot
🚷 view threshold
26.06
(+5.76%)Baseline: 24.64
19.81
(76.01%)
/rendered_html: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
341.47
(+7.00%)Baseline: 319.14
392.77
(86.94%)
📈 view plot
🚷 view threshold
395.40
(-1.64%)Baseline: 401.99
471.85
(83.80%)
📈 view plot
🚷 view threshold
3,805.32
(-1.41%)Baseline: 3,859.69
5,137.64
(74.07%)
📈 view plot
🚷 view threshold
24.82
(+4.08%)Baseline: 23.85
19.01
(76.61%)
/server_side_hello_world: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
337.57
(+1.66%)Baseline: 332.06
399.28
(84.55%)
📈 view plot
🚷 view threshold
388.61
(-3.23%)Baseline: 401.59
461.04
(84.29%)
📈 view plot
🚷 view threshold
4,000.36
(+3.16%)Baseline: 3,877.79
5,387.92
(74.25%)
📈 view plot
🚷 view threshold
24.77
(+4.96%)Baseline: 23.60
18.45
(74.47%)
/server_side_hello_world_es5: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
341.90
(+2.91%)Baseline: 332.25
390.91
(87.46%)
📈 view plot
🚷 view threshold
392.02
(-2.85%)Baseline: 403.52
461.54
(84.94%)
📈 view plot
🚷 view threshold
3,721.09
(-1.16%)Baseline: 3,764.67
5,042.38
(73.80%)
📈 view plot
🚷 view threshold
24.72
(+5.03%)Baseline: 23.54
18.53
(74.96%)
/server_side_hello_world_hooks: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
246.66
(-25.74%)Baseline: 332.14
399.68
(61.71%)
📈 view plot
🚷 view threshold
379.36
(-5.78%)Baseline: 402.65
453.87
(83.58%)
📈 view plot
🚷 view threshold
4,701.92
(+27.30%)Baseline: 3,693.53
5,091.30
(92.35%)
📈 view plot
🚷 view threshold
24.59
(+3.12%)Baseline: 23.85
19.54
(79.46%)
/server_side_hello_world_props: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
340.40
(+8.39%)Baseline: 314.06
401.77
(84.72%)
📈 view plot
🚷 view threshold
396.80
(-2.54%)Baseline: 407.15
508.16
(78.09%)
📈 view plot
🚷 view threshold
3,533.40
(-15.50%)Baseline: 4,181.69
5,996.89
(58.92%)
📈 view plot
🚷 view threshold
24.88
(+7.67%)Baseline: 23.11
17.92
(72.01%)
/server_side_hello_world_shared_store: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
593.06
(-8.31%)Baseline: 646.82
822.02
(72.15%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
1,066.24
(+25.44%)Baseline: 850.01
1,001.13
(106.50%)

📈 view plot
🚷 view threshold
6,296.78
(-18.20%)Baseline: 7,697.77
11,322.63
(55.61%)
📈 view plot
🚷 view threshold
10.10
(-13.33%)Baseline: 11.65
9.82
(97.23%)
/server_side_hello_world_shared_store_controller: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
482.64
(-26.20%)Baseline: 654.01
795.30
(60.69%)
📈 view plot
🚷 view threshold
842.68
(-0.30%)Baseline: 845.20
1,002.52
(84.06%)
📈 view plot
🚷 view threshold
8,618.31
(+18.09%)Baseline: 7,298.35
10,416.69
(82.74%)
📈 view plot
🚷 view threshold
11.86
(+1.91%)Baseline: 11.64
10.01
(84.36%)
/server_side_hello_world_shared_store_defer: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
702.70
(+7.89%)Baseline: 651.29
774.91
(90.68%)
📈 view plot
🚷 view threshold
936.12
(+10.06%)Baseline: 850.56
999.46
(93.66%)
📈 view plot
🚷 view threshold
7,420.69
(-0.44%)Baseline: 7,453.71
10,065.30
(73.73%)
📈 view plot
🚷 view threshold
12.09
(+4.94%)Baseline: 11.52
9.47
(78.30%)
/server_side_hello_world_with_options: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
341.43
(+5.90%)Baseline: 322.41
386.48
(88.34%)
📈 view plot
🚷 view threshold
396.09
(-0.03%)Baseline: 396.20
449.19
(88.18%)
📈 view plot
🚷 view threshold
3,738.55
(-5.94%)Baseline: 3,974.82
5,526.71
(67.65%)
📈 view plot
🚷 view threshold
24.87
(+3.79%)Baseline: 23.96
19.03
(76.53%)
/server_side_log_throw: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
136.42
(-57.98%)Baseline: 324.62
408.22
(33.42%)
📈 view plot
🚷 view threshold
389.63
(-2.68%)Baseline: 400.34
455.72
(85.50%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
7,305.73
(+77.82%)Baseline: 4,108.48
5,754.00
(126.97%)

📈 view plot
🚷 view threshold
23.70
(+1.46%)Baseline: 23.36
19.92
(84.06%)
/server_side_log_throw_plain_js: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
345.94
(+9.69%)Baseline: 315.38
389.96
(88.71%)
📈 view plot
🚷 view threshold
408.59
(+2.19%)Baseline: 399.84
457.67
(89.28%)
📈 view plot
🚷 view threshold
3,825.03
(-5.11%)Baseline: 4,030.93
5,778.64
(66.19%)
📈 view plot
🚷 view threshold
24.15
(+5.27%)Baseline: 22.94
19.00
(78.66%)
/server_side_log_throw_raise: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
345.84
(+9.75%)Baseline: 315.11
391.45
(88.35%)
📈 view plot
🚷 view threshold
399.65
(-0.47%)Baseline: 401.53
460.77
(86.74%)
📈 view plot
🚷 view threshold
3,946.27
(+1.34%)Baseline: 3,893.98
5,184.44
(76.12%)
📈 view plot
🚷 view threshold
24.32
(+3.83%)Baseline: 23.42
19.59
(80.53%)
/server_side_log_throw_raise_invoker: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
6.71
(-17.12%)Baseline: 8.10
10.42
(64.38%)
📈 view plot
🚷 view threshold
11.63
(-30.18%)Baseline: 16.66
21.78
(53.41%)
📈 view plot
🚷 view threshold
104.26
(-13.89%)Baseline: 121.08
192.78
(54.08%)
📈 view plot
🚷 view threshold
904.94
(+16.68%)Baseline: 775.60
593.55
(65.59%)
/server_side_redux_app: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
356.75
(+7.09%)Baseline: 333.14
404.22
(88.26%)
📈 view plot
🚷 view threshold
407.37
(+0.07%)Baseline: 407.07
466.26
(87.37%)
📈 view plot
🚷 view threshold
4,068.52
(+4.54%)Baseline: 3,891.86
5,288.85
(76.93%)
📈 view plot
🚷 view threshold
23.62
(+3.78%)Baseline: 22.76
19.00
(80.45%)
/server_side_redux_app_cached: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
9.13
(-12.30%)Baseline: 10.41
13.40
(68.15%)
📈 view plot
🚷 view threshold
17.14
(-7.99%)Baseline: 18.63
25.81
(66.41%)
📈 view plot
🚷 view threshold
143.10
(+7.80%)Baseline: 132.75
211.37
(67.70%)
📈 view plot
🚷 view threshold
735.58
(+12.59%)Baseline: 653.33
467.74
(63.59%)
/turbo_frame_tag_hello_world: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
7.71
(-11.34%)Baseline: 8.70
11.32
(68.12%)
📈 view plot
🚷 view threshold
11.24
(-38.13%)Baseline: 18.17
26.72
(42.07%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
209.67
(+68.02%)Baseline: 124.79
206.10
(101.73%)

📈 view plot
🚷 view threshold
577.89
(-20.72%)Baseline: 728.92
529.97
(91.71%)
/turbolinks_cache_disabled: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
8.04
(-13.80%)Baseline: 9.33
12.06
(66.68%)
📈 view plot
🚷 view threshold
19.71
(-2.01%)Baseline: 20.11
29.94
(65.83%)
📈 view plot
🚷 view threshold
109.96
(-24.21%)Baseline: 145.09
232.72
(47.25%)
📈 view plot
🚷 view threshold
750.30
(+14.89%)Baseline: 653.05
447.45
(59.64%)
/xhr_refresh: Core📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
672.99
(+7.22%)Baseline: 627.66
786.54
(85.56%)
📈 view plot
🚷 view threshold
868.66
(+3.37%)Baseline: 840.34
957.09
(90.76%)
📈 view plot
🚷 view threshold
6,425.13
(-14.24%)Baseline: 7,491.99
10,854.94
(59.19%)
📈 view plot
🚷 view threshold
12.72
(+3.56%)Baseline: 12.28
10.46
(82.27%)
🐰 View full continuous benchmarking report in Bencher

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchalexeyr/3459-unify-suites
Testbedgithub-actions

🚨 17 Alerts

BenchmarkMeasure
Units
ViewBenchmark Result
(Result Δ%)
Lower Boundary
(Limit %)
Upper Boundary
(Limit %)
/broken_app: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
269.77
(-24.80%)Baseline: 358.74
275.18
(102.00%)

/cached_react_helmet: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
65.08
(+101.13%)Baseline: 32.36
48.31
(134.72%)

/cached_redux_component: Prop99_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
410.64
(+70.73%)Baseline: 240.53
363.64
(112.92%)

/client_side_manual_render: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
276.53
(-26.84%)Baseline: 378.00
296.72
(107.30%)

/error_scenarios_hub: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
244.29
(-32.47%)Baseline: 361.73
287.82
(117.82%)

/error_scenarios_hub: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
59.29
(+91.00%)Baseline: 31.04
43.03
(137.79%)

/non_existing_react_component: Prop99_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
495.26
(+92.39%)Baseline: 257.43
413.91
(119.65%)

/react_helmet: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
259.12
(-24.97%)Baseline: 345.37
268.75
(103.72%)

/react_helmet: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
46.39
(+42.09%)Baseline: 32.65
43.58
(106.44%)

/react_router: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
272.43
(-30.93%)Baseline: 394.43
280.91
(103.11%)

/react_router: Prop99_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
454.33
(+109.13%)Baseline: 217.25
332.27
(136.73%)

/redis_receiver: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
195.24
(+32.74%)Baseline: 147.08
189.38
(103.09%)

/rendered_html: Prop50_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
26.45
(+31.18%)Baseline: 20.16
25.13
(105.24%)

/server_render_with_timeout: Prop99_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
452.31
(+87.02%)Baseline: 241.86
363.81
(124.32%)

/server_side_hello_world_es5: Prop50_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
28.70
(+38.70%)Baseline: 20.69
26.53
(108.19%)

/ssr_async_error: Prorps
req/s
📈 plot
🚷 threshold
🚨 alert (🔔)
225.25
(-33.33%)Baseline: 337.87
270.06
(119.89%)

/ssr_async_error: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
70.72
(+111.20%)Baseline: 33.48
46.22
(153.00%)

Click to view all benchmark results
Benchmarkfailed_pct%p50_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
p90_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
p99_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
rpsBenchmark Result
req/s
(Result Δ%)
Lower Boundary
req/s
(Limit %)
/: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
50.17
(+23.28%)Baseline: 40.70
54.08
(92.76%)
📈 view plot
🚷 view threshold
74.41
(+19.00%)Baseline: 62.53
76.78
(96.92%)
📈 view plot
🚷 view threshold
601.14
(+17.68%)Baseline: 510.82
792.74
(75.83%)
📈 view plot
🚷 view threshold
161.15
(-12.09%)Baseline: 183.32
149.41
(92.72%)
/async_components_demo: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
42.20
(+18.51%)Baseline: 35.61
46.14
(91.45%)
📈 view plot
🚷 view threshold
60.91
(+16.03%)Baseline: 52.49
65.07
(93.60%)
📈 view plot
🚷 view threshold
454.59
(+3.73%)Baseline: 438.23
653.95
(69.51%)
📈 view plot
🚷 view threshold
192.82
(-6.04%)Baseline: 205.22
156.86
(81.35%)
/async_on_server_sync_on_client: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
24.11
(+9.26%)Baseline: 22.07
27.87
(86.52%)
📈 view plot
🚷 view threshold
38.97
(-3.11%)Baseline: 40.22
59.34
(65.67%)
📈 view plot
🚷 view threshold
270.37
(+5.64%)Baseline: 255.95
353.06
(76.58%)
📈 view plot
🚷 view threshold
318.43
(-2.14%)Baseline: 325.40
246.05
(77.27%)
/async_render_function_returns_string: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
21.07
(+4.95%)Baseline: 20.08
26.07
(80.82%)
📈 view plot
🚷 view threshold
35.52
(+2.25%)Baseline: 34.74
49.93
(71.14%)
📈 view plot
🚷 view threshold
239.15
(-4.57%)Baseline: 250.60
375.91
(63.62%)
📈 view plot
🚷 view threshold
280.43
(-20.65%)Baseline: 353.39
271.53
(96.83%)
/broken_app: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
20.62
(+1.53%)Baseline: 20.31
26.48
(77.87%)
📈 view plot
🚷 view threshold
28.21
(-15.84%)Baseline: 33.52
48.83
(57.77%)
📈 view plot
🚷 view threshold
357.71
(+45.14%)Baseline: 246.46
377.50
(94.76%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
269.77
(-24.80%)Baseline: 358.74
275.18
(102.00%)

/cached_react_helmet: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
18.26
(-5.51%)Baseline: 19.32
24.20
(75.46%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
65.08
(+101.13%)Baseline: 32.36
48.31
(134.72%)

📈 view plot
🚷 view threshold
243.74
(+3.65%)Baseline: 235.16
351.59
(69.33%)
📈 view plot
🚷 view threshold
299.90
(-21.09%)Baseline: 380.05
299.24
(99.78%)
/cached_redux_component: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
14.55
(-21.92%)Baseline: 18.64
23.74
(61.29%)
📈 view plot
🚷 view threshold
28.78
(-7.05%)Baseline: 30.96
42.97
(66.97%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
410.64
(+70.73%)Baseline: 240.53
363.64
(112.92%)

📈 view plot
🚷 view threshold
369.82
(-3.88%)Baseline: 384.74
294.91
(79.74%)
/client_side_hello_world: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
19.93
(+4.38%)Baseline: 19.09
24.43
(81.59%)
📈 view plot
🚷 view threshold
33.85
(+9.87%)Baseline: 30.81
43.53
(77.76%)
📈 view plot
🚷 view threshold
236.99
(+4.85%)Baseline: 226.03
347.50
(68.20%)
📈 view plot
🚷 view threshold
370.96
(-0.96%)Baseline: 374.55
283.42
(76.40%)
/client_side_hello_world_shared_store_controller: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
25.20
(+23.23%)Baseline: 20.45
25.96
(97.07%)
📈 view plot
🚷 view threshold
34.14
(+2.94%)Baseline: 33.16
46.61
(73.24%)
📈 view plot
🚷 view threshold
138.38
(-45.35%)Baseline: 253.19
382.50
(36.18%)
📈 view plot
🚷 view threshold
345.63
(-0.74%)Baseline: 348.20
274.50
(79.42%)
/client_side_manual_render: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
20.67
(+14.54%)Baseline: 18.05
23.51
(87.92%)
📈 view plot
🚷 view threshold
33.71
(+15.95%)Baseline: 29.07
39.35
(85.68%)
📈 view plot
🚷 view threshold
240.37
(-1.86%)Baseline: 244.92
364.02
(66.03%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
276.53
(-26.84%)Baseline: 378.00
296.72
(107.30%)

/css_modules_images_fonts_example: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
26.31
(+29.53%)Baseline: 20.31
27.31
(96.35%)
📈 view plot
🚷 view threshold
38.14
(+15.74%)Baseline: 32.95
45.39
(84.02%)
📈 view plot
🚷 view threshold
298.00
(+17.94%)Baseline: 252.68
390.45
(76.32%)
📈 view plot
🚷 view threshold
294.24
(-16.14%)Baseline: 350.85
263.75
(89.64%)
/error_scenarios_hub: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.92
(+16.87%)Baseline: 19.61
24.82
(92.36%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
59.29
(+91.00%)Baseline: 31.04
43.03
(137.79%)

📈 view plot
🚷 view threshold
308.18
(+27.49%)Baseline: 241.73
360.64
(85.45%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
244.29
(-32.47%)Baseline: 361.73
287.82
(117.82%)

/lazy_apollo_graphql: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
55.74
(+11.17%)Baseline: 50.14
63.37
(87.97%)
📈 view plot
🚷 view threshold
85.00
(-5.26%)Baseline: 89.72
131.52
(64.63%)
📈 view plot
🚷 view threshold
646.54
(-0.31%)Baseline: 648.52
934.49
(69.19%)
📈 view plot
🚷 view threshold
135.53
(+4.10%)Baseline: 130.19
101.96
(75.23%)
/non_existing_react_component: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
8.20
(-58.46%)Baseline: 19.74
26.84
(30.55%)
📈 view plot
🚷 view threshold
23.20
(-33.52%)Baseline: 34.90
53.53
(43.34%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
495.26
(+92.39%)Baseline: 257.43
413.91
(119.65%)

📈 view plot
🚷 view threshold
292.95
(-16.83%)Baseline: 352.21
271.69
(92.74%)
/non_existing_rsc_payload: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.97
(+17.90%)Baseline: 19.48
24.90
(92.25%)
📈 view plot
🚷 view threshold
35.70
(-0.52%)Baseline: 35.89
50.85
(70.20%)
📈 view plot
🚷 view threshold
253.00
(+10.01%)Baseline: 229.97
345.19
(73.29%)
📈 view plot
🚷 view threshold
327.80
(-8.63%)Baseline: 358.76
293.86
(89.65%)
/pure_component_wrapped_in_function: Pro📈 view plot
🚷 view threshold
100.00📈 view plot
🚷 view threshold
20.19
(+12.93%)Baseline: 17.88
21.99
(91.81%)
📈 view plot
🚷 view threshold
33.00
(+14.34%)Baseline: 28.86
37.92
(87.03%)
📈 view plot
🚷 view threshold
230.02
(+3.31%)Baseline: 222.65
320.82
(71.70%)
📈 view plot
🚷 view threshold
386.04
(-3.82%)Baseline: 401.39
324.83
(84.15%)
/react_helmet: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
21.98
(+5.89%)Baseline: 20.76
26.53
(82.85%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
46.39
(+42.09%)Baseline: 32.65
43.58
(106.44%)

📈 view plot
🚷 view threshold
315.56
(+20.47%)Baseline: 261.94
382.93
(82.41%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
259.12
(-24.97%)Baseline: 345.37
268.75
(103.72%)

/react_router: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
17.78
(+2.33%)Baseline: 17.37
22.67
(78.43%)
📈 view plot
🚷 view threshold
24.68
(-16.17%)Baseline: 29.44
36.62
(67.39%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
454.33
(+109.13%)Baseline: 217.25
332.27
(136.73%)

📈 view plot
🚷 view threshold
🚨 view alert (🔔)
272.43
(-30.93%)Baseline: 394.43
280.91
(103.11%)

/redis_receiver: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
65.87
(-5.18%)Baseline: 69.47
88.63
(74.32%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
195.24
(+32.74%)Baseline: 147.08
189.38
(103.09%)

📈 view plot
🚷 view threshold
795.21
(-15.80%)Baseline: 944.38
1,360.59
(58.45%)
📈 view plot
🚷 view threshold
84.31
(-2.09%)Baseline: 86.11
64.09
(76.01%)
/rendered_html: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
🚨 view alert (🔔)
26.45
(+31.18%)Baseline: 20.16
25.13
(105.24%)

📈 view plot
🚷 view threshold
40.79
(+17.81%)Baseline: 34.62
50.31
(81.08%)
📈 view plot
🚷 view threshold
285.96
(+18.86%)Baseline: 240.59
350.33
(81.63%)
📈 view plot
🚷 view threshold
296.29
(-15.55%)Baseline: 350.84
267.47
(90.27%)
/rsc_native_metadata: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
21.92
(+2.68%)Baseline: 21.35
27.48
(79.76%)
📈 view plot
🚷 view threshold
34.39
(-5.43%)Baseline: 36.36
51.15
(67.23%)
📈 view plot
🚷 view threshold
317.58
(+32.66%)Baseline: 239.39
354.76
(89.52%)
📈 view plot
🚷 view threshold
339.35
(+0.32%)Baseline: 338.27
262.74
(77.43%)
/rsc_posts_page_over_redis: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
66.24
(-1.26%)Baseline: 67.09
84.24
(78.63%)
📈 view plot
🚷 view threshold
110.49
(-1.02%)Baseline: 111.63
143.10
(77.21%)
📈 view plot
🚷 view threshold
779.57
(+6.00%)Baseline: 735.45
1,036.69
(75.20%)
📈 view plot
🚷 view threshold
109.73
(+6.73%)Baseline: 102.81
77.57
(70.69%)
/server_render_with_timeout: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
15.51
(-24.06%)Baseline: 20.42
25.51
(60.80%)
📈 view plot
🚷 view threshold
23.20
(-26.62%)Baseline: 31.62
41.65
(55.70%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
452.31
(+87.02%)Baseline: 241.86
363.81
(124.32%)

📈 view plot
🚷 view threshold
290.66
(-18.75%)Baseline: 357.74
280.30
(96.44%)
/server_router: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
21.72
(+1.30%)Baseline: 21.44
26.74
(81.23%)
📈 view plot
🚷 view threshold
36.32
(+3.46%)Baseline: 35.11
47.52
(76.43%)
📈 view plot
🚷 view threshold
261.96
(+7.62%)Baseline: 243.41
355.34
(73.72%)
📈 view plot
🚷 view threshold
350.64
(+3.40%)Baseline: 339.12
261.22
(74.50%)
/server_side_hello_world_es5: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
🚨 view alert (🔔)
28.70
(+38.70%)Baseline: 20.69
26.53
(108.19%)

📈 view plot
🚷 view threshold
39.35
(+15.54%)Baseline: 34.06
46.10
(85.35%)
📈 view plot
🚷 view threshold
169.94
(-31.61%)Baseline: 248.48
369.28
(46.02%)
📈 view plot
🚷 view threshold
298.81
(-14.80%)Baseline: 350.72
267.94
(89.67%)
/server_side_hello_world_hooks: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
21.70
(+9.22%)Baseline: 19.87
25.06
(86.61%)
📈 view plot
🚷 view threshold
34.64
(+1.25%)Baseline: 34.21
45.13
(76.76%)
📈 view plot
🚷 view threshold
237.92
(-1.79%)Baseline: 242.26
365.93
(65.02%)
📈 view plot
🚷 view threshold
348.65
(-2.66%)Baseline: 358.18
283.45
(81.30%)
/server_side_hello_world_shared_store: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
28.57
(+15.41%)Baseline: 24.76
31.43
(90.91%)
📈 view plot
🚷 view threshold
44.03
(+15.04%)Baseline: 38.27
50.13
(87.84%)
📈 view plot
🚷 view threshold
321.73
(+7.28%)Baseline: 299.90
444.38
(72.40%)
📈 view plot
🚷 view threshold
277.61
(-6.63%)Baseline: 297.32
229.55
(82.69%)
/server_side_hello_world_shared_store_defer: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
27.39
(+12.99%)Baseline: 24.24
31.17
(87.86%)
📈 view plot
🚷 view threshold
39.07
(+6.17%)Baseline: 36.80
46.65
(83.75%)
📈 view plot
🚷 view threshold
359.97
(+13.70%)Baseline: 316.59
471.18
(76.40%)
📈 view plot
🚷 view threshold
292.26
(-3.28%)Baseline: 302.16
238.50
(81.60%)
/server_side_hello_world_with_options: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.16
(+7.00%)Baseline: 20.71
26.91
(82.34%)
📈 view plot
🚷 view threshold
33.09
(-5.30%)Baseline: 34.94
51.44
(64.33%)
📈 view plot
🚷 view threshold
256.90
(+1.07%)Baseline: 254.17
376.88
(68.16%)
📈 view plot
🚷 view threshold
266.64
(-21.44%)Baseline: 339.41
260.17
(97.57%)
/server_side_log_throw: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.03
(+6.99%)Baseline: 20.59
25.65
(85.89%)
📈 view plot
🚷 view threshold
33.63
(-1.22%)Baseline: 34.05
48.23
(69.72%)
📈 view plot
🚷 view threshold
299.05
(+19.88%)Baseline: 249.45
365.73
(81.77%)
📈 view plot
🚷 view threshold
348.82
(-1.81%)Baseline: 355.26
274.07
(78.57%)
/server_side_log_throw_raise: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
11.28
(+7.46%)Baseline: 10.50
13.80
(81.72%)
📈 view plot
🚷 view threshold
17.83
(+2.24%)Baseline: 17.44
22.17
(80.43%)
📈 view plot
🚷 view threshold
131.00
(+4.33%)Baseline: 125.57
183.91
(71.23%)
📈 view plot
🚷 view threshold
525.59
(-23.14%)Baseline: 683.87
507.07
(96.48%)
/ssr_async_error: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
24.97
(+24.82%)Baseline: 20.00
27.07
(92.24%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
70.72
(+111.20%)Baseline: 33.48
46.22
(153.00%)

📈 view plot
🚷 view threshold
336.70
(+21.66%)Baseline: 276.75
418.34
(80.49%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
225.25
(-33.33%)Baseline: 337.87
270.06
(119.89%)

/ssr_async_prop_error: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
25.55
(+17.91%)Baseline: 21.67
27.66
(92.38%)
📈 view plot
🚷 view threshold
42.63
(+18.80%)Baseline: 35.88
52.38
(81.38%)
📈 view plot
🚷 view threshold
289.94
(+12.71%)Baseline: 257.25
375.26
(77.26%)
📈 view plot
🚷 view threshold
293.26
(-11.11%)Baseline: 329.90
266.46
(90.86%)
/stream_native_metadata: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
24.10
(+15.78%)Baseline: 20.81
26.79
(89.97%)
📈 view plot
🚷 view threshold
39.44
(+11.95%)Baseline: 35.23
49.25
(80.09%)
📈 view plot
🚷 view threshold
276.75
(+14.91%)Baseline: 240.85
357.55
(77.40%)
📈 view plot
🚷 view threshold
315.37
(-8.93%)Baseline: 346.29
260.05
(82.46%)
/stream_shell_error_demo: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.92
(+11.60%)Baseline: 20.54
26.75
(85.69%)
📈 view plot
🚷 view threshold
36.35
(-5.85%)Baseline: 38.61
97.41
(37.32%)
📈 view plot
🚷 view threshold
311.07
(+24.08%)Baseline: 250.70
380.28
(81.80%)
📈 view plot
🚷 view threshold
325.20
(-5.79%)Baseline: 345.18
261.57
(80.43%)
/test_incremental_rendering: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
24.63
(+18.51%)Baseline: 20.78
25.61
(96.17%)
📈 view plot
🚷 view threshold
36.53
(-0.02%)Baseline: 36.54
52.21
(69.97%)
📈 view plot
🚷 view threshold
266.70
(+5.09%)Baseline: 253.77
356.28
(74.86%)
📈 view plot
🚷 view threshold
315.52
(-6.82%)Baseline: 338.60
265.30
(84.08%)
🐰 View full continuous benchmarking report in Bencher

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchalexeyr/3459-unify-suites
Testbedgithub-actions

🚨 12 Alerts

BenchmarkMeasure
Units
ViewBenchmark Result
(Result Δ%)
Upper Boundary
(Limit %)
/async_on_server_sync_on_client_client_render: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
51.70
(+58.13%)Baseline: 32.69
43.61
(118.54%)

/context_function_return_jsx: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
51.17
(+64.19%)Baseline: 31.17
42.81
(119.52%)

/image_example: Prop99_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
407.06
(+52.65%)Baseline: 266.66
394.20
(103.26%)

/non_existing_stream_react_component: Prop99_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
476.92
(+87.49%)Baseline: 254.38
360.20
(132.40%)

/react_helmet_broken: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
41.39
(+31.39%)Baseline: 31.50
39.42
(105.00%)

/rsc_component_error: Prop99_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
436.25
(+69.34%)Baseline: 257.62
370.54
(117.73%)

/server_router_client_render: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
53.78
(+61.37%)Baseline: 33.33
50.17
(107.20%)

/server_side_hello_world_shared_store_controller: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
69.52
(+75.00%)Baseline: 39.73
53.95
(128.85%)

/server_side_log_throw_plain_js: Prop99_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
369.29
(+63.87%)Baseline: 225.36
344.87
(107.08%)

/server_side_redux_app: Prop99_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
421.88
(+57.59%)Baseline: 267.71
395.31
(106.72%)

/ssr_shell_error: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
49.93
(+48.22%)Baseline: 33.69
46.18
(108.11%)

/ssr_sync_error: Prop90_latency
ms
📈 plot
🚷 threshold
🚨 alert (🔔)
54.45
(+51.84%)Baseline: 35.86
51.95
(104.82%)

Click to view all benchmark results
Benchmarkfailed_pct%p50_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
p90_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
p99_latencyBenchmark Result
ms
(Result Δ%)
Upper Boundary
ms
(Limit %)
rpsBenchmark Result
req/s
(Result Δ%)
Lower Boundary
req/s
(Limit %)
/apollo_graphql: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
48.86
(-8.63%)Baseline: 53.47
66.73
(73.22%)
📈 view plot
🚷 view threshold
85.09
(-5.59%)Baseline: 90.13
124.27
(68.47%)
📈 view plot
🚷 view threshold
558.30
(-10.58%)Baseline: 624.36
913.61
(61.11%)
📈 view plot
🚷 view threshold
145.16
(+11.60%)Baseline: 130.07
105.39
(72.60%)
/async_on_server_sync_on_client_client_render: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
17.39
(-10.39%)Baseline: 19.41
25.71
(67.64%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
51.70
(+58.13%)Baseline: 32.69
43.61
(118.54%)

📈 view plot
🚷 view threshold
255.33
(+4.15%)Baseline: 245.15
355.17
(71.89%)
📈 view plot
🚷 view threshold
318.22
(-13.44%)Baseline: 367.64
291.58
(91.63%)
/async_render_function_returns_component: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
20.25
(-3.19%)Baseline: 20.92
26.29
(77.03%)
📈 view plot
🚷 view threshold
31.32
(-9.50%)Baseline: 34.61
46.71
(67.06%)
📈 view plot
🚷 view threshold
284.57
(+12.81%)Baseline: 252.25
381.79
(74.54%)
📈 view plot
🚷 view threshold
369.64
(+7.96%)Baseline: 342.39
257.65
(69.70%)
/cache_demo: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
20.95
(+0.51%)Baseline: 20.84
28.03
(74.73%)
📈 view plot
🚷 view threshold
32.41
(-10.47%)Baseline: 36.20
56.44
(57.42%)
📈 view plot
🚷 view threshold
232.96
(-18.81%)Baseline: 286.94
437.56
(53.24%)
📈 view plot
🚷 view threshold
357.98
(+11.93%)Baseline: 319.81
238.92
(66.74%)
/client_side_hello_world_shared_store: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
19.79
(-1.25%)Baseline: 20.04
25.73
(76.90%)
📈 view plot
🚷 view threshold
31.54
(-2.42%)Baseline: 32.32
40.55
(77.78%)
📈 view plot
🚷 view threshold
287.38
(+8.81%)Baseline: 264.12
394.62
(72.83%)
📈 view plot
🚷 view threshold
361.67
(+5.36%)Baseline: 343.28
262.16
(72.49%)
/client_side_hello_world_shared_store_defer: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
20.47
(-3.74%)Baseline: 21.27
26.70
(76.66%)
📈 view plot
🚷 view threshold
33.36
(+0.91%)Baseline: 33.06
45.05
(74.05%)
📈 view plot
🚷 view threshold
188.54
(-23.66%)Baseline: 246.98
379.49
(49.68%)
📈 view plot
🚷 view threshold
363.96
(+6.01%)Baseline: 343.31
266.29
(73.16%)
/client_side_log_throw: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
18.63
(+0.74%)Baseline: 18.49
25.80
(72.21%)
📈 view plot
🚷 view threshold
31.39
(+7.44%)Baseline: 29.21
39.22
(80.05%)
📈 view plot
🚷 view threshold
216.46
(-12.74%)Baseline: 248.07
393.00
(55.08%)
📈 view plot
🚷 view threshold
393.46
(+4.22%)Baseline: 377.54
289.68
(73.62%)
/console_logs_in_async_server: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
2,122.73
(-0.09%)Baseline: 2,124.69
2,130.83
(99.62%)
📈 view plot
🚷 view threshold
2,142.44
(-11.14%)Baseline: 2,411.01
5,184.17
(41.33%)
📈 view plot
🚷 view threshold
23,352.42
(+2.48%)Baseline: 22,786.75
30,670.31
(76.14%)
📈 view plot
🚷 view threshold
3.16
(+1.73%)Baseline: 3.11
2.33
(73.86%)
/context_function_return_jsx: Pro📈 view plot
🚷 view threshold
100.00📈 view plot
🚷 view threshold
16.22
(-12.20%)Baseline: 18.47
23.41
(69.29%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
51.17
(+64.19%)Baseline: 31.17
42.81
(119.52%)

📈 view plot
🚷 view threshold
225.72
(+5.54%)Baseline: 213.88
333.56
(67.67%)
📈 view plot
🚷 view threshold
345.27
(-12.09%)Baseline: 392.77
321.85
(93.22%)
/empty: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
6.76
(+19.47%)Baseline: 5.66
7.51
(89.99%)
📈 view plot
🚷 view threshold
8.61
(-2.52%)Baseline: 8.83
11.08
(77.70%)
📈 view plot
🚷 view threshold
37.28
(-49.58%)Baseline: 73.94
106.61
(34.97%)
📈 view plot
🚷 view threshold
1,291.08
(+1.22%)Baseline: 1,275.50
1,061.19
(82.19%)
/hybrid_metadata_streaming: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
20.52
(-0.16%)Baseline: 20.55
27.58
(74.40%)
📈 view plot
🚷 view threshold
32.35
(-13.49%)Baseline: 37.40
56.75
(57.01%)
📈 view plot
🚷 view threshold
290.28
(+10.56%)Baseline: 262.57
410.78
(70.67%)
📈 view plot
🚷 view threshold
357.80
(+6.52%)Baseline: 335.91
261.74
(73.15%)
/image_example: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
14.86
(-30.09%)Baseline: 21.26
26.24
(56.64%)
📈 view plot
🚷 view threshold
28.36
(-21.53%)Baseline: 36.14
53.70
(52.81%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
407.06
(+52.65%)Baseline: 266.66
394.20
(103.26%)

📈 view plot
🚷 view threshold
365.98
(+10.02%)Baseline: 332.66
248.37
(67.86%)
/loadable: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
26.00
(+14.46%)Baseline: 22.71
28.82
(90.23%)
📈 view plot
🚷 view threshold
36.15
(+3.66%)Baseline: 34.87
45.20
(79.98%)
📈 view plot
🚷 view threshold
156.54
(-45.59%)Baseline: 287.71
425.65
(36.78%)
📈 view plot
🚷 view threshold
321.96
(+2.70%)Baseline: 313.49
237.56
(73.79%)
/native_metadata: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
20.77
(-3.05%)Baseline: 21.42
27.60
(75.26%)
📈 view plot
🚷 view threshold
33.27
(-6.74%)Baseline: 35.67
52.14
(63.81%)
📈 view plot
🚷 view threshold
253.23
(-0.86%)Baseline: 255.42
381.55
(66.37%)
📈 view plot
🚷 view threshold
369.92
(+9.98%)Baseline: 336.34
260.14
(70.32%)
/non_existing_stream_react_component: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
8.85
(-56.27%)Baseline: 20.24
24.79
(35.69%)
📈 view plot
🚷 view threshold
27.48
(-18.11%)Baseline: 33.56
43.24
(63.56%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
476.92
(+87.49%)Baseline: 254.38
360.20
(132.40%)

📈 view plot
🚷 view threshold
366.06
(+2.43%)Baseline: 357.38
288.21
(78.73%)
/posts_page: Pro📈 view plot
🚷 view threshold
100.00📈 view plot
🚷 view threshold
8.88
(-1.84%)Baseline: 9.05
10.96
(81.02%)
📈 view plot
🚷 view threshold
12.23
(-9.42%)Baseline: 13.50
16.64
(73.50%)
📈 view plot
🚷 view threshold
88.85
(-17.12%)Baseline: 107.20
151.11
(58.80%)
📈 view plot
🚷 view threshold
910.52
(+11.69%)Baseline: 815.25
629.56
(69.14%)
/pure_component: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
20.90
(+0.01%)Baseline: 20.90
26.70
(78.28%)
📈 view plot
🚷 view threshold
36.07
(+1.47%)Baseline: 35.55
51.49
(70.05%)
📈 view plot
🚷 view threshold
179.54
(-24.69%)Baseline: 238.40
370.73
(48.43%)
📈 view plot
🚷 view threshold
361.92
(+5.68%)Baseline: 342.46
268.06
(74.07%)
/react_helmet_broken: Pro📈 view plot
🚷 view threshold
100.00📈 view plot
🚷 view threshold
18.13
(-12.15%)Baseline: 20.64
26.36
(68.78%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
41.39
(+31.39%)Baseline: 31.50
39.42
(105.00%)

📈 view plot
🚷 view threshold
263.47
(+6.22%)Baseline: 248.04
376.43
(69.99%)
📈 view plot
🚷 view threshold
308.87
(-14.97%)Baseline: 363.25
288.83
(93.51%)
/render_js: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
18.38
(-0.34%)Baseline: 18.44
23.82
(77.16%)
📈 view plot
🚷 view threshold
30.26
(-2.00%)Baseline: 30.88
41.25
(73.35%)
📈 view plot
🚷 view threshold
222.86
(-4.08%)Baseline: 232.33
332.92
(66.94%)
📈 view plot
🚷 view threshold
411.12
(+7.72%)Baseline: 381.66
297.27
(72.31%)
/rsc_component_error: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
6.98
(-65.97%)Baseline: 20.51
26.90
(25.95%)
📈 view plot
🚷 view threshold
19.61
(-42.90%)Baseline: 34.34
47.33
(41.43%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
436.25
(+69.34%)Baseline: 257.62
370.54
(117.73%)

📈 view plot
🚷 view threshold
329.42
(-4.46%)Baseline: 344.79
279.40
(84.82%)
/rsc_echo_props: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
30.36
(+5.26%)Baseline: 28.84
38.89
(78.07%)
📈 view plot
🚷 view threshold
48.90
(+3.18%)Baseline: 47.39
62.95
(77.68%)
📈 view plot
🚷 view threshold
352.59
(-11.29%)Baseline: 397.45
618.45
(57.01%)
📈 view plot
🚷 view threshold
254.91
(+8.57%)Baseline: 234.78
185.37
(72.72%)
/rsc_posts_page_over_http: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
20.86
(-1.54%)Baseline: 21.19
27.64
(75.47%)
📈 view plot
🚷 view threshold
33.02
(-5.35%)Baseline: 34.89
50.17
(65.82%)
📈 view plot
🚷 view threshold
290.97
(+11.39%)Baseline: 261.22
395.20
(73.63%)
📈 view plot
🚷 view threshold
353.34
(+4.11%)Baseline: 339.38
263.74
(74.64%)
/server_router_client_render: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
17.44
(-10.85%)Baseline: 19.56
26.04
(66.96%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
53.78
(+61.37%)Baseline: 33.33
50.17
(107.20%)

📈 view plot
🚷 view threshold
247.73
(+1.06%)Baseline: 245.13
363.75
(68.10%)
📈 view plot
🚷 view threshold
313.38
(-10.96%)Baseline: 351.96
282.32
(90.09%)
/server_side_hello_world: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
21.19
(-2.17%)Baseline: 21.66
28.50
(74.35%)
📈 view plot
🚷 view threshold
35.61
(+2.14%)Baseline: 34.86
45.90
(77.58%)
📈 view plot
🚷 view threshold
255.86
(+4.64%)Baseline: 244.51
366.34
(69.84%)
📈 view plot
🚷 view threshold
355.57
(+4.23%)Baseline: 341.12
262.83
(73.92%)
/server_side_hello_world_shared_store_controller: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
22.07
(-13.92%)Baseline: 25.64
32.98
(66.93%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
69.52
(+75.00%)Baseline: 39.73
53.95
(128.85%)

📈 view plot
🚷 view threshold
300.11
(+0.29%)Baseline: 299.24
439.78
(68.24%)
📈 view plot
🚷 view threshold
248.31
(-13.41%)Baseline: 286.75
217.84
(87.73%)
/server_side_log_throw_plain_js: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
13.07
(-31.30%)Baseline: 19.03
24.82
(52.66%)
📈 view plot
🚷 view threshold
25.82
(-15.38%)Baseline: 30.51
39.75
(64.96%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
369.29
(+63.87%)Baseline: 225.36
344.87
(107.08%)

📈 view plot
🚷 view threshold
410.50
(+5.79%)Baseline: 388.04
302.71
(73.74%)
/server_side_log_throw_raise_invoker: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
16.81
(+0.47%)Baseline: 16.73
20.83
(80.71%)
📈 view plot
🚷 view threshold
25.70
(-3.60%)Baseline: 26.66
35.63
(72.13%)
📈 view plot
🚷 view threshold
232.85
(+9.34%)Baseline: 212.96
315.30
(73.85%)
📈 view plot
🚷 view threshold
438.16
(+5.80%)Baseline: 414.14
310.24
(70.81%)
/server_side_redux_app: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
14.93
(-30.52%)Baseline: 21.49
28.19
(52.96%)
📈 view plot
🚷 view threshold
28.87
(-15.22%)Baseline: 34.05
45.55
(63.37%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
421.88
(+57.59%)Baseline: 267.71
395.31
(106.72%)

📈 view plot
🚷 view threshold
359.72
(+7.07%)Baseline: 335.97
268.64
(74.68%)
/server_side_redux_app_cached: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
19.14
(-2.63%)Baseline: 19.66
25.88
(73.96%)
📈 view plot
🚷 view threshold
28.12
(-10.48%)Baseline: 31.41
42.76
(65.76%)
📈 view plot
🚷 view threshold
215.49
(-7.48%)Baseline: 232.90
340.44
(63.30%)
📈 view plot
🚷 view threshold
397.67
(+6.87%)Baseline: 372.12
300.03
(75.45%)
/ssr_shell_error: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
18.19
(-8.99%)Baseline: 19.99
27.81
(65.40%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
49.93
(+48.22%)Baseline: 33.69
46.18
(108.11%)

📈 view plot
🚷 view threshold
261.18
(-1.98%)Baseline: 266.45
422.65
(61.80%)
📈 view plot
🚷 view threshold
304.55
(-13.01%)Baseline: 350.08
284.41
(93.39%)
/ssr_sync_error: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
18.31
(-12.78%)Baseline: 20.99
25.75
(71.10%)
📈 view plot
🚷 view threshold
🚨 view alert (🔔)
54.45
(+51.84%)Baseline: 35.86
51.95
(104.82%)

📈 view plot
🚷 view threshold
265.40
(+5.43%)Baseline: 251.74
350.59
(75.70%)
📈 view plot
🚷 view threshold
302.31
(-12.05%)Baseline: 343.74
277.99
(91.96%)
/stream_async_components: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
18.06
(-13.50%)Baseline: 20.88
27.86
(64.81%)
📈 view plot
🚷 view threshold
47.45
(+31.32%)Baseline: 36.13
53.41
(88.85%)
📈 view plot
🚷 view threshold
262.91
(+1.24%)Baseline: 259.69
366.16
(71.80%)
📈 view plot
🚷 view threshold
304.62
(-8.93%)Baseline: 334.50
267.48
(87.81%)
/stream_error_demo: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
20.69
(-0.55%)Baseline: 20.80
27.25
(75.94%)
📈 view plot
🚷 view threshold
35.31
(-0.16%)Baseline: 35.37
49.81
(70.89%)
📈 view plot
🚷 view threshold
248.01
(-7.35%)Baseline: 267.68
409.06
(60.63%)
📈 view plot
🚷 view threshold
359.84
(+5.31%)Baseline: 341.69
259.00
(71.98%)
/turbolinks_cache_disabled: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
18.90
(+0.02%)Baseline: 18.90
25.01
(75.56%)
📈 view plot
🚷 view threshold
28.58
(-5.96%)Baseline: 30.39
42.13
(67.83%)
📈 view plot
🚷 view threshold
221.60
(-1.73%)Baseline: 225.50
344.35
(64.35%)
📈 view plot
🚷 view threshold
392.45
(+5.01%)Baseline: 373.72
289.55
(73.78%)
/xhr_refresh: Pro📈 view plot
🚷 view threshold
0.00📈 view plot
🚷 view threshold
24.51
(-1.45%)Baseline: 24.87
32.69
(74.97%)
📈 view plot
🚷 view threshold
36.30
(-4.99%)Baseline: 38.21
50.52
(71.86%)
📈 view plot
🚷 view threshold
340.80
(+13.84%)Baseline: 299.37
423.83
(80.41%)
📈 view plot
🚷 view threshold
315.09
(+7.49%)Baseline: 293.14
216.19
(68.61%)
🐰 View full continuous benchmarking report in Bencher

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants