You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
demo(benchmark-react): reduce variance with in-page sub-iterations (#3811)
* demo(benchmark-react): reduce CI benchmark variance below ±10
- Increase warmup and measurement iterations for CI (small: 5+25, large: 3+20)
- Tighten convergence targets (small: 5%, large: 8%)
- Switch from stddev to MAD-based CI margin for robustness against outliers
- Increase inter-scenario GC settle time from 50ms to 200ms
Made-with: Cursor
* demo(benchmark-react): add in-page sub-iterations and reduce variance
- Run multiple ops per page visit (default 5), returning the median
duration as one sample. Eliminates page-navigation overhead between
measurements and dramatically reduces variance.
- Add resetStore() to BenchAPI for clearing caches between mount
sub-iterations (data-client, tanstack-query, swr).
- Vary mutation data each sub-iteration (incrementing counter for
titles, toggling moveItem direction) to ensure real DOM changes.
- Add waitForPaint between mutation sub-iterations to prevent
server-resolution renders from bleeding into the next measurement.
- Report variance as percentage instead of absolute values.
- Reduce warmup/minMeasurement counts since sub-iterations provide
sufficient noise reduction.
- Fix SWR mount sub-iterations: add revalidateOnMount + dedupingInterval: 0
to ensure fresh fetches after cache.clear().
- Update README with latest results showing ~6778% mutation throughput
advantage for data-client (up from ~4442% with more accurate measurement).
Made-with: Cursor
* fix: bugbot
* demo(benchmark-react): reduce warmup/measurement counts for faster CI
With 5 sub-iterations per round providing sufficient noise reduction,
lower warmup (small: 3→2, large: 2→1) and max measurement caps
(small CI: 20→15, large CI: 15→12) to cut ~30-40s from CI runtime.
Made-with: Cursor
* Fix benchmark range format for single sample
Co-authored-by: Nathaniel Tucker <me@ntucker.me>
* demo(benchmark-react): fix stats bugs and add per-scenario opsPerRound
- Replace z=1.96 with t-distribution critical values for accurate CI
on small samples (n=3-15)
- Fix even-length median calculation in scaledMAD/isConverged/computeStats
- Fix median===0 premature convergence (now requires margin===0 too)
- Fix invalidateAndResolve title accumulation bug using fixture data
- Clamp deleteEntity sub-iteration args to mountCount bound
- Remove dead cdp parameter from runScenario
- Add per-scenario opsPerRound override to Scenario type
- Set opsPerRound=9 for update-entity-sorted, =5 for list-detail-switch-10
- Update README with remeasured results and variance tiers
Made-with: Cursor
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Copy file name to clipboardExpand all lines: examples/benchmark-react/README.md
+22-22Lines changed: 22 additions & 22 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,8 +13,8 @@ The repo has two benchmark suites:
13
13
14
14
-**What we measure:** Wall-clock time from triggering an action (e.g. `init(100)` or `updateUser('user0')`) until a MutationObserver detects the expected DOM change in the benchmark container. Optionally we also record React Profiler commit duration and, with `BENCH_TRACE=true`, Chrome trace duration.
15
15
-**Why:** Normalized caching should show wins on shared-entity updates (one store write, many components update), ref stability (fewer new object references), and derived-view memoization (`Query` schema avoids re-sorting when entities haven't changed). See [js-framework-benchmark "How the duration is measured"](https://github.com/krausest/js-framework-benchmark/wiki/How-the-duration-is-measured) for a similar timeline-based approach.
16
-
-**Statistical:** Warmup runs are discarded; we report median and 95% CI. Libraries are interleaved per round to reduce environmental variance.
17
-
-**No CPU throttling:** Runs at native speed with more samples for statistical significance rather than artificial slowdown. Small (cheap) scenarios use 3 warmup + 15 measurement runs locally (10 in CI); large (expensive) scenarios use 1 warmup + 4 measurement runs.
16
+
-**Statistical:** Warmup runs are discarded; we report median and 95% CI (as percentage of median). Libraries are interleaved per round to reduce environmental variance. Each round runs multiple sub-iterations per page visit and reports the median, further reducing per-sample noise. The default is 5 sub-iterations; individual scenarios can override this via `opsPerRound` in `bench/scenarios.ts` (e.g. `update-entity-sorted` uses 9, `list-detail-switch-10` uses 5).
17
+
-**No CPU throttling:** Runs at native speed with more samples for statistical significance rather than artificial slowdown. Small (cheap) scenarios use 2 warmup + up to 12 measurement rounds locally; large (expensive) scenarios use 1 warmup + up to 6 measurement rounds. Early stopping triggers when 95% CI margin drops below the target percentage.
0 commit comments