Skip to content

[code-infra] Port the benchmarks to new library - #5974

Draft
Janpot wants to merge 27 commits into
mui:masterfrom
Janpot:janpot/benchmark-cli
Draft

Janpot wants to merge 27 commits into
mui:masterfrom
Janpot:janpot/benchmark-cli

Conversation

@Janpot

@Janpot Janpot commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Closes #5403

Ports the benchmarks to the benchmark CLI from mui/mui-public#1898 (installed from its pkg.pr.new build), the way mui/base-ui-charts#1186 and mui/material-ui#49329 do, and removes the Vitest benchmarks in test/performance.

smoke/smoke.bench.tsx mounts each of the library's 36 components in a benchmark of its own; the runner shares one page load per round between a file's benchmarks, so the file costs little more than one. It replaces the separate mount benchmarks. The pull request job runs only the smoke file; the Combobox, Menu and Select open and typing cases stay, for a nightly run against the last release, to be set up separately.

Comparison

We ran both setups 10 times in CI on all 15 benchmarks. A good setup should therefore report "no change" every time. Any regression it reports is a false alarm.

Both time the same thing: React's render and the paint after it. Vitest runs on a 2-CPU machine, the new tool on a larger one.

Vitest (removed) New tool, separate files (earlier version of this PR)
Runs with a false alarm 4 of 10 0 of 10
Benchmarks flagged, in total 18 0
Precision ±12% to ±46% ±2% to ±8%
Precision, typical benchmark ±32% ±4.7%
Error margin each run reports, compared with reality about 7× too small about 1.1× too small
CI job time, typical (fastest–slowest) 4.9 (4.3–5.8) min 11.6 (9.7–14.2) min

Precision is roughly the smallest slowdown a setup can reliably catch.

The same check on the smoke file as the pull request job runs it now (10% threshold, 3 minutes per run):

Smoke file (36)
Runs with a false alarm 1 of 10 (Collapsible, render)
Precision, typical ±9% render, ±8% paint
Error margin vs reality about 1.0× (accurate)
CI job time 5.4 (4.0–6.0) min

The smoke file gets 30 to 70 rounds within its time limit, so it is less precise than the separate files were; it is meant to catch big regressions. The one false alarm was a whole run off by +10% to +32% for Collapsible, which renders in a few milliseconds.

Library fixes, to try the benchmarks on

Three changes that make components render less on mount:

  • Slider no longer re-renders every part once its thumbs register; only Slider.Value updates.
  • Radio Group, Toggle Group, Toolbar, Tabs and Menubar items take their position from render order instead of re-rendering once to learn it.
  • Scroll Area measures every instance on the page before updating any, instead of making the browser redo layout once per instance.

Measured in CI by the smoke file against master: Slider −17% to −34% render time, Toggle Group −5% to −29%, Toolbar −3% to −26%; Radio Group and Scroll Area showed no clear change, and no other benchmark changed. The earlier separate benchmarks measured Slider −20% to −31%, Radio Group −10% to −26% and Toggle Group −20% to −32%.

test/benchmark holds the same benchmarks as test/performance, on reactBenchmark() from @mui/internal-benchmark/page, run by the benchmark CLI from mui/mui-public#1898 (its preview build). test/performance stays for comparison as test:benchmark:vitest.
@Janpot Janpot mentioned this pull request Oct 12, 2026
4 tasks
@pkg-pr-new

pkg-pr-new Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

commit: 0306ea1

@code-infra-dashboard

code-infra-dashboard Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Bundle size

Bundle Parsed size Gzip size
@base-ui/react 🔺+302B(+0.06%) 🔺+153B(+0.09%)

Details of bundle changes

Performance

No regressions in 36 benchmarks · ran 4m 24s · details

Smoke · RadioGroup

Metric baseline current Δ vs baseline
render 13.8 ms 11 ms 🟢 better -36.6% – -10.3%
bench:paint 23.85 ms 18.8 ms 🟢 better -33.9% – -10.7%

Smoke · Slider

Metric baseline current Δ vs baseline
render 20.6 ms 14.9 ms 🟢 better -42.5% – -22.2%
bench:paint 33.65 ms 25.5 ms 🟢 better -37.1% – -18.3%

Smoke · ToggleGroup

Metric baseline current Δ vs baseline
render 4.8 ms 3.85 ms 🟢 better -32.3% – -1.6%
bench:paint 9.45 ms 7.9 ms 🟢 better -30.0% – -4.8%

Smoke · Toolbar

Metric baseline current Δ vs baseline
render 7.6 ms 5.85 ms 🟢 better -37.3% – -8.0%
bench:paint 15.25 ms 11.6 ms 🟢 better -36.3% – -11.1%

Medians; Δ is the confidence interval of the paired per-round difference (99%).


Check out the code infra dashboard for more information about this PR.

@netlify

netlify Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for base-ui ready!

Name Link
🔨 Latest commit 0306ea1
🔍 Latest deploy log https://app.netlify.com/projects/base-ui/deploys/6ad0af2ad40055cc413e3cef
😎 Deploy Preview https://deploy-preview-5974--base-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

…as artifacts

The .lintignore entries were appended onto its last line. The artifacts are TEMPORARY, while the benchmark setups are compared on repeated runs.
@Janpot Janpot added the internal Behind-the-scenes enhancement. Formerly called “core”. label Oct 12, 2026
Janpot added 22 commits October 12, 2026 10:33
Shortens the Benchmark CLI check on pull requests; with 50 rounds and 3 minutes it took 19 minutes for the 15 benchmarks.
test/benchmark runs the same cases with the same metrics, so the Vitest suite in
test/performance and its CI job go. The CLI job takes over the 'Benchmark tests'
name.
…y component

smoke/smoke.bench.tsx mounts each of the library's 36 components on its own, at a
modest count; the runner shares a page load per round between a file's benchmarks
(mui/mui-public#1898 at 621b803), so they cost little more than one. The separate
mount benchmarks and the mixed surface it duplicates go; the Combobox, Menu and
Select open and typing cases stay.
The rows were built inside each render function, so every sample built them again
inside the timed window. Also picks up mui/mui-public#1898 at feb4328, which stops
the page build from warning about every 'use client' directive.
A round of the whole smoke file takes about 4 s in CI, so a minute fit about 15
rounds past the sample size, too few to settle at the 5% band.
smokeBenchmark(name, count, renderRow) creates the rows once per page load and
applies the shared sampling, so each case is just the component it mounts. Picks up
mui/mui-public#1898 at f172e98.
…s the sample size; graceful stop on a signal
The open and typing benchmarks stay, for a fuller run against the last release to be
set up separately.
Their CI precision is about ±10%; at the default 5% band, a run of unchanged code
flagged one of them in 10. They are there to catch big regressions.
The 30-round sample size moves from the CI command into SMOKE_OPTIONS, so a local run
samples the same way; the 3-minute timeout was the default and goes. The comments say
why without numbers that drift.
@Janpot Janpot changed the title [test] Port the benchmarks to the benchmark CLI [code-infra] Port the benchmarks to new library Oct 14, 2026
@github-actions github-actions Bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Oct 16, 2026

This branch has not been deployed

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

Labels

internal Behind-the-scenes enhancement. Formerly called “core”. PR: out-of-date The pull request has merge conflicts and can't be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant