Repository navigation
gpui: lay out with Taffy 0.14, whose cache keeps clean subtrees laid out - #49
Merged
Merged
Conversation
Taffy 0.13 keeps one cached size per kind of constraint, so a node measured under two widths in one layout evicts one with the other. A single dirty node then lays out every clean subtree around it again, on every frame: in gpui_perf's settings-toggle, eight dirty nodes out of 1203 cost ~2950 measure calls and 3.3 ms of layout. Taffy 0.14 keeps nine sizes per node whatever their kind. 0.14 hands a leaf's measure function its whole layout; fast::layout's MeasuredTaffy lays each leaf out around GPUI's measurement as 0.13 did, so taffy.rs only changes the tree it lays out through.
trancong12102
added a commit
to aislopware/gpui-fast
that referenced
this pull request
Oct 9, 2026
Takes longbridge#44 (chat transcript lists stay composited on their scroll layers), longbridge#46 (layout panics and stale rendering in view splices), longbridge#47 (caret sibling requirements in releases) and longbridge#49 (Taffy 0.14 with MeasuredTaffy). Leaves out longbridge#41, longbridge#42 and longbridge#43, upstream's window composition for X11 and wgpu, as the fork keeps its own composition (as in ed16b23). Conflicts: - Cargo.lock: ours, re-resolved for taffy 0.14 (no gtk/wry). - docs/upstream-sync.md: ours plus upstream's Taffy 0.14 entry; the composition entry stays out. - gpui_perf/Cargo.toml: ours (no linux_webview, no webview deps). - gpui_perf/src/runner.rs: both scroll scenario lists. - gpui_macos/src/fast/composition.rs, gpui_linux x11/window.rs and client.rs, the three composition.rs files, README, ci.yml: ours. - fast/dependencies.rs: ours (interned, sorted states, Checked) with longbridge#44's shared read logs and dependencies_so_far, its states interned as ours. - fast/layers/invalidate.rs: longbridge#44's OwnerChange and render_dependencies; with_own_rebuild keeps our rebuild ranges and note_rebuild guard and falls back on longbridge#44's rendering_since. - fast/layers/lists.rs: both row fields (fades, reads); our row scene insertion; drawn_alike over fast::scene::operations. - fast/layout.rs: both retention fields (root_phases; pending_replays, list_rows). - fast/layout_key.rs: longbridge#44's list row hooks with our fast_retention(). - fast/retained.rs: both state fields; note_rebuild and note_rendering both called; recording.rendered before our place_root. - fast/splice.rs: ours (splice_gaps, deferred_out_of_date, kept_layout, Checked) with longbridge#46's layout_reaches guard and offset-read checks for the view, its gaps and its deferred draws; render_dependencies copied. - fast/tests/retained.rs: both sides' tests. - fast/tests/layers_lists.rs: our outside-write test now checks the frame draws as without layers (under longbridge#44 the rows render again on a composited frame instead of demoting). - gpui_perf chat.rs: momentum_phase for our ScrollWheelEvent. cargo test -p gpui --features test-support --lib: 764 passed. gpui_perf --headless --verify: 72 checks identical. settings-toggle (retained): 61.75M -> 23.60M instructions per frame, 1735 -> 25 measure calls, layout 4.2 ms -> 1.5 ms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
What
Lay out with Taffy 0.14 instead of 0.13.
Taffy 0.13 caches one size per node per kind of constraint (e.g. "width known, height not"). When a node is measured under two different widths in one layout, the second evicts the first, and on the next frame both miss again. So a single dirty node makes Taffy lay out every clean subtree around it again, on every frame. In
gpui_perf'ssettings-toggle, 8 dirty nodes out of 1203 cost ~2950 measure calls, ~27k cache misses and 3.3 ms of layout per frame. gpui-fast's retained layout already keeps nodes clean; this lets their caches actually hit. Taffy 0.14 keeps nine sizes per node, evicting the least recently used.0.14 hands a leaf's measure function its whole layout.
fast::layout::MeasuredTaffylays each leaf out around GPUI's measurement as 0.13 did, sotaffy.rschanges one line.docs/upstream-sync.mdrecords the difference from upstream (still on 0.13).Correctness
cargo test -p gpui --features test-support --lib: 641 passed.gpui_perf --headless --verify: all 55 checks identical.script/check-upstream: 0 violations.Performance
Headless, main-thread instructions per frame, retained views on:
Real window (showcase
--auto, median of 3 alternating runs): Taffy's share of the workspace scenarios drops by ~40% (e.g. 0.34 → 0.20 ms). A settings page of 80 row views, measured in a real window with a temporary showcase page that is not part of this PR, went from 7–8 ms to 3–4 ms of main-thread CPU per frame (layout 5–6.5 ms → 2–2.4 ms).🤖 Generated with Claude Code