Skip to content

Compute the content bounds only of nodes whose children changed - #59999

Open
hryhoriiK97 wants to merge 1 commit into
react:mainfrom
hryhoriiK97:yoga-skip-unchanged-content-bounds
Open

hryhoriiK97 wants to merge 1 commit into
react:mainfrom
hryhoriiK97:yoga-skip-unchanged-content-bounds

Conversation

@hryhoriiK97

@hryhoriiK97 hryhoriiK97 commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Summary:

After each layout, YogaLayoutableShadowNode::layout() computes overflowInset for every node with a new layout, by walking all its children in getContentBounds(). Yoga also sets hasNewLayout on nodes whose layout comes from its cache, without laying out their children again. So when one row changes in a ScrollView with 500 rows, all rows are walked again: about 506 getContentBounds() calls over 2,000 children per commit.

Behind a new flag, skipUnchangedOverflowInsetInLayout (off by default), a node keeps the overflowInset of its previous revision unless a child has a new layout or its props or children changed. A new member, overflowInsetNeedsUpdate_, tracks the second case. Clones inherit it like yogaTreeHasBeenConfigured_, and appendChild and replaceChild set it (except for Yoga's clone-on-write copies). The root of a layout always recomputes. ScrollViewShadowNode also sets it when it moves right-to-left content after its own layout, so the member is protected and the C++ API snapshots have one new line.

The result is the same as before: a size change makes Yoga lay out all children again, and any other change to a child gives it a new layout or a new props object or children list. When Yoga sets hasNewLayout doesn't change, so onLayout is unaffected.

Changelog:

[INTERNAL] [ADDED] - Feature flag skipUnchangedOverflowInsetInLayout, to skip computing the overflow insets of nodes whose children didn't change

Test Plan:

  • New OverflowInsetTest, run with the flag off and on. It commits eight changes one after another and compares every node with a tree built from scratch, and it covers the right-to-left ScrollView case. All 107 tests in components/view/tests pass. Without the new member, or without the ScrollViewShadowNode line, the tests fail with the flag on.
  • Fantom: 17 suites that use layout, hit testing or scrolling pass (1,121 tests), with the skipping always on.
  • On an iPhone 15 Pro and an OPPO CPH2269 (Android 11), a temporary build that computed overflowInset both ways found no difference in 13 scenario runs.
  • Release RNTester, one binary per platform with the flag switched at runtime, flag off and on in A/B/B/A order, twice. Time per layout pass, median of 4:
Scenario Phone Flag off Flag on
500 rows in a ScrollView, one row changes every 250 ms OPPO CPH2269 10,164 µs 7,528 µs (−26%)
iPhone 15 Pro 1,954 µs 1,061 µs (−46%)
The same, color-only change OPPO CPH2269 8,215 µs 6,118 µs (−26%)
iPhone 15 Pro 1,563 µs 1,015 µs (−35%)
200 rows with overflowing children iPhone 15 Pro 844 µs 491 µs (−42%)
Scrolling an inverted chat FlatList iPhone 15 Pro 4,142 µs 4,097 µs

Not run: yarn cxx-api-validate (no Doxygen here), so the snapshot line was added by hand.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Nov 13, 2026
@facebook-github-tools facebook-github-tools Bot added p: Software Mansion Partner: Software Mansion Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. labels Nov 13, 2026
@hryhoriiK97

hryhoriiK97 commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor Author

@javache when you have a moment, I'd like your opinion on the approach before going further. A node keeps its previous overflowInset behind a feature flag, and ScrollViewShadowNode sets the protected flag when it moves right-to-left content after its own layout. Are you okay with subclasses doing that, or would you prefer another way, like a virtual method? I'm happy to change it.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Software Mansion Partner: Software Mansion Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant