diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java index 732884763708..5075a22a411c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java @@ -21,6 +21,7 @@ import com.facebook.react.bridge.ReactNoCrashSoftException; import com.facebook.react.bridge.ReactSoftExceptionLogger; import com.facebook.react.bridge.RetryableMountingLayerException; +import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.fabric.mounting.mountitems.DispatchCommandMountItem; import com.facebook.react.fabric.mounting.mountitems.MountItem; import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags; @@ -54,6 +55,21 @@ public class MountItemDispatcher { private long mBatchedExecutionTime = 0L; private long mRunStartTime = 0L; + private long mLastFrameTimeNanos = 0L; + private boolean mIsPremountScheduled = false; + private final Runnable mPremountRunnable = + () -> { + mIsPremountScheduled = false; + + if (mPreMountItems.isEmpty()) { + // Avoid starting systrace if there are no pre mount items. + return; + } + + long deadline = mLastFrameTimeNanos + (FRAME_TIME_NS / 2); + dispatchPreMountItemsImpl(deadline); + }; + public MountItemDispatcher(MountingManager mountingManager, ItemDispatchListener listener) { mMountingManager = mountingManager; mItemDispatchListener = listener; @@ -338,11 +354,25 @@ private boolean dispatchMountItems() { @UiThread @ThreadConfined(UI) public void dispatchPreMountItems(long frameTimeNanos) { + mLastFrameTimeNanos = frameTimeNanos; + if (mPreMountItems.isEmpty()) { // Avoid starting systrace if there are no pre mount items. return; } + if (ReactNativeFeatureFlags.enablePreciseSchedulingForPremountItemsOnAndroid()) { + if (!mIsPremountScheduled) { + mIsPremountScheduled = true; + UiThreadUtil.getUiThreadHandler().post(mPremountRunnable); + } + } else { + long deadline = mLastFrameTimeNanos + FRAME_TIME_NS / 2; + dispatchPreMountItemsImpl(deadline); + } + } + + private void dispatchPreMountItemsImpl(long deadline) { Systrace.beginSection( Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "MountItemDispatcher::premountViews"); @@ -350,10 +380,9 @@ public void dispatchPreMountItems(long frameTimeNanos) { // reentering during dispatchPreMountItems mInDispatch = true; - long frameTimeDeadline = frameTimeNanos + FRAME_TIME_NS / 2; try { while (true) { - if (System.nanoTime() > frameTimeDeadline) { + if (System.nanoTime() > deadline) { break; } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index 36c1dfb8c612..5784404f29fa 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<60fcb02736ca814a842225291e3a55b1>> + * @generated SignedSource<<73409b567e77f17838ae9681a8e20be6>> */ /** @@ -148,6 +148,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun enableMicrotasks(): Boolean = accessor.enableMicrotasks() + /** + * Moves execution of pre-mount items to outside the choregrapher in the main thread, so we can estimate idle time more precisely (Android only). + */ + @JvmStatic + public fun enablePreciseSchedulingForPremountItemsOnAndroid(): Boolean = accessor.enablePreciseSchedulingForPremountItemsOnAndroid() + /** * When enabled, Android will receive prop updates based on the differences between the last rendered shadow node and the last committed shadow node. */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index d45e432c70b5..f851574f87c9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<9f2978b5a732a3ca4f3c3d74debba782>> */ /** @@ -40,6 +40,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso private var enableLayoutAnimationsOnIOSCache: Boolean? = null private var enableLongTaskAPICache: Boolean? = null private var enableMicrotasksCache: Boolean? = null + private var enablePreciseSchedulingForPremountItemsOnAndroidCache: Boolean? = null private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null private var enableReportEventPaintTimeCache: Boolean? = null private var enableSynchronousStateUpdatesCache: Boolean? = null @@ -251,6 +252,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun enablePreciseSchedulingForPremountItemsOnAndroid(): Boolean { + var cached = enablePreciseSchedulingForPremountItemsOnAndroidCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.enablePreciseSchedulingForPremountItemsOnAndroid() + enablePreciseSchedulingForPremountItemsOnAndroidCache = cached + } + return cached + } + override fun enablePropsUpdateReconciliationAndroid(): Boolean { var cached = enablePropsUpdateReconciliationAndroidCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index 8cbae2ba7c24..89950a0f986e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<03618f182004add50655a88e6e65e96d>> + * @generated SignedSource<<0d2f5427661ce67e468aea47bdd29802>> */ /** @@ -68,6 +68,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun enableMicrotasks(): Boolean + @DoNotStrip @JvmStatic public external fun enablePreciseSchedulingForPremountItemsOnAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun enablePropsUpdateReconciliationAndroid(): Boolean @DoNotStrip @JvmStatic public external fun enableReportEventPaintTime(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index 712e8919b792..83264bfcf22e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<72e3e7b5a53e64f8f48310d8b07cdf76>> */ /** @@ -63,6 +63,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun enableMicrotasks(): Boolean = false + override fun enablePreciseSchedulingForPremountItemsOnAndroid(): Boolean = false + override fun enablePropsUpdateReconciliationAndroid(): Boolean = false override fun enableReportEventPaintTime(): Boolean = false diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index 099a9ae121ba..119d2f0b8cf0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<0dbb1f1a08649132955698ac51050e62>> + * @generated SignedSource<> */ /** @@ -44,6 +44,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private var enableLayoutAnimationsOnIOSCache: Boolean? = null private var enableLongTaskAPICache: Boolean? = null private var enableMicrotasksCache: Boolean? = null + private var enablePreciseSchedulingForPremountItemsOnAndroidCache: Boolean? = null private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null private var enableReportEventPaintTimeCache: Boolean? = null private var enableSynchronousStateUpdatesCache: Boolean? = null @@ -275,6 +276,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun enablePreciseSchedulingForPremountItemsOnAndroid(): Boolean { + var cached = enablePreciseSchedulingForPremountItemsOnAndroidCache + if (cached == null) { + cached = currentProvider.enablePreciseSchedulingForPremountItemsOnAndroid() + accessedFeatureFlags.add("enablePreciseSchedulingForPremountItemsOnAndroid") + enablePreciseSchedulingForPremountItemsOnAndroidCache = cached + } + return cached + } + override fun enablePropsUpdateReconciliationAndroid(): Boolean { var cached = enablePropsUpdateReconciliationAndroidCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index 35fef93bc868..c3eb8fbe97c4 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<79cd9812257f42d553b49a3f6d3d4989>> + * @generated SignedSource<<0f6129ccbcf7857785724f14b41edb2d>> */ /** @@ -63,6 +63,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun enableMicrotasks(): Boolean + @DoNotStrip public fun enablePreciseSchedulingForPremountItemsOnAndroid(): Boolean + @DoNotStrip public fun enablePropsUpdateReconciliationAndroid(): Boolean @DoNotStrip public fun enableReportEventPaintTime(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index 4beafbe1177b..326213c7d46a 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<9e891a5d26221136d7334982fc2e99d3>> + * @generated SignedSource<<43b92dd984e985e09e3efad9c8fedf44>> */ /** @@ -159,6 +159,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool enablePreciseSchedulingForPremountItemsOnAndroid() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enablePreciseSchedulingForPremountItemsOnAndroid"); + return method(javaProvider_); + } + bool enablePropsUpdateReconciliationAndroid() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enablePropsUpdateReconciliationAndroid"); @@ -443,6 +449,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableMicrotasks( return ReactNativeFeatureFlags::enableMicrotasks(); } +bool JReactNativeFeatureFlagsCxxInterop::enablePreciseSchedulingForPremountItemsOnAndroid( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::enablePreciseSchedulingForPremountItemsOnAndroid(); +} + bool JReactNativeFeatureFlagsCxxInterop::enablePropsUpdateReconciliationAndroid( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::enablePropsUpdateReconciliationAndroid(); @@ -670,6 +681,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "enableMicrotasks", JReactNativeFeatureFlagsCxxInterop::enableMicrotasks), + makeNativeMethod( + "enablePreciseSchedulingForPremountItemsOnAndroid", + JReactNativeFeatureFlagsCxxInterop::enablePreciseSchedulingForPremountItemsOnAndroid), makeNativeMethod( "enablePropsUpdateReconciliationAndroid", JReactNativeFeatureFlagsCxxInterop::enablePropsUpdateReconciliationAndroid), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index 4bc95edb2d6f..02bb54491bec 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<70edc4176da74aed5eaa1561a907a7ee>> + * @generated SignedSource<<54c94f9bfa07e41d978899dbce03469f>> */ /** @@ -90,6 +90,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool enableMicrotasks( facebook::jni::alias_ref); + static bool enablePreciseSchedulingForPremountItemsOnAndroid( + facebook::jni::alias_ref); + static bool enablePropsUpdateReconciliationAndroid( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index a088e4b628fd..15b4f233ca2c 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<80b130f32b0bc59b9a9605777537feeb>> + * @generated SignedSource<> */ /** @@ -101,6 +101,10 @@ bool ReactNativeFeatureFlags::enableMicrotasks() { return getAccessor().enableMicrotasks(); } +bool ReactNativeFeatureFlags::enablePreciseSchedulingForPremountItemsOnAndroid() { + return getAccessor().enablePreciseSchedulingForPremountItemsOnAndroid(); +} + bool ReactNativeFeatureFlags::enablePropsUpdateReconciliationAndroid() { return getAccessor().enablePropsUpdateReconciliationAndroid(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index a169c62b74b1..646a250ad70c 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<3b5ff29faaf1575c051131bdf24a3237>> + * @generated SignedSource<<2cde82b474ab94cd05bdf5e04e700c13>> */ /** @@ -137,6 +137,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool enableMicrotasks(); + /** + * Moves execution of pre-mount items to outside the choregrapher in the main thread, so we can estimate idle time more precisely (Android only). + */ + RN_EXPORT static bool enablePreciseSchedulingForPremountItemsOnAndroid(); + /** * When enabled, Android will receive prop updates based on the differences between the last rendered shadow node and the last committed shadow node. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 5932d2a9b927..5fa57e0f6156 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<4e91fe2df3304f2aa03b41dcbf4a7599>> + * @generated SignedSource<> */ /** @@ -389,6 +389,24 @@ bool ReactNativeFeatureFlagsAccessor::enableMicrotasks() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::enablePreciseSchedulingForPremountItemsOnAndroid() { + auto flagValue = enablePreciseSchedulingForPremountItemsOnAndroid_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(20, "enablePreciseSchedulingForPremountItemsOnAndroid"); + + flagValue = currentProvider_->enablePreciseSchedulingForPremountItemsOnAndroid(); + enablePreciseSchedulingForPremountItemsOnAndroid_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::enablePropsUpdateReconciliationAndroid() { auto flagValue = enablePropsUpdateReconciliationAndroid_.load(); @@ -398,7 +416,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePropsUpdateReconciliationAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(20, "enablePropsUpdateReconciliationAndroid"); + markFlagAsAccessed(21, "enablePropsUpdateReconciliationAndroid"); flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid(); enablePropsUpdateReconciliationAndroid_ = flagValue; @@ -416,7 +434,7 @@ bool ReactNativeFeatureFlagsAccessor::enableReportEventPaintTime() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(21, "enableReportEventPaintTime"); + markFlagAsAccessed(22, "enableReportEventPaintTime"); flagValue = currentProvider_->enableReportEventPaintTime(); enableReportEventPaintTime_ = flagValue; @@ -434,7 +452,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSynchronousStateUpdates() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(22, "enableSynchronousStateUpdates"); + markFlagAsAccessed(23, "enableSynchronousStateUpdates"); flagValue = currentProvider_->enableSynchronousStateUpdates(); enableSynchronousStateUpdates_ = flagValue; @@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::enableTextPreallocationOptimisation() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(23, "enableTextPreallocationOptimisation"); + markFlagAsAccessed(24, "enableTextPreallocationOptimisation"); flagValue = currentProvider_->enableTextPreallocationOptimisation(); enableTextPreallocationOptimisation_ = flagValue; @@ -470,7 +488,7 @@ bool ReactNativeFeatureFlagsAccessor::enableUIConsistency() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(24, "enableUIConsistency"); + markFlagAsAccessed(25, "enableUIConsistency"); flagValue = currentProvider_->enableUIConsistency(); enableUIConsistency_ = flagValue; @@ -488,7 +506,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecycling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(25, "enableViewRecycling"); + markFlagAsAccessed(26, "enableViewRecycling"); flagValue = currentProvider_->enableViewRecycling(); enableViewRecycling_ = flagValue; @@ -506,7 +524,7 @@ bool ReactNativeFeatureFlagsAccessor::excludeYogaFromRawProps() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(26, "excludeYogaFromRawProps"); + markFlagAsAccessed(27, "excludeYogaFromRawProps"); flagValue = currentProvider_->excludeYogaFromRawProps(); excludeYogaFromRawProps_ = flagValue; @@ -524,7 +542,7 @@ bool ReactNativeFeatureFlagsAccessor::fetchImagesInViewPreallocation() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(27, "fetchImagesInViewPreallocation"); + markFlagAsAccessed(28, "fetchImagesInViewPreallocation"); flagValue = currentProvider_->fetchImagesInViewPreallocation(); fetchImagesInViewPreallocation_ = flagValue; @@ -542,7 +560,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(28, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); + markFlagAsAccessed(29, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact(); fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue; @@ -560,7 +578,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMountingCoordinatorReportedPendingTrans // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(29, "fixMountingCoordinatorReportedPendingTransactionsOnAndroid"); + markFlagAsAccessed(30, "fixMountingCoordinatorReportedPendingTransactionsOnAndroid"); flagValue = currentProvider_->fixMountingCoordinatorReportedPendingTransactionsOnAndroid(); fixMountingCoordinatorReportedPendingTransactionsOnAndroid_ = flagValue; @@ -578,7 +596,7 @@ bool ReactNativeFeatureFlagsAccessor::forceBatchingMountItemsOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(30, "forceBatchingMountItemsOnAndroid"); + markFlagAsAccessed(31, "forceBatchingMountItemsOnAndroid"); flagValue = currentProvider_->forceBatchingMountItemsOnAndroid(); forceBatchingMountItemsOnAndroid_ = flagValue; @@ -596,7 +614,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledDebug() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(31, "fuseboxEnabledDebug"); + markFlagAsAccessed(32, "fuseboxEnabledDebug"); flagValue = currentProvider_->fuseboxEnabledDebug(); fuseboxEnabledDebug_ = flagValue; @@ -614,7 +632,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(32, "fuseboxEnabledRelease"); + markFlagAsAccessed(33, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -632,7 +650,7 @@ bool ReactNativeFeatureFlagsAccessor::initEagerTurboModulesOnNativeModulesQueueA // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(33, "initEagerTurboModulesOnNativeModulesQueueAndroid"); + markFlagAsAccessed(34, "initEagerTurboModulesOnNativeModulesQueueAndroid"); flagValue = currentProvider_->initEagerTurboModulesOnNativeModulesQueueAndroid(); initEagerTurboModulesOnNativeModulesQueueAndroid_ = flagValue; @@ -650,7 +668,7 @@ bool ReactNativeFeatureFlagsAccessor::lazyAnimationCallbacks() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(34, "lazyAnimationCallbacks"); + markFlagAsAccessed(35, "lazyAnimationCallbacks"); flagValue = currentProvider_->lazyAnimationCallbacks(); lazyAnimationCallbacks_ = flagValue; @@ -668,7 +686,7 @@ bool ReactNativeFeatureFlagsAccessor::loadVectorDrawablesOnImages() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(35, "loadVectorDrawablesOnImages"); + markFlagAsAccessed(36, "loadVectorDrawablesOnImages"); flagValue = currentProvider_->loadVectorDrawablesOnImages(); loadVectorDrawablesOnImages_ = flagValue; @@ -686,7 +704,7 @@ bool ReactNativeFeatureFlagsAccessor::removeNestedCallsToDispatchMountItemsOnAnd // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(36, "removeNestedCallsToDispatchMountItemsOnAndroid"); + markFlagAsAccessed(37, "removeNestedCallsToDispatchMountItemsOnAndroid"); flagValue = currentProvider_->removeNestedCallsToDispatchMountItemsOnAndroid(); removeNestedCallsToDispatchMountItemsOnAndroid_ = flagValue; @@ -704,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::setAndroidLayoutDirection() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(37, "setAndroidLayoutDirection"); + markFlagAsAccessed(38, "setAndroidLayoutDirection"); flagValue = currentProvider_->setAndroidLayoutDirection(); setAndroidLayoutDirection_ = flagValue; @@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(38, "traceTurboModulePromiseRejectionsOnAndroid"); + markFlagAsAccessed(39, "traceTurboModulePromiseRejectionsOnAndroid"); flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid(); traceTurboModulePromiseRejectionsOnAndroid_ = flagValue; @@ -740,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(39, "useFabricInterop"); + markFlagAsAccessed(40, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -758,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::useImmediateExecutorInAndroidBridgeless() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(40, "useImmediateExecutorInAndroidBridgeless"); + markFlagAsAccessed(41, "useImmediateExecutorInAndroidBridgeless"); flagValue = currentProvider_->useImmediateExecutorInAndroidBridgeless(); useImmediateExecutorInAndroidBridgeless_ = flagValue; @@ -776,7 +794,7 @@ bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(41, "useModernRuntimeScheduler"); + markFlagAsAccessed(42, "useModernRuntimeScheduler"); flagValue = currentProvider_->useModernRuntimeScheduler(); useModernRuntimeScheduler_ = flagValue; @@ -794,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(42, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(43, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -812,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::useNewReactImageViewBackgroundDrawing() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(43, "useNewReactImageViewBackgroundDrawing"); + markFlagAsAccessed(44, "useNewReactImageViewBackgroundDrawing"); flagValue = currentProvider_->useNewReactImageViewBackgroundDrawing(); useNewReactImageViewBackgroundDrawing_ = flagValue; @@ -830,7 +848,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimisedViewPreallocationOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(44, "useOptimisedViewPreallocationOnAndroid"); + markFlagAsAccessed(45, "useOptimisedViewPreallocationOnAndroid"); flagValue = currentProvider_->useOptimisedViewPreallocationOnAndroid(); useOptimisedViewPreallocationOnAndroid_ = flagValue; @@ -848,7 +866,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(45, "useOptimizedEventBatchingOnAndroid"); + markFlagAsAccessed(46, "useOptimizedEventBatchingOnAndroid"); flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid(); useOptimizedEventBatchingOnAndroid_ = flagValue; @@ -866,7 +884,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdate() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(46, "useRuntimeShadowNodeReferenceUpdate"); + markFlagAsAccessed(47, "useRuntimeShadowNodeReferenceUpdate"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdate(); useRuntimeShadowNodeReferenceUpdate_ = flagValue; @@ -884,7 +902,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdateOnLayou // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(47, "useRuntimeShadowNodeReferenceUpdateOnLayout"); + markFlagAsAccessed(48, "useRuntimeShadowNodeReferenceUpdateOnLayout"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdateOnLayout(); useRuntimeShadowNodeReferenceUpdateOnLayout_ = flagValue; @@ -902,7 +920,7 @@ bool ReactNativeFeatureFlagsAccessor::useStateAlignmentMechanism() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(48, "useStateAlignmentMechanism"); + markFlagAsAccessed(49, "useStateAlignmentMechanism"); flagValue = currentProvider_->useStateAlignmentMechanism(); useStateAlignmentMechanism_ = flagValue; @@ -920,7 +938,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(49, "useTurboModuleInterop"); + markFlagAsAccessed(50, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 819a18a46e0d..bb5798df4dd8 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<3273d68bcf8118b939e11dde654c3e34>> */ /** @@ -51,6 +51,7 @@ class ReactNativeFeatureFlagsAccessor { bool enableLayoutAnimationsOnIOS(); bool enableLongTaskAPI(); bool enableMicrotasks(); + bool enablePreciseSchedulingForPremountItemsOnAndroid(); bool enablePropsUpdateReconciliationAndroid(); bool enableReportEventPaintTime(); bool enableSynchronousStateUpdates(); @@ -91,7 +92,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 50> accessedFeatureFlags_; + std::array, 51> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> allowRecursiveCommitsWithSynchronousMountOnAndroid_; @@ -113,6 +114,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> enableLayoutAnimationsOnIOS_; std::atomic> enableLongTaskAPI_; std::atomic> enableMicrotasks_; + std::atomic> enablePreciseSchedulingForPremountItemsOnAndroid_; std::atomic> enablePropsUpdateReconciliationAndroid_; std::atomic> enableReportEventPaintTime_; std::atomic> enableSynchronousStateUpdates_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 118926799e8e..9c9bd460a441 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<3ba99bf8dd5f7e146e3488dbc8bc59c8>> */ /** @@ -107,6 +107,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool enablePreciseSchedulingForPremountItemsOnAndroid() override { + return false; + } + bool enablePropsUpdateReconciliationAndroid() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 859bffe5631e..4e94bf6a34ff 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<43f360d769690622252f3051f71e78ab>> + * @generated SignedSource<<727c5ccb59b23aa6e14d58121e0007bd>> */ /** @@ -45,6 +45,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool enableLayoutAnimationsOnIOS() = 0; virtual bool enableLongTaskAPI() = 0; virtual bool enableMicrotasks() = 0; + virtual bool enablePreciseSchedulingForPremountItemsOnAndroid() = 0; virtual bool enablePropsUpdateReconciliationAndroid() = 0; virtual bool enableReportEventPaintTime() = 0; virtual bool enableSynchronousStateUpdates() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index f2d3fc3adcff..b0450475b28e 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<7df4018785f9aefb615b8671abf71454>> + * @generated SignedSource<> */ /** @@ -137,6 +137,11 @@ bool NativeReactNativeFeatureFlags::enableMicrotasks( return ReactNativeFeatureFlags::enableMicrotasks(); } +bool NativeReactNativeFeatureFlags::enablePreciseSchedulingForPremountItemsOnAndroid( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::enablePreciseSchedulingForPremountItemsOnAndroid(); +} + bool NativeReactNativeFeatureFlags::enablePropsUpdateReconciliationAndroid( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::enablePropsUpdateReconciliationAndroid(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 84c154b4ab27..7bbe7c3df819 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<4404c58578548e8dcb909fb9c6629d44>> + * @generated SignedSource<<596ec10892f79595c352d27574a0c5a3>> */ /** @@ -75,6 +75,8 @@ class NativeReactNativeFeatureFlags bool enableMicrotasks(jsi::Runtime& runtime); + bool enablePreciseSchedulingForPremountItemsOnAndroid(jsi::Runtime& runtime); + bool enablePropsUpdateReconciliationAndroid(jsi::Runtime& runtime); bool enableReportEventPaintTime(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index ee67559c0f22..fb4ef2284803 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -130,6 +130,11 @@ const definitions: FeatureFlagDefinitions = { description: 'Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution).', }, + enablePreciseSchedulingForPremountItemsOnAndroid: { + defaultValue: false, + description: + 'Moves execution of pre-mount items to outside the choregrapher in the main thread, so we can estimate idle time more precisely (Android only).', + }, enablePropsUpdateReconciliationAndroid: { defaultValue: false, description: diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 396a2c1b05a6..dc67d6081e0c 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<0bc6eb9982c84fc359957413cc26dd12>> + * @generated SignedSource<<79bdedd5a09ba284cdaa2e4f40ffd2fd>> * @flow strict */ @@ -68,6 +68,7 @@ export type ReactNativeFeatureFlags = { enableLayoutAnimationsOnIOS: Getter, enableLongTaskAPI: Getter, enableMicrotasks: Getter, + enablePreciseSchedulingForPremountItemsOnAndroid: Getter, enablePropsUpdateReconciliationAndroid: Getter, enableReportEventPaintTime: Getter, enableSynchronousStateUpdates: Getter, @@ -255,6 +256,10 @@ export const enableLongTaskAPI: Getter = createNativeFlagGetter('enable * Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution). */ export const enableMicrotasks: Getter = createNativeFlagGetter('enableMicrotasks', false); +/** + * Moves execution of pre-mount items to outside the choregrapher in the main thread, so we can estimate idle time more precisely (Android only). + */ +export const enablePreciseSchedulingForPremountItemsOnAndroid: Getter = createNativeFlagGetter('enablePreciseSchedulingForPremountItemsOnAndroid', false); /** * When enabled, Android will receive prop updates based on the differences between the last rendered shadow node and the last committed shadow node. */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index 8832b8de6eec..7111c3dd041a 100644 --- a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<039fde6acab2250f771634a7c350bbb7>> + * @generated SignedSource<> * @flow strict */ @@ -43,6 +43,7 @@ export interface Spec extends TurboModule { +enableLayoutAnimationsOnIOS?: () => boolean; +enableLongTaskAPI?: () => boolean; +enableMicrotasks?: () => boolean; + +enablePreciseSchedulingForPremountItemsOnAndroid?: () => boolean; +enablePropsUpdateReconciliationAndroid?: () => boolean; +enableReportEventPaintTime?: () => boolean; +enableSynchronousStateUpdates?: () => boolean;