Skip to content

Commit 516dda4

Browse files
rozelefacebook-github-bot
authored andcommitted
Delete ShadowTreeRevision on background thread (facebook#50997)
Summary: Pull Request resolved: facebook#50997 In some apps, we spend a non-trivial amount of time calling ShadowNode destructors on the UI thread. A simple way to avoid stalling the UI thread is to move the `baseRevision_` instance to a data structure that is cleared on a background thread, so it's tree of ShadowNode shared_ptrs are released (and in most cases destroyed) on the background thread. To minimize thread initialization costs, this change adds an AsyncDestructor helper that uses a single background thread and a queue of to-be-destroyed objects that are released in a run loop. This change is also guarded by a feature flag so we can keep an eye out for potential memory leaks. ## Changelog [Internal] Differential Revision: D73688009
1 parent 78e45e5 commit 516dda4

22 files changed

+260
-52
lines changed

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<3043c6e2fd674eaf2c1d6c3a064083b2>>
7+
* @generated SignedSource<<fd5a1c2afb98cc36d63d00027567541f>>
88
*/
99

1010
/**
@@ -90,6 +90,12 @@ public object ReactNativeFeatureFlags {
9090
@JvmStatic
9191
public fun enableCustomFocusSearchOnClippedElementsAndroid(): Boolean = accessor.enableCustomFocusSearchOnClippedElementsAndroid()
9292

93+
/**
94+
* Enables destructor calls for ShadowTreeRevision in the background to reduce UI thread work.
95+
*/
96+
@JvmStatic
97+
public fun enableDestroyShadowTreeRevisionAsync(): Boolean = accessor.enableDestroyShadowTreeRevisionAsync()
98+
9399
/**
94100
* Feature flag to configure eager attachment of the root view/initialisation of the JS code.
95101
*/

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<090ff0c403728370f2c88a2434c9ae12>>
7+
* @generated SignedSource<<9ade7405479f8e3b870913b1ae8c488d>>
88
*/
99

1010
/**
@@ -30,6 +30,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
3030
private var enableBridgelessArchitectureCache: Boolean? = null
3131
private var enableCppPropsIteratorSetterCache: Boolean? = null
3232
private var enableCustomFocusSearchOnClippedElementsAndroidCache: Boolean? = null
33+
private var enableDestroyShadowTreeRevisionAsyncCache: Boolean? = null
3334
private var enableEagerRootViewAttachmentCache: Boolean? = null
3435
private var enableFabricLogsCache: Boolean? = null
3536
private var enableFabricRendererCache: Boolean? = null
@@ -153,6 +154,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
153154
return cached
154155
}
155156

157+
override fun enableDestroyShadowTreeRevisionAsync(): Boolean {
158+
var cached = enableDestroyShadowTreeRevisionAsyncCache
159+
if (cached == null) {
160+
cached = ReactNativeFeatureFlagsCxxInterop.enableDestroyShadowTreeRevisionAsync()
161+
enableDestroyShadowTreeRevisionAsyncCache = cached
162+
}
163+
return cached
164+
}
165+
156166
override fun enableEagerRootViewAttachment(): Boolean {
157167
var cached = enableEagerRootViewAttachmentCache
158168
if (cached == null) {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<1d7b3dd1a1e40eb7802834c22eb01256>>
7+
* @generated SignedSource<<b8f288fd66a28f4d746f537af34203f0>>
88
*/
99

1010
/**
@@ -48,6 +48,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
4848

4949
@DoNotStrip @JvmStatic public external fun enableCustomFocusSearchOnClippedElementsAndroid(): Boolean
5050

51+
@DoNotStrip @JvmStatic public external fun enableDestroyShadowTreeRevisionAsync(): Boolean
52+
5153
@DoNotStrip @JvmStatic public external fun enableEagerRootViewAttachment(): Boolean
5254

5355
@DoNotStrip @JvmStatic public external fun enableFabricLogs(): Boolean

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<bf8b0d4c128a040853d2b12f74597d46>>
7+
* @generated SignedSource<<05501abbe5a486b8b5595eb23626d98c>>
88
*/
99

1010
/**
@@ -43,6 +43,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
4343

4444
override fun enableCustomFocusSearchOnClippedElementsAndroid(): Boolean = true
4545

46+
override fun enableDestroyShadowTreeRevisionAsync(): Boolean = false
47+
4648
override fun enableEagerRootViewAttachment(): Boolean = false
4749

4850
override fun enableFabricLogs(): Boolean = false

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<4c8f6a3a41aebb8c9e81c26cd7973f90>>
7+
* @generated SignedSource<<084fa5f87550a9a53bb263bf8445a4ba>>
88
*/
99

1010
/**
@@ -34,6 +34,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
3434
private var enableBridgelessArchitectureCache: Boolean? = null
3535
private var enableCppPropsIteratorSetterCache: Boolean? = null
3636
private var enableCustomFocusSearchOnClippedElementsAndroidCache: Boolean? = null
37+
private var enableDestroyShadowTreeRevisionAsyncCache: Boolean? = null
3738
private var enableEagerRootViewAttachmentCache: Boolean? = null
3839
private var enableFabricLogsCache: Boolean? = null
3940
private var enableFabricRendererCache: Boolean? = null
@@ -167,6 +168,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
167168
return cached
168169
}
169170

171+
override fun enableDestroyShadowTreeRevisionAsync(): Boolean {
172+
var cached = enableDestroyShadowTreeRevisionAsyncCache
173+
if (cached == null) {
174+
cached = currentProvider.enableDestroyShadowTreeRevisionAsync()
175+
accessedFeatureFlags.add("enableDestroyShadowTreeRevisionAsync")
176+
enableDestroyShadowTreeRevisionAsyncCache = cached
177+
}
178+
return cached
179+
}
180+
170181
override fun enableEagerRootViewAttachment(): Boolean {
171182
var cached = enableEagerRootViewAttachmentCache
172183
if (cached == null) {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<5a02fc6cd183f41724b3599fad1fd507>>
7+
* @generated SignedSource<<e127791010263843290152a17f94dbd6>>
88
*/
99

1010
/**
@@ -43,6 +43,8 @@ public interface ReactNativeFeatureFlagsProvider {
4343

4444
@DoNotStrip public fun enableCustomFocusSearchOnClippedElementsAndroid(): Boolean
4545

46+
@DoNotStrip public fun enableDestroyShadowTreeRevisionAsync(): Boolean
47+
4648
@DoNotStrip public fun enableEagerRootViewAttachment(): Boolean
4749

4850
@DoNotStrip public fun enableFabricLogs(): Boolean

packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<77e8728a964ccb7227f1020b5cca3663>>
7+
* @generated SignedSource<<15633f8f1184b64d0656451a246844f0>>
88
*/
99

1010
/**
@@ -99,6 +99,12 @@ class ReactNativeFeatureFlagsJavaProvider
9999
return method(javaProvider_);
100100
}
101101

102+
bool enableDestroyShadowTreeRevisionAsync() override {
103+
static const auto method =
104+
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableDestroyShadowTreeRevisionAsync");
105+
return method(javaProvider_);
106+
}
107+
102108
bool enableEagerRootViewAttachment() override {
103109
static const auto method =
104110
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableEagerRootViewAttachment");
@@ -345,6 +351,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableCustomFocusSearchOnClippedElement
345351
return ReactNativeFeatureFlags::enableCustomFocusSearchOnClippedElementsAndroid();
346352
}
347353

354+
bool JReactNativeFeatureFlagsCxxInterop::enableDestroyShadowTreeRevisionAsync(
355+
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
356+
return ReactNativeFeatureFlags::enableDestroyShadowTreeRevisionAsync();
357+
}
358+
348359
bool JReactNativeFeatureFlagsCxxInterop::enableEagerRootViewAttachment(
349360
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
350361
return ReactNativeFeatureFlags::enableEagerRootViewAttachment();
@@ -566,6 +577,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
566577
makeNativeMethod(
567578
"enableCustomFocusSearchOnClippedElementsAndroid",
568579
JReactNativeFeatureFlagsCxxInterop::enableCustomFocusSearchOnClippedElementsAndroid),
580+
makeNativeMethod(
581+
"enableDestroyShadowTreeRevisionAsync",
582+
JReactNativeFeatureFlagsCxxInterop::enableDestroyShadowTreeRevisionAsync),
569583
makeNativeMethod(
570584
"enableEagerRootViewAttachment",
571585
JReactNativeFeatureFlagsCxxInterop::enableEagerRootViewAttachment),

packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<c97e1762ba0482b784915c13785f0949>>
7+
* @generated SignedSource<<6afef40f6dbefae1baa4d520b7962bb3>>
88
*/
99

1010
/**
@@ -60,6 +60,9 @@ class JReactNativeFeatureFlagsCxxInterop
6060
static bool enableCustomFocusSearchOnClippedElementsAndroid(
6161
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
6262

63+
static bool enableDestroyShadowTreeRevisionAsync(
64+
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
65+
6366
static bool enableEagerRootViewAttachment(
6467
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
6568

packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<f1a0488306a1cbe4cc892eba27a3b7c5>>
7+
* @generated SignedSource<<3a8347697be55719757512af997a03a4>>
88
*/
99

1010
/**
@@ -66,6 +66,10 @@ bool ReactNativeFeatureFlags::enableCustomFocusSearchOnClippedElementsAndroid()
6666
return getAccessor().enableCustomFocusSearchOnClippedElementsAndroid();
6767
}
6868

69+
bool ReactNativeFeatureFlags::enableDestroyShadowTreeRevisionAsync() {
70+
return getAccessor().enableDestroyShadowTreeRevisionAsync();
71+
}
72+
6973
bool ReactNativeFeatureFlags::enableEagerRootViewAttachment() {
7074
return getAccessor().enableEagerRootViewAttachment();
7175
}

packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<8c259acc61fa1b132df222cf16a2f29f>>
7+
* @generated SignedSource<<6dc689885f573c59e299214e5926fdd5>>
88
*/
99

1010
/**
@@ -89,6 +89,11 @@ class ReactNativeFeatureFlags {
8989
*/
9090
RN_EXPORT static bool enableCustomFocusSearchOnClippedElementsAndroid();
9191

92+
/**
93+
* Enables destructor calls for ShadowTreeRevision in the background to reduce UI thread work.
94+
*/
95+
RN_EXPORT static bool enableDestroyShadowTreeRevisionAsync();
96+
9297
/**
9398
* Feature flag to configure eager attachment of the root view/initialisation of the JS code.
9499
*/

0 commit comments

Comments
 (0)