You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is what I noticed in many apps on the new arch. In paper architecture we created constants on UIManager thread so it didn't affect TTI however on the new arch it happens on js thread. This pr caches constants on first run (usually on onboarding and speeds up all subsequent runs.) The best solution would be to get rid of constants and just generate them at build time and put in hermes bytecode. I know that something like that is already on the roadmap but this seems to be a good temporary solution :)
Motivation: startup in bridgeless + new architecture was spending significant time in UIManager host functions (getConstants / getConstantsForViewManager) even on repeated launches.
This PR adds Android-side caching for UIManager constants and lazy view manager constants, preloads them early on app startup, and reuses them from UIConstantsProviderBinding to avoid recomputing on subsequent runs.
It also adds cache identity validation so stale cache is not reused after app/bundle changes (including OTA/file-bundle changes). Cache is only used when identity matches; otherwise it safely falls back to normal computation and refreshes cache.
Changelog:
[ANDROID] [CHANGED] - Cache and preload UIManager constants in bridgeless new architecture and invalidate cache when app/bundle identity changes.
meta-clabot
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
Mar 12, 2026
Would it make sense to cache this in JS instead? We’d also want to have a feature flag for this.
That sounds like a cleaner solution. I first use this optimisation with birdgeless off environment and then UIManager created constants in constructor. If in bridgeless the old paper UIManager is no longer created I think js would be cleaner. Let me test that and add a feature flag.
@javache
I implemented and tested JS version and got similar improvement. A bit worse as in the native one we load cache when process starts so everything is ready when we need it. The main problem I have with js approach is persistence. We don't want to make RN dependent on MMKV or other synchronous storages so we would need to implement a turbo module. Please let me know if there already is a built in solution in RN we could use :). I think keeping it on the native side can be a bit cleaner because of that but please let me know what do you think. I can hide it behind a feature flag and go native or js way depending on your response.
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
CLA SignedThis label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.Shared with MetaApplied via automation to indicate that an Issue or Pull Request has been shared with the team.
2 participants
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:
Motivation: startup in bridgeless + new architecture was spending significant time in UIManager host functions (
getConstants/getConstantsForViewManager) even on repeated launches.This PR adds Android-side caching for UIManager constants and lazy view manager constants, preloads them early on app startup, and reuses them from
UIConstantsProviderBindingto avoid recomputing on subsequent runs.It also adds cache identity validation so stale cache is not reused after app/bundle changes (including OTA/file-bundle changes). Cache is only used when identity matches; otherwise it safely falls back to normal computation and refreshes cache.
Changelog:
[ANDROID] [CHANGED] - Cache and preload UIManager constants in bridgeless new architecture and invalidate cache when app/bundle identity changes.
Test Plan:
Build/install RNTester release on device:
./gradlew :packages:rn-tester:android:app:installReleaseBUILD SUCCESSFULandInstalled on 1 device.Capture Hermes sampling profiles on release (two sequential launches, 10s window via
react-native-release-profiler):yarn workspace @react-native/tester react-native-release-profiler --fromDownload --raw --appId com.facebook.react.uiapp/Users/szymonkapala/work/react-native/.tmp/rntester-profiler-verify-20260312-214548/run1.cpuprofile.txt/Users/szymonkapala/work/react-native/.tmp/rntester-profiler-verify-20260312-214548/run2.cpuprofile.txtProfile comparison (sample-based):
getConstantsForViewManagerpresent (41samples),getConstantspresent (1sample).getConstantsForViewManager0samples,getConstants0samples.This verifies first-run population + second-run reuse behavior with the new cache identity checks.