From d055efd4deb4cde7f3599049cb5e27c268cb7c81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Thu, 29 Aug 2024 20:57:25 -0700 Subject: [PATCH] Implement optimized event batching on Android (#46270) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/46270 Changelog: [internal] When analyzing traces, I noticed that we were using the choreographer to batch events in the native layer on Android. This approach isn't very efficient for 2 reasons: 1. The choreographer runs in specific intervals and there could be some delay between receiving the events and dispatching them from the choreographer. 2. A slow mount operation in the choreographer after receiving the event would completely block the dispatch for the whole duration of the operation. This could take as long as 100s of ms, so it can be very significant. This is especially relevant with layout events, which are dispatched using the same mechanism as input events. In this case, there are instances where we delay rendering in JS because we're doing an expensive mount in the UI thread. It makes sense to batch events in native so we don't do unnecessary work in JS to process them, but there's a better mechanism to do this. Instead of posting a frame callback in the choreographer, we can batch events using a new task in an Android handler running on the UI thread. This would run immediately after the job where the events are dispatched, after all the events are dispatched. This implements that mechanism behind a feature flag. Reviewed By: sammy-SC Differential Revision: D62004018 fbshipit-source-id: d8b78a75cf05d0d8c9dd867a82a776f8d293a683 --- .../featureflags/ReactNativeFeatureFlags.kt | 8 +++- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 +++++- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 +- .../ReactNativeFeatureFlagsDefaults.kt | 4 +- .../ReactNativeFeatureFlagsLocalAccessor.kt | 13 ++++++- .../ReactNativeFeatureFlagsProvider.kt | 4 +- .../events/FabricEventDispatcher.java | 39 ++++++++++++++++++- .../JReactNativeFeatureFlagsCxxInterop.cpp | 16 +++++++- .../JReactNativeFeatureFlagsCxxInterop.h | 5 ++- .../featureflags/ReactNativeFeatureFlags.cpp | 6 ++- .../featureflags/ReactNativeFeatureFlags.h | 7 +++- .../ReactNativeFeatureFlagsAccessor.cpp | 28 ++++++++++--- .../ReactNativeFeatureFlagsAccessor.h | 6 ++- .../ReactNativeFeatureFlagsDefaults.h | 6 ++- .../ReactNativeFeatureFlagsProvider.h | 3 +- .../NativeReactNativeFeatureFlags.cpp | 7 +++- .../NativeReactNativeFeatureFlags.h | 4 +- .../ReactNativeFeatureFlags.config.js | 5 +++ .../featureflags/ReactNativeFeatureFlags.js | 7 +++- .../specs/NativeReactNativeFeatureFlags.js | 3 +- 20 files changed, 162 insertions(+), 25 deletions(-) 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 c9e5e731a7b..ee53e7efa48 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<> + * @generated SignedSource<> */ /** @@ -280,6 +280,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun useOptimisedViewPreallocationOnAndroid(): Boolean = accessor.useOptimisedViewPreallocationOnAndroid() + /** + * Uses an optimized mechanism for event batching on Android that does not need to wait for a Choreographer frame callback. + */ + @JvmStatic + public fun useOptimizedEventBatchingOnAndroid(): Boolean = accessor.useOptimizedEventBatchingOnAndroid() + /** * When enabled, cloning shadow nodes within react native will update the reference held by the current JS fiber tree. */ 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 e00a8b17117..9ef2ffa78f3 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<<47dbdb6ffcd04bb7b2d2d01c4c1e7ace>> */ /** @@ -62,6 +62,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null private var useNewReactImageViewBackgroundDrawingCache: Boolean? = null private var useOptimisedViewPreallocationOnAndroidCache: Boolean? = null + private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null private var useRuntimeShadowNodeReferenceUpdateCache: Boolean? = null private var useRuntimeShadowNodeReferenceUpdateOnLayoutCache: Boolean? = null private var useStateAlignmentMechanismCache: Boolean? = null @@ -445,6 +446,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun useOptimizedEventBatchingOnAndroid(): Boolean { + var cached = useOptimizedEventBatchingOnAndroidCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.useOptimizedEventBatchingOnAndroid() + useOptimizedEventBatchingOnAndroidCache = cached + } + return cached + } + override fun useRuntimeShadowNodeReferenceUpdate(): Boolean { var cached = useRuntimeShadowNodeReferenceUpdateCache 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 d221e1420b8..949027d4897 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<<580db8acae42a65aeb678d2d6ef4630c>> + * @generated SignedSource<<93ce8e0026e125192af1ad86730941c0>> */ /** @@ -112,6 +112,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun useOptimisedViewPreallocationOnAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun useOptimizedEventBatchingOnAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun useRuntimeShadowNodeReferenceUpdate(): Boolean @DoNotStrip @JvmStatic public external fun useRuntimeShadowNodeReferenceUpdateOnLayout(): 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 f537181cd65..a1c8ff270e4 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<<00aae631e9d9b146fae9be838e04e165>> + * @generated SignedSource<> */ /** @@ -107,6 +107,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun useOptimisedViewPreallocationOnAndroid(): Boolean = false + override fun useOptimizedEventBatchingOnAndroid(): Boolean = false + override fun useRuntimeShadowNodeReferenceUpdate(): Boolean = false override fun useRuntimeShadowNodeReferenceUpdateOnLayout(): 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 4f41507f1b1..65b3dc38c75 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<> + * @generated SignedSource<<7727737ae31a239d6b68397fafadbfea>> */ /** @@ -66,6 +66,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private var useNativeViewConfigsInBridgelessModeCache: Boolean? = null private var useNewReactImageViewBackgroundDrawingCache: Boolean? = null private var useOptimisedViewPreallocationOnAndroidCache: Boolean? = null + private var useOptimizedEventBatchingOnAndroidCache: Boolean? = null private var useRuntimeShadowNodeReferenceUpdateCache: Boolean? = null private var useRuntimeShadowNodeReferenceUpdateOnLayoutCache: Boolean? = null private var useStateAlignmentMechanismCache: Boolean? = null @@ -491,6 +492,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun useOptimizedEventBatchingOnAndroid(): Boolean { + var cached = useOptimizedEventBatchingOnAndroidCache + if (cached == null) { + cached = currentProvider.useOptimizedEventBatchingOnAndroid() + accessedFeatureFlags.add("useOptimizedEventBatchingOnAndroid") + useOptimizedEventBatchingOnAndroidCache = cached + } + return cached + } + override fun useRuntimeShadowNodeReferenceUpdate(): Boolean { var cached = useRuntimeShadowNodeReferenceUpdateCache 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 2226963318c..b6bfbc6cf98 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<<2c8c28515aa6929b975ef7193c8bf72e>> + * @generated SignedSource<> */ /** @@ -107,6 +107,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun useOptimisedViewPreallocationOnAndroid(): Boolean + @DoNotStrip public fun useOptimizedEventBatchingOnAndroid(): Boolean + @DoNotStrip public fun useRuntimeShadowNodeReferenceUpdate(): Boolean @DoNotStrip public fun useRuntimeShadowNodeReferenceUpdateOnLayout(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/FabricEventDispatcher.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/FabricEventDispatcher.java index 0e4ba72f731..b7675134bd1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/FabricEventDispatcher.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/FabricEventDispatcher.java @@ -7,6 +7,7 @@ package com.facebook.react.uimanager.events; +import android.os.Handler; import android.view.Choreographer; import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.bridge.LifecycleEventListener; @@ -15,6 +16,7 @@ import com.facebook.react.bridge.ReactNoCrashSoftException; import com.facebook.react.bridge.ReactSoftExceptionLogger; import com.facebook.react.bridge.UIManager; import com.facebook.react.bridge.UiThreadUtil; +import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags; import com.facebook.react.modules.core.ReactChoreographer; import com.facebook.react.uimanager.UIManagerHelper; import com.facebook.react.uimanager.common.UIManagerType; @@ -27,6 +29,8 @@ import java.util.concurrent.CopyOnWriteArrayList; */ @Nullsafe(Nullsafe.Mode.LOCAL) public class FabricEventDispatcher implements EventDispatcher, LifecycleEventListener { + private static final Handler uiThreadHandler = UiThreadUtil.getUiThreadHandler(); + private final ReactEventEmitter mReactEventEmitter; private final ReactApplicationContext mReactContext; private final CopyOnWriteArrayList mListeners = @@ -36,6 +40,25 @@ public class FabricEventDispatcher implements EventDispatcher, LifecycleEventLis private final FabricEventDispatcher.ScheduleDispatchFrameCallback mCurrentFrameCallback = new FabricEventDispatcher.ScheduleDispatchFrameCallback(); + private boolean mIsDispatchScheduled = false; + private final Runnable mDispatchEventsRunnable = + new Runnable() { + @Override + public void run() { + mIsDispatchScheduled = false; + + Systrace.beginSection( + Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "BatchEventDispatchedListeners"); + try { + for (BatchEventDispatchedListener listener : mPostEventDispatchListeners) { + listener.onBatchEventDispatched(); + } + } finally { + Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); + } + } + }; + public FabricEventDispatcher(ReactApplicationContext reactContext) { mReactContext = reactContext; mReactContext.addLifecycleEventListener(this); @@ -89,7 +112,14 @@ public class FabricEventDispatcher implements EventDispatcher, LifecycleEventLis } private void scheduleDispatchOfBatchedEvents() { - mCurrentFrameCallback.maybeScheduleDispatchOfBatchedEvents(); + if (ReactNativeFeatureFlags.useOptimizedEventBatchingOnAndroid()) { + if (!mIsDispatchScheduled) { + mIsDispatchScheduled = true; + uiThreadHandler.postAtFrontOfQueue(mDispatchEventsRunnable); + } + } else { + mCurrentFrameCallback.maybeScheduleDispatchOfBatchedEvents(); + } } /** Add a listener to this EventDispatcher. */ @@ -137,7 +167,12 @@ public class FabricEventDispatcher implements EventDispatcher, LifecycleEventLis private void cancelDispatchOfBatchedEvents() { UiThreadUtil.assertOnUiThread(); - mCurrentFrameCallback.stop(); + if (ReactNativeFeatureFlags.useOptimizedEventBatchingOnAndroid()) { + mIsDispatchScheduled = false; + uiThreadHandler.removeCallbacks(mDispatchEventsRunnable); + } else { + mCurrentFrameCallback.stop(); + } } public void registerEventEmitter(@UIManagerType int uiManagerType, RCTEventEmitter eventEmitter) { 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 aff92774312..b4b62e99d11 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<<35f5003b77104e68e32741e4626e2ba6>> + * @generated SignedSource<> */ /** @@ -291,6 +291,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool useOptimizedEventBatchingOnAndroid() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("useOptimizedEventBatchingOnAndroid"); + return method(javaProvider_); + } + bool useRuntimeShadowNodeReferenceUpdate() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("useRuntimeShadowNodeReferenceUpdate"); @@ -529,6 +535,11 @@ bool JReactNativeFeatureFlagsCxxInterop::useOptimisedViewPreallocationOnAndroid( return ReactNativeFeatureFlags::useOptimisedViewPreallocationOnAndroid(); } +bool JReactNativeFeatureFlagsCxxInterop::useOptimizedEventBatchingOnAndroid( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::useOptimizedEventBatchingOnAndroid(); +} + bool JReactNativeFeatureFlagsCxxInterop::useRuntimeShadowNodeReferenceUpdate( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::useRuntimeShadowNodeReferenceUpdate(); @@ -692,6 +703,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "useOptimisedViewPreallocationOnAndroid", JReactNativeFeatureFlagsCxxInterop::useOptimisedViewPreallocationOnAndroid), + makeNativeMethod( + "useOptimizedEventBatchingOnAndroid", + JReactNativeFeatureFlagsCxxInterop::useOptimizedEventBatchingOnAndroid), makeNativeMethod( "useRuntimeShadowNodeReferenceUpdate", JReactNativeFeatureFlagsCxxInterop::useRuntimeShadowNodeReferenceUpdate), 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 760d549343c..133f5786b65 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<> + * @generated SignedSource<<0e82efb1fac0a62802f5f09e96de31d0>> */ /** @@ -156,6 +156,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool useOptimisedViewPreallocationOnAndroid( facebook::jni::alias_ref); + static bool useOptimizedEventBatchingOnAndroid( + facebook::jni::alias_ref); + static bool useRuntimeShadowNodeReferenceUpdate( 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 a336b0da56a..5d603e20a93 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<> + * @generated SignedSource<<31c0fac0172a6d3f9ab84a77d4967f5e>> */ /** @@ -189,6 +189,10 @@ bool ReactNativeFeatureFlags::useOptimisedViewPreallocationOnAndroid() { return getAccessor().useOptimisedViewPreallocationOnAndroid(); } +bool ReactNativeFeatureFlags::useOptimizedEventBatchingOnAndroid() { + return getAccessor().useOptimizedEventBatchingOnAndroid(); +} + bool ReactNativeFeatureFlags::useRuntimeShadowNodeReferenceUpdate() { return getAccessor().useRuntimeShadowNodeReferenceUpdate(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 63271e91427..d371a473618 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<<748622d87b1051bbb1cd79fb479ab0e2>> + * @generated SignedSource<<56c3d93945f6c320e268c9ba32cbde0f>> */ /** @@ -247,6 +247,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool useOptimisedViewPreallocationOnAndroid(); + /** + * Uses an optimized mechanism for event batching on Android that does not need to wait for a Choreographer frame callback. + */ + RN_EXPORT static bool useOptimizedEventBatchingOnAndroid(); + /** * When enabled, cloning shadow nodes within react native will update the reference held by the current JS fiber tree. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 312b2e36eb0..4356721714c 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<<90f05e6a6a414704176234724ca1fc04>> + * @generated SignedSource<<73c8cf1d23aa58b4b60e4018c0ddc12e>> */ /** @@ -785,6 +785,24 @@ bool ReactNativeFeatureFlagsAccessor::useOptimisedViewPreallocationOnAndroid() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() { + auto flagValue = useOptimizedEventBatchingOnAndroid_.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(42, "useOptimizedEventBatchingOnAndroid"); + + flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid(); + useOptimizedEventBatchingOnAndroid_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdate() { auto flagValue = useRuntimeShadowNodeReferenceUpdate_.load(); @@ -794,7 +812,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(42, "useRuntimeShadowNodeReferenceUpdate"); + markFlagAsAccessed(43, "useRuntimeShadowNodeReferenceUpdate"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdate(); useRuntimeShadowNodeReferenceUpdate_ = flagValue; @@ -812,7 +830,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(43, "useRuntimeShadowNodeReferenceUpdateOnLayout"); + markFlagAsAccessed(44, "useRuntimeShadowNodeReferenceUpdateOnLayout"); flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdateOnLayout(); useRuntimeShadowNodeReferenceUpdateOnLayout_ = flagValue; @@ -830,7 +848,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(44, "useStateAlignmentMechanism"); + markFlagAsAccessed(45, "useStateAlignmentMechanism"); flagValue = currentProvider_->useStateAlignmentMechanism(); useStateAlignmentMechanism_ = flagValue; @@ -848,7 +866,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(45, "useTurboModuleInterop"); + markFlagAsAccessed(46, "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 45b9d9bbc04..e0c66cd1d72 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<<94a2acd88ff16cfe528e0ec9baf6a383>> */ /** @@ -73,6 +73,7 @@ class ReactNativeFeatureFlagsAccessor { bool useNativeViewConfigsInBridgelessMode(); bool useNewReactImageViewBackgroundDrawing(); bool useOptimisedViewPreallocationOnAndroid(); + bool useOptimizedEventBatchingOnAndroid(); bool useRuntimeShadowNodeReferenceUpdate(); bool useRuntimeShadowNodeReferenceUpdateOnLayout(); bool useStateAlignmentMechanism(); @@ -87,7 +88,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 46> accessedFeatureFlags_; + std::array, 47> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> allowRecursiveCommitsWithSynchronousMountOnAndroid_; @@ -131,6 +132,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> useNativeViewConfigsInBridgelessMode_; std::atomic> useNewReactImageViewBackgroundDrawing_; std::atomic> useOptimisedViewPreallocationOnAndroid_; + std::atomic> useOptimizedEventBatchingOnAndroid_; std::atomic> useRuntimeShadowNodeReferenceUpdate_; std::atomic> useRuntimeShadowNodeReferenceUpdateOnLayout_; std::atomic> useStateAlignmentMechanism_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 90513ef6228..f999b7c36e9 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<<602c539c5cf438a04a1fb4b6ce05cd3a>> */ /** @@ -195,6 +195,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool useOptimizedEventBatchingOnAndroid() override { + return false; + } + bool useRuntimeShadowNodeReferenceUpdate() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 8bf060efdcc..e68a77bb4af 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<<6bfd567b419f4dbb1a72470265fae271>> + * @generated SignedSource<> */ /** @@ -67,6 +67,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool useNativeViewConfigsInBridgelessMode() = 0; virtual bool useNewReactImageViewBackgroundDrawing() = 0; virtual bool useOptimisedViewPreallocationOnAndroid() = 0; + virtual bool useOptimizedEventBatchingOnAndroid() = 0; virtual bool useRuntimeShadowNodeReferenceUpdate() = 0; virtual bool useRuntimeShadowNodeReferenceUpdateOnLayout() = 0; virtual bool useStateAlignmentMechanism() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index f33a4a9be69..4015c22847d 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<<903710df33dd5666f8f2ddce79f66660>> + * @generated SignedSource<<1461fc4acff2a28056df4faa4d622a16>> */ /** @@ -247,6 +247,11 @@ bool NativeReactNativeFeatureFlags::useOptimisedViewPreallocationOnAndroid( return ReactNativeFeatureFlags::useOptimisedViewPreallocationOnAndroid(); } +bool NativeReactNativeFeatureFlags::useOptimizedEventBatchingOnAndroid( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::useOptimizedEventBatchingOnAndroid(); +} + bool NativeReactNativeFeatureFlags::useRuntimeShadowNodeReferenceUpdate( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::useRuntimeShadowNodeReferenceUpdate(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 166b4071f13..225467de77f 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<<6d1f1233f646704d1403f984dabbb2e4>> + * @generated SignedSource<<9f06e832566c4c1271eaf9bb5cfdf886>> */ /** @@ -119,6 +119,8 @@ class NativeReactNativeFeatureFlags bool useOptimisedViewPreallocationOnAndroid(jsi::Runtime& runtime); + bool useOptimizedEventBatchingOnAndroid(jsi::Runtime& runtime); + bool useRuntimeShadowNodeReferenceUpdate(jsi::Runtime& runtime); bool useRuntimeShadowNodeReferenceUpdateOnLayout(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 09b3f412d4a..e4f1b270a4d 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -240,6 +240,11 @@ const definitions: FeatureFlagDefinitions = { description: 'Moves more of the work in view preallocation to the main thread to free up JS thread.', }, + useOptimizedEventBatchingOnAndroid: { + defaultValue: false, + description: + 'Uses an optimized mechanism for event batching on Android that does not need to wait for a Choreographer frame callback.', + }, useRuntimeShadowNodeReferenceUpdate: { defaultValue: false, description: diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index b6e642d9b10..4eef09446f3 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<> + * @generated SignedSource<<1f82c87c0c011c0bf2e76a6e46bb1d3e>> * @flow strict-local */ @@ -88,6 +88,7 @@ export type ReactNativeFeatureFlags = { useNativeViewConfigsInBridgelessMode: Getter, useNewReactImageViewBackgroundDrawing: Getter, useOptimisedViewPreallocationOnAndroid: Getter, + useOptimizedEventBatchingOnAndroid: Getter, useRuntimeShadowNodeReferenceUpdate: Getter, useRuntimeShadowNodeReferenceUpdateOnLayout: Getter, useStateAlignmentMechanism: Getter, @@ -332,6 +333,10 @@ export const useNewReactImageViewBackgroundDrawing: Getter = createNati * Moves more of the work in view preallocation to the main thread to free up JS thread. */ export const useOptimisedViewPreallocationOnAndroid: Getter = createNativeFlagGetter('useOptimisedViewPreallocationOnAndroid', false); +/** + * Uses an optimized mechanism for event batching on Android that does not need to wait for a Choreographer frame callback. + */ +export const useOptimizedEventBatchingOnAndroid: Getter = createNativeFlagGetter('useOptimizedEventBatchingOnAndroid', false); /** * When enabled, cloning shadow nodes within react native will update the reference held by the current JS fiber tree. */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index 98c7d4b774b..8db23a6537e 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<<0f11ba941f22bed8f3b43d1332dc4557>> + * @generated SignedSource<<8370ce5bfcfa27bfdaab6549ae54b6d4>> * @flow strict-local */ @@ -65,6 +65,7 @@ export interface Spec extends TurboModule { +useNativeViewConfigsInBridgelessMode?: () => boolean; +useNewReactImageViewBackgroundDrawing?: () => boolean; +useOptimisedViewPreallocationOnAndroid?: () => boolean; + +useOptimizedEventBatchingOnAndroid?: () => boolean; +useRuntimeShadowNodeReferenceUpdate?: () => boolean; +useRuntimeShadowNodeReferenceUpdateOnLayout?: () => boolean; +useStateAlignmentMechanism?: () => boolean;