Skip to content

Commit 2d1db71

Browse files
NickGerlemanfacebook-github-bot
authored andcommitted
Add global cache for Facsimile Layouts (#52308)
Summary: Pull Request resolved: #52308 Experimentation shows, that we very heavily rely on the global text cache for performance (not sure how much of this is invalidation, vs repeated text, or revisiting previous surfaces). This adds a global LRU cache, of prepared layouts, given a specific AttributedString and constraints. This is similar to the existing cache, with the caveat, that we need to have separate entries for any display states, instead of just those that effect metrics. I sized it at 200 elements for now, since an Android `Layout` is much heavier than a `Size` (in practice, each seem to weight 1-3KB (though this will be significantly reduced with future change to move from `SpannableStringBuilder` to `SpannableString` and also contributes to the global JNI ref table, but set this up to be customizable via flag, so we can experiment, on perf impact, vs memory. Changelog: [Internal] Reviewed By: rshest Differential Revision: D77341994 fbshipit-source-id: b453250dc475f6a281a3260b876bf80f301dd5dd
1 parent d96bbcd commit 2d1db71

24 files changed

+265
-64
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<<f5a7da2d8775ac1defa4037efd984504>>
7+
* @generated SignedSource<<697babc37818f427f02fd3ab4c53febd>>
88
*/
99

1010
/**
@@ -294,6 +294,12 @@ public object ReactNativeFeatureFlags {
294294
@JvmStatic
295295
public fun fuseboxNetworkInspectionEnabled(): Boolean = accessor.fuseboxNetworkInspectionEnabled()
296296

297+
/**
298+
* Number cached PreparedLayouts in TextLayoutManager cache
299+
*/
300+
@JvmStatic
301+
public fun preparedTextCacheSize(): Double = accessor.preparedTextCacheSize()
302+
297303
/**
298304
* Enables storing js caller stack when creating promise in native module. This is useful in case of Promise rejection and tracing the cause.
299305
*/

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<<0c6c54413dc51e692605811e89d567dc>>
7+
* @generated SignedSource<<275296a2e051e0ae2a17d80836ae9ee1>>
88
*/
99

1010
/**
@@ -64,6 +64,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
6464
private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
6565
private var fuseboxEnabledReleaseCache: Boolean? = null
6666
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
67+
private var preparedTextCacheSizeCache: Double? = null
6768
private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null
6869
private var updateRuntimeShadowNodeReferencesOnCommitCache: Boolean? = null
6970
private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null
@@ -472,6 +473,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
472473
return cached
473474
}
474475

476+
override fun preparedTextCacheSize(): Double {
477+
var cached = preparedTextCacheSizeCache
478+
if (cached == null) {
479+
cached = ReactNativeFeatureFlagsCxxInterop.preparedTextCacheSize()
480+
preparedTextCacheSizeCache = cached
481+
}
482+
return cached
483+
}
484+
475485
override fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean {
476486
var cached = traceTurboModulePromiseRejectionsOnAndroidCache
477487
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<<4c47c4c6977880efee8b45bbcd4d999d>>
7+
* @generated SignedSource<<25ee348b038042f2f45efdb526949f1b>>
88
*/
99

1010
/**
@@ -116,6 +116,8 @@ public object ReactNativeFeatureFlagsCxxInterop {
116116

117117
@DoNotStrip @JvmStatic public external fun fuseboxNetworkInspectionEnabled(): Boolean
118118

119+
@DoNotStrip @JvmStatic public external fun preparedTextCacheSize(): Double
120+
119121
@DoNotStrip @JvmStatic public external fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean
120122

121123
@DoNotStrip @JvmStatic public external fun updateRuntimeShadowNodeReferencesOnCommit(): 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<<33af38489ce1077f24a639db52213953>>
7+
* @generated SignedSource<<a1eb592bf34ec0bd242c44a2f6bb6828>>
88
*/
99

1010
/**
@@ -111,6 +111,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi
111111

112112
override fun fuseboxNetworkInspectionEnabled(): Boolean = false
113113

114+
override fun preparedTextCacheSize(): Double = 200.0
115+
114116
override fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean = false
115117

116118
override fun updateRuntimeShadowNodeReferencesOnCommit(): 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<<97d032014047ab05c6d9fc39665a4b3e>>
7+
* @generated SignedSource<<cdd5ac40322e76f95cc8831d30012375>>
88
*/
99

1010
/**
@@ -68,6 +68,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
6868
private var fixMappingOfEventPrioritiesBetweenFabricAndReactCache: Boolean? = null
6969
private var fuseboxEnabledReleaseCache: Boolean? = null
7070
private var fuseboxNetworkInspectionEnabledCache: Boolean? = null
71+
private var preparedTextCacheSizeCache: Double? = null
7172
private var traceTurboModulePromiseRejectionsOnAndroidCache: Boolean? = null
7273
private var updateRuntimeShadowNodeReferencesOnCommitCache: Boolean? = null
7374
private var useAlwaysAvailableJSErrorHandlingCache: Boolean? = null
@@ -520,6 +521,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
520521
return cached
521522
}
522523

524+
override fun preparedTextCacheSize(): Double {
525+
var cached = preparedTextCacheSizeCache
526+
if (cached == null) {
527+
cached = currentProvider.preparedTextCacheSize()
528+
accessedFeatureFlags.add("preparedTextCacheSize")
529+
preparedTextCacheSizeCache = cached
530+
}
531+
return cached
532+
}
533+
523534
override fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean {
524535
var cached = traceTurboModulePromiseRejectionsOnAndroidCache
525536
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<<8a607ad40a3e991943c32bc120fcd66f>>
7+
* @generated SignedSource<<10197755f82d5b7251563ce1517c8fac>>
88
*/
99

1010
/**
@@ -111,6 +111,8 @@ public interface ReactNativeFeatureFlagsProvider {
111111

112112
@DoNotStrip public fun fuseboxNetworkInspectionEnabled(): Boolean
113113

114+
@DoNotStrip public fun preparedTextCacheSize(): Double
115+
114116
@DoNotStrip public fun traceTurboModulePromiseRejectionsOnAndroid(): Boolean
115117

116118
@DoNotStrip public fun updateRuntimeShadowNodeReferencesOnCommit(): 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<<9a0a41bc27ee271578e74664951c5217>>
7+
* @generated SignedSource<<53e68ed98b80c867e3045902e1618c9b>>
88
*/
99

1010
/**
@@ -303,6 +303,12 @@ class ReactNativeFeatureFlagsJavaProvider
303303
return method(javaProvider_);
304304
}
305305

306+
double preparedTextCacheSize() override {
307+
static const auto method =
308+
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jdouble()>("preparedTextCacheSize");
309+
return method(javaProvider_);
310+
}
311+
306312
bool traceTurboModulePromiseRejectionsOnAndroid() override {
307313
static const auto method =
308314
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("traceTurboModulePromiseRejectionsOnAndroid");
@@ -593,6 +599,11 @@ bool JReactNativeFeatureFlagsCxxInterop::fuseboxNetworkInspectionEnabled(
593599
return ReactNativeFeatureFlags::fuseboxNetworkInspectionEnabled();
594600
}
595601

602+
double JReactNativeFeatureFlagsCxxInterop::preparedTextCacheSize(
603+
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
604+
return ReactNativeFeatureFlags::preparedTextCacheSize();
605+
}
606+
596607
bool JReactNativeFeatureFlagsCxxInterop::traceTurboModulePromiseRejectionsOnAndroid(
597608
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
598609
return ReactNativeFeatureFlags::traceTurboModulePromiseRejectionsOnAndroid();
@@ -811,6 +822,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
811822
makeNativeMethod(
812823
"fuseboxNetworkInspectionEnabled",
813824
JReactNativeFeatureFlagsCxxInterop::fuseboxNetworkInspectionEnabled),
825+
makeNativeMethod(
826+
"preparedTextCacheSize",
827+
JReactNativeFeatureFlagsCxxInterop::preparedTextCacheSize),
814828
makeNativeMethod(
815829
"traceTurboModulePromiseRejectionsOnAndroid",
816830
JReactNativeFeatureFlagsCxxInterop::traceTurboModulePromiseRejectionsOnAndroid),

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<<1d3320eb050bd827c0109319afb92991>>
7+
* @generated SignedSource<<70de16b94b14f0e7de235f72e1566abe>>
88
*/
99

1010
/**
@@ -162,6 +162,9 @@ class JReactNativeFeatureFlagsCxxInterop
162162
static bool fuseboxNetworkInspectionEnabled(
163163
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
164164

165+
static double preparedTextCacheSize(
166+
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
167+
165168
static bool traceTurboModulePromiseRejectionsOnAndroid(
166169
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
167170

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<<e95ca3707afa85dbcd17a351872da3b3>>
7+
* @generated SignedSource<<2206721fac3452fd4d9ca3053cc7bc32>>
88
*/
99

1010
/**
@@ -202,6 +202,10 @@ bool ReactNativeFeatureFlags::fuseboxNetworkInspectionEnabled() {
202202
return getAccessor().fuseboxNetworkInspectionEnabled();
203203
}
204204

205+
double ReactNativeFeatureFlags::preparedTextCacheSize() {
206+
return getAccessor().preparedTextCacheSize();
207+
}
208+
205209
bool ReactNativeFeatureFlags::traceTurboModulePromiseRejectionsOnAndroid() {
206210
return getAccessor().traceTurboModulePromiseRejectionsOnAndroid();
207211
}

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<<61381e3eb65214c519a01283366a53c6>>
7+
* @generated SignedSource<<d724d9cfe69141b40f95df5308894f50>>
88
*/
99

1010
/**
@@ -259,6 +259,11 @@ class ReactNativeFeatureFlags {
259259
*/
260260
RN_EXPORT static bool fuseboxNetworkInspectionEnabled();
261261

262+
/**
263+
* Number cached PreparedLayouts in TextLayoutManager cache
264+
*/
265+
RN_EXPORT static double preparedTextCacheSize();
266+
262267
/**
263268
* Enables storing js caller stack when creating promise in native module. This is useful in case of Promise rejection and tracing the cause.
264269
*/

0 commit comments

Comments
 (0)