Skip to content

Skip copying the culling context in the differ when view culling is off - #59677

Open
hryhoriiK97 wants to merge 1 commit into
react:mainfrom
hryhoriiK97:differ-skip-culling-context-copies
Open

hryhoriiK97 wants to merge 1 commit into
react:mainfrom
hryhoriiK97:differ-skip-culling-context-copies

Conversation

@hryhoriiK97

Copy link
Copy Markdown
Contributor

Summary:

In its two per-child loops (slicing a node's children, and walking matched child pairs), the differ calls CullingContext::adjustCullingContextIfNeeded for every child and reads ReactNativeFeatureFlags::enableViewCulling() each time. Each call builds a ShadowViewNodePair with a copy of the child's ShadowView (props, state and event emitter shared_ptrs) and returns a new CullingContext (a Rect and a Transform with its operations vector). Without view culling, the result is always an unchanged copy of the parent's context.

View culling is off by default, so every commit pays for this on every child the differ visits. This change reads the flag once per call and, when culling is off, passes the parent's context to the children instead. With culling on, the same calls run in the same order as before. The other adjustCullingContextIfNeeded calls are in rarer paths (flattening, unflattening, deletions) and are left as they are.

I found this while profiling typing in a TextInput on Android: each keystroke commits a state update, and the differ walks the whole screen. On a low-end phone the copies were about 5% of the differ's time.

Changelog:

[GENERAL] [CHANGED] - The differ no longer copies its view culling context for every child when view culling is off

Test Plan:

  • yarn fantom with the tester rebuilt from this change:
    • ScrollView-viewCulling-itest.js (runs with enableViewCulling:true): 44 passed.
    • TextInput suites 39 passed, ScrollView suites 86 passed, Mounting-itest.js 56 passed.
    • Full suite: 3316 passed. The other failures are not related to this change: snapshot printing in my checkout's Jest setup (LogBox and expect snapshots), and the known flaky tester crash in one suite (polyfillArrayES2023Methods-itest.js), which passes on rerun.
  • clang-format clean (node scripts/clang-format.js --check).
  • On a device. RNTester release build on a Galaxy A16 (Android 16), one APK with both versions behind a local switch, typing into a TextInput on the TextInput example page for 12 s per run, call stacks sampled at 1 kHz, 5 rounds alternating old/new. JS thread samples spent in adjustCullingContextIfNeeded and the flag reads:
before this PR
per 12 s run 13 / 9 / 12 / 12 / 12 2 / 1 / 1 / 2 / 0

That is about 1.3–1.5% of the JS thread while typing (the differ itself is about 30% of it). Total differ time moves by more than that between runs, so I am not claiming more.

🤖 Generated with Claude Code

Slicing and the differ's matched-pairs loop read `enableViewCulling` and
copy a `CullingContext` (a `Rect` and a `Transform`) for every child, but
without view culling `adjustCullingContextIfNeeded` returns an unchanged
copy. Read the flag once per call and, when culling is off, pass the
parent's context to the children instead of copying it.

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 Oct 30, 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 Oct 30, 2026
@meta-codesync

meta-codesync Bot commented Oct 30, 2026

Copy link
Copy Markdown

@javache has imported this pull request. If you are a Meta employee, you can view this in D128599926.

@christophpurrer christophpurrer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review automatically exported from Phabricator review in Meta.

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.

3 participants