FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

perf(ios): request layout once per turn and append subviews without copying by triniwiz · Pull Request #11507 · NativeScript/NativeScript · GitHub

Repository navigation

perf(ios): request layout once per turn and append subviews without copying - #11507

Merged
NathanWalker merged 2 commits into
mainfrom
perf/ios-view-attach
Oct 6, 2026
Merged

NathanWalker merged 2 commits into
mainfrom
perf/ios-view-attach

Conversation

triniwiz commented Oct 6, 2026 •
edited
Loading

Copy link
Copy Markdown
Member

PR Checklist

What is the current behavior?

  • requestLayout on iOS climbs to the root on every call and calls setNeedsLayout at each level. CSS calls it once per layout-affecting property, so styling one view costs depth times properties native calls, all reaching ancestors that were already flagged by the first call.
  • insertNativeSubview reads subviews before checking whether an index was given. Reading it copies the array, so appending k children to one parent is O(k^2).

What is the new behavior?

  • requestLayout returns early when the view already climbed in this turn and is still flagged. A layout pass in between clears the flag, so the next request climbs again. The set of views is cleared by a microtask at the end of the turn.
  • Appends call addSubview without reading subviews.

New specs: a repeat request in the same turn does not climb (fails on main), and a request climbs again in the next turn and after a layout pass.

Numbers

Scenario (M) Painted before Painted after Attach before Attach after
flex-wrap-tiles 1155.9 987.8 551.0 390.6
grid-dashboard 292.7 256.1 143.5 112.0
insert-remove 1144.0 1004.8 541.9 396.0
nested-chain 31.7 27.0 16.1 10.3
relayout-resize 330.2 302.1 118.7 92.3
relayout-style 328.1 302.7 117.5 91.4
styled-cards 385.6 337.1 198.0 152.5
text-flow 205.6 192.8 48.5 40.8
tree-fanout 330.5 299.7 118.6 90.9
Mutation (M) Before After
restyle (relayout-style) 185.9 176.2
restore (relayout-style) 186.0 173.6
insert (insert-remove) 466.0 458.4
remove (insert-remove) 303.3 306.0
shrink (relayout-resize) 144.4 143.1
grow (relayout-resize) 144.0 142.9

How this was measured

xplat-benchmarks ns-core app (plain core, no plugins), iPhone 17 Pro Max simulator, iOS 26.4. Each scenario mounts about 1,000 views at size M. Base and change were installed alternately for 3 rounds of 10 measured iterations, median ms, lower is better. "Attach" is assigning the built tree to a loaded parent (native view creation, CSS, native setters); "painted" ends one frame after layout. A GC is forced before each mutation, as it already is after each unmount, so a collection pause lands in the same phase for both builds.

Part of a series: #11505, #11506, #11507 (this), #11510.

nx-cloud Bot commented Oct 6, 2026 •
edited
Loading

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 3d0b554

Command Status Duration Result
nx test apps-automated -c=android ✅ Succeeded 3m 24s View ↗
nx run-many --target=test --configuration=ci --... ✅ Succeeded <1s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-10-06 23:01:25 UTC

pkg-pr-new Bot commented Oct 6, 2026 •
edited
Loading

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@nativescript/core@11507
npm i https://pkg.pr.new/@nativescript/vite@11507
npm i https://pkg.pr.new/@nativescript/webpack@11507

commit: 3d0b554

Comment thread packages/core/ui/text-base/index.ios.ts Outdated
…opying

- requestLayout returns early when the view already climbed in this turn
  and is still flagged. CSS calls it once per layout-affecting property,
  so each call climbed to the root with a native setNeedsLayout at every
  level. A layout pass in between clears the flag, so the next request
  climbs again; the set is cleared by a microtask.
- insertNativeSubview calls addSubview without reading `subviews` when
  no index is given. Reading it copies the array, so appending k
  children was O(k^2).
triniwiz force-pushed the perf/ios-view-attach branch from c3fbe9f to 4fd7ff1 Compare October 6, 2026 20:27
triniwiz changed the title perf(core): cheaper view attach, and one layout request per turn on iOS perf(ios): request layout once per turn and append subviews without copying Oct 6, 2026
A synchronous layout pass (e.g. layoutIfNeeded) can lay out an ancestor and
clear its flag while skipping a collapsed child, which stays flagged. The
child's next requestLayout in the same turn was skipped, so the ancestor never
re-laid out and the child stayed hidden after becoming visible. The shortcut
now applies only while every ancestor is still flagged.
NathanWalker merged commit 3a8a213 into main Oct 6, 2026
10 checks passed
NathanWalker deleted the perf/ios-view-attach branch October 6, 2026 23:20
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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants


Back | FazBrowse Home | New Git URL