Repository navigation
Conversation
The layout setter redefined `visible` on Container.prototype on every container's first layout, and restored Pixi's original descriptor whenever any container's layout was removed. The restore also stripped visibility tracking from every other container that still had a layout. Install the override once and never restore it. Its setter does no layout work for containers without a layout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
We build audio plugin editors on Pixi and @pixi/layout that run in native web views inside DAWs, so mount time matters to us: editors are opened and closed constantly while people work. We have been running a series of measured performance passes on our UI library, profiling and comparing before and after each change, and one of the biggest costs turned out to be inside @pixi/layout.
Headline: installing the
visibleoverride once instead of on every first layout made mounting 2,041 layout nodes about 73% faster in a standalone benchmark (82 ms to 23 ms in Chrome), and cut total mount CPU by about 15% in our own UI stress test. While testing the fix we also found a small visibility bug in the same code, fixed here too.Detailed benchmarks, method and caveats are further down.
Overview
The
layoutsetter inContainerMixinredefinesvisibleonContainer.prototypeeach time a container gets its first layout, and restores Pixi's original descriptor whenever any container's layout is removed. This PR installs the override once and keeps it.Problem
Fix
this.layoutis set, so containers without a layout behave as before.Most of the diff is re-indentation. If you would rather install the override at import time, as
TextMixindoes fortext, I can switch to that.Tests
Two new tests in
tests/__tests__/visibility.test.ts:visiblesetter stays the same function across several first layouts and after one layout is removed;Both fail on
mainand pass with this change. Lint, types andnpm run buildpass. Unit tests: 123 of 127 pass; the 4 failures are story screenshot tests that load images fromfakeimg.ryd.tools, which timed out from this machine, and they fail the same way onmain.Benchmark
2,041 layout nodes (a 40 x 50 grid, each given its first layout in its constructor). Builds of
mainand this branch alternate, with a fresh process or browser per run. Medians of per-run totals in ms; the last column counts the pairs in which this branch was faster.Chrome 154.0.8037.99 headless with a real
Applicationand Sprite cells; Node 24.16.0 (V8 13.6) without a renderer.Scripts and raw output:
https://gist.github.com/rynwhite/23a60b891eed47bdf9f0771b67800473
The Node update rows are a renderer-less micro-loop running identical code in both builds; the small gap there does not show up in Chrome frames.
Where the mount cost comes from: redefining an accessor on a prototype invalidates V8's cached property lookups for every object that inherits it. About a third of the extra mount time is inside the
definePropertycalls themselves, and redefining an unrelated accessor onContainer.prototypeonce per node reproducesmain's cost almost exactly, so the repeated redefinition is the cause.For context, the same change applied as a patch on 3.2.1 lowered mount CPU by about 15% (median -148 ms, lower in 15 of 15 paired runs) on our own stress screen (about 7,400 Pixi nodes, 2,000 with layouts, larger than a real editor), measured with a different harness.
Risk
Behaviour change: once any container has had a layout,
Container.prototypekeeps the layout-awarevisiblesetter, even after every layout is removed. Onmainthe override is already in place except between a removal and the next first layout. For a container without a layout, the setter adds onethis.layoutread to Pixi's setter.Prepared by Claude Opus 5.5 (max effort) for @rynwhite.
🤖 Generated with Claude Code