Add renderer/style-recalc benchmarks, findings doc and layout profiler - #3795
Add renderer/style-recalc benchmarks, findings doc and layout profiler#3795mattgperry wants to merge 2 commits into
Conversation
- dev/html/public/benchmarks: interactive benchmarks comparing renderer strategies (inline style, adopted stylesheet, registered CSS variables, WAAPI, CSS transitions, GSAP) in benign and hostile style-recalculation environments, plus a harness that isolates which selector/environment patterns turn a single style-attribute write into a full-page recalculation. - FINDINGS.md: measured results and methodology, including measurement pitfalls (vsync floor, rAF throttling in occluded tabs, tween semantics) and layout projection profiling notes. - dev/react/profile-layout.mjs: Playwright/CDP V8 sampling profiler for the layout stress examples, reporting projection-attributed JS time and per-function hotspots. - layout-stress-deep example: deep-tree (30x40) layout animation stress test exercising per-ancestor projection cost. Co-authored-by: Cursor <cursoragent@cursor.com>
Greptile SummaryThe PR adds interactive renderer/style-recalculation benchmarks, a findings document, a CDP layout profiler, and a deep projection stress example. One configured renderer currently prevents the benchmark suites from completing.
Confidence Score: 4/5The benchmark tooling should not merge until the nonexistent The new benchmark pages all configure a variable renderer whose bind path invokes an API absent from the loaded Motion entrypoint, preventing complete results; the remaining clock-guidance issue is non-blocking. Files Needing Attention: dev/html/public/benchmarks/renderer-bench-lib.js, dev/html/public/benchmarks/style-recalc-harness.html Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart LR
P["Benchmark page"] --> R["Shared runner"]
R --> B["Bind selected strategy"]
B --> A["Animate values"]
A --> M["Frame meter"]
M --> T["Results table"]
P2["Layout profiler"] --> D["dev/react example"]
D --> C["Click layout stress case"]
C --> V["CDP V8 profile"]
V --> O["JSON profile report"]
Reviews (1): Last reviewed commit: "Add renderer/style-recalc benchmarks, fi..." | Re-trigger Greptile |
| const cleanups = [] | ||
| for (const box of boxes) { | ||
| const values = makeValues(props) | ||
| cleanups.push(varEffect(box, values)) |
There was a problem hiding this comment.
Undefined variable renderer API
When any automatic benchmark reaches the var strategy, this calls varEffect, but framer-motion/dom exports no such API, causing a TypeError that stops the run before the remaining strategies execute or a complete results table is produced.
Knowledge Base Used: Repo Build Tooling
| const preRender = () => { | ||
| renderStart = performance.now() | ||
| } | ||
| const postRender = () => { | ||
| renderMs += performance.now() - renderStart |
There was a problem hiding this comment.
Unsynchronized benchmark clock
These frame-step measurements, along with the corresponding flush and setup timings in style-recalc-harness.html, use performance.now() instead of the repository-required time.now(), weakening timestamp consistency within Motion's synchronized frameloop.
Context Used: CLAUDE.md (source)
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!
Review finding: the benchmarks destructured varEffect from window.Motion, but that only exists on an experimental branch - on main the var strategies threw at bind time. The lib now falls back to a standalone implementation of the same mechanism (per-value registered custom property with inherits: false, style points at var(--name) once, per-frame writes touch only the custom property), preferring Motion.varEffect when present. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Moved to the private motiondivision/motion-research repo (benchmarks made standalone via pinned esm.sh imports, findings updated with per-item attribution corrections). Keeping research artifacts out of library history. |
Summary
dev/html/public/benchmarks: interactive benchmarks comparing renderer strategies (inline style writes, adopted stylesheet, registered CSS variables, WAAPI, CSS transitions, GSAP) in benign and hostile style-recalculation environments, plusstyle-recalc-harness.html, which isolates which selector/environment patterns ([style*=…]attribute selectors, inherited properties,@container style()queries) turn a single style-attribute write into a full-page recalculation.FINDINGS.md: measured results and methodology — what triggers recalculation bombs, renderer comparisons, and measurement pitfalls (vsync floor masking real cost, rAF throttling in occluded tabs, tween semantics differences between libraries).dev/react/profile-layout.mjs: Playwright/CDP V8 sampling profiler for the layout stress examples, reporting projection-attributed JS time and per-function self-time hotspots. Works with both the current minimalrecordStatsand newer reporter-returning versions.layout-stress-deepexample: deep-tree (depth 30 × 40 chains) layout animation stress test exercising per-ancestor projection cost.No library code changes — dev/test tooling only.
Test plan
layout-stress-deepandlayout-stress-transformon main