Skip to content

Commit

Permalink
do not pass state wrapper for text during view preallocation (#46418)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #46418

changelog: [internal]

introduce a small performance optimisation on Android.

When Paragraph is preallocated, it does not have valid C++ state. But we still send it to Android layer because it is part of a more generic pipeline. This has a cost because Android will end up using the state to update internal state on ReactTextView. To avoid this, simply add a special case to view preallocation and prevent it from sending C++ state.

Reviewed By: javache

Differential Revision: D62435529

fbshipit-source-id: 36b5b00a7a390432721d28d53ff8d4af76169e08
  • Loading branch information
sammy-SC authored and facebook-github-bot committed Sep 12, 2024
1 parent 13db1cb commit 6243a33
Show file tree
Hide file tree
Showing 20 changed files with 156 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<<312da6e350ea6b96180156a341810654>>
* @generated SignedSource<<b9b1988a78ba67a99027372dab215d06>>
*/

/**
Expand Down Expand Up @@ -160,6 +160,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableSynchronousStateUpdates(): Boolean = accessor.enableSynchronousStateUpdates()

/**
* Text preallocation optimisation where unnecessary work is removed.
*/
@JvmStatic
public fun enableTextPreallocationOptimisation(): Boolean = accessor.enableTextPreallocationOptimisation()

/**
* Ensures that JavaScript always has a consistent view of the state of the UI (e.g.: commits done in other threads are not immediately propagated to JS during its execution).
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<a397b9b648fab0e8b1f9d8a9dba04ab4>>
* @generated SignedSource<<ae270cbe5e211d74cc056511be4ead16>>
*/

/**
Expand Down Expand Up @@ -42,6 +42,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
private var enableReportEventPaintTimeCache: Boolean? = null
private var enableSynchronousStateUpdatesCache: Boolean? = null
private var enableTextPreallocationOptimisationCache: Boolean? = null
private var enableUIConsistencyCache: Boolean? = null
private var enableViewRecyclingCache: Boolean? = null
private var excludeYogaFromRawPropsCache: Boolean? = null
Expand Down Expand Up @@ -268,6 +269,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso
return cached
}

override fun enableTextPreallocationOptimisation(): Boolean {
var cached = enableTextPreallocationOptimisationCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.enableTextPreallocationOptimisation()
enableTextPreallocationOptimisationCache = cached
}
return cached
}

override fun enableUIConsistency(): Boolean {
var cached = enableUIConsistencyCache
if (cached == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<ba7f0d3c03fef86fb12e4d9842dcb241>>
* @generated SignedSource<<66a5f1eb19c081e178077b40fba27d93>>
*/

/**
Expand Down Expand Up @@ -72,6 +72,8 @@ public object ReactNativeFeatureFlagsCxxInterop {

@DoNotStrip @JvmStatic public external fun enableSynchronousStateUpdates(): Boolean

@DoNotStrip @JvmStatic public external fun enableTextPreallocationOptimisation(): Boolean

@DoNotStrip @JvmStatic public external fun enableUIConsistency(): Boolean

@DoNotStrip @JvmStatic public external fun enableViewRecycling(): Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<fa8245a05ab1f508318e1d18938f9dab>>
* @generated SignedSource<<25a422b93ab27473bfccabf653b1e196>>
*/

/**
Expand Down Expand Up @@ -67,6 +67,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi

override fun enableSynchronousStateUpdates(): Boolean = false

override fun enableTextPreallocationOptimisation(): Boolean = false

override fun enableUIConsistency(): Boolean = false

override fun enableViewRecycling(): Boolean = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<069787b84036b763c47d128e66ddd1ab>>
* @generated SignedSource<<d18208e5018340e48e3c20b6a80ecccd>>
*/

/**
Expand Down Expand Up @@ -46,6 +46,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
private var enablePropsUpdateReconciliationAndroidCache: Boolean? = null
private var enableReportEventPaintTimeCache: Boolean? = null
private var enableSynchronousStateUpdatesCache: Boolean? = null
private var enableTextPreallocationOptimisationCache: Boolean? = null
private var enableUIConsistencyCache: Boolean? = null
private var enableViewRecyclingCache: Boolean? = null
private var excludeYogaFromRawPropsCache: Boolean? = null
Expand Down Expand Up @@ -294,6 +295,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
return cached
}

override fun enableTextPreallocationOptimisation(): Boolean {
var cached = enableTextPreallocationOptimisationCache
if (cached == null) {
cached = currentProvider.enableTextPreallocationOptimisation()
accessedFeatureFlags.add("enableTextPreallocationOptimisation")
enableTextPreallocationOptimisationCache = cached
}
return cached
}

override fun enableUIConsistency(): Boolean {
var cached = enableUIConsistencyCache
if (cached == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<978d9e8d1129951f3c5750f95e2ff5d2>>
* @generated SignedSource<<2e20df15ed5c75e0749eeead23b3c9dc>>
*/

/**
Expand Down Expand Up @@ -67,6 +67,8 @@ public interface ReactNativeFeatureFlagsProvider {

@DoNotStrip public fun enableSynchronousStateUpdates(): Boolean

@DoNotStrip public fun enableTextPreallocationOptimisation(): Boolean

@DoNotStrip public fun enableUIConsistency(): Boolean

@DoNotStrip public fun enableViewRecycling(): Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,14 @@ void FabricMountingManager::preallocateShadowView(
// We DO want to hold onto C object from Java, since we don't know the
// lifetime of the Java object
jni::local_ref<StateWrapperImpl::JavaPart> javaStateWrapper = nullptr;
if (shadowView.state != nullptr) {

// Paragraph only has a dummy state during view preallocation.
// Updating state on Android side has a cost and doing it unnecessarily for
// dummy state is wasteful.
bool preventPassingStateWrapperForText =
ReactNativeFeatureFlags::enableTextPreallocationOptimisation() &&
strcmp(shadowView.componentName, "Paragraph") == 0;
if (shadowView.state != nullptr && !preventPassingStateWrapperForText) {
javaStateWrapper = StateWrapperImpl::newObjectJavaArgs();
StateWrapperImpl* cStateWrapper = cthis(javaStateWrapper);
cStateWrapper->setState(shadowView.state);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<63ef974f6ed666553bc0be593730a08e>>
* @generated SignedSource<<4ae4df54833e6fc817d73fe7cb7d1887>>
*/

/**
Expand Down Expand Up @@ -171,6 +171,12 @@ class ReactNativeFeatureFlagsProviderHolder
return method(javaProvider_);
}

bool enableTextPreallocationOptimisation() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableTextPreallocationOptimisation");
return method(javaProvider_);
}

bool enableUIConsistency() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableUIConsistency");
Expand Down Expand Up @@ -447,6 +453,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableSynchronousStateUpdates(
return ReactNativeFeatureFlags::enableSynchronousStateUpdates();
}

bool JReactNativeFeatureFlagsCxxInterop::enableTextPreallocationOptimisation(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableTextPreallocationOptimisation();
}

bool JReactNativeFeatureFlagsCxxInterop::enableUIConsistency(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableUIConsistency();
Expand Down Expand Up @@ -665,6 +676,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"enableSynchronousStateUpdates",
JReactNativeFeatureFlagsCxxInterop::enableSynchronousStateUpdates),
makeNativeMethod(
"enableTextPreallocationOptimisation",
JReactNativeFeatureFlagsCxxInterop::enableTextPreallocationOptimisation),
makeNativeMethod(
"enableUIConsistency",
JReactNativeFeatureFlagsCxxInterop::enableUIConsistency),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<d39aa0038255aedc5613fc2e44b9ad88>>
* @generated SignedSource<<a46a48a0f3c1a84badde0aa5618faf84>>
*/

/**
Expand Down Expand Up @@ -96,6 +96,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool enableSynchronousStateUpdates(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

static bool enableTextPreallocationOptimisation(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

static bool enableUIConsistency(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<7c97c370b2f453691c153fb370bea149>>
* @generated SignedSource<<5df8c423af27ec25003d26a67ec1ef56>>
*/

/**
Expand Down Expand Up @@ -109,6 +109,10 @@ bool ReactNativeFeatureFlags::enableSynchronousStateUpdates() {
return getAccessor().enableSynchronousStateUpdates();
}

bool ReactNativeFeatureFlags::enableTextPreallocationOptimisation() {
return getAccessor().enableTextPreallocationOptimisation();
}

bool ReactNativeFeatureFlags::enableUIConsistency() {
return getAccessor().enableUIConsistency();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<<c3f43e92b0710e4a68bb76d874b3058d>>
* @generated SignedSource<<631e0b3e36325d36803b7e6fbefe2644>>
*/

/**
Expand Down Expand Up @@ -147,6 +147,11 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool enableSynchronousStateUpdates();

/**
* Text preallocation optimisation where unnecessary work is removed.
*/
RN_EXPORT static bool enableTextPreallocationOptimisation();

/**
* Ensures that JavaScript always has a consistent view of the state of the UI (e.g.: commits done in other threads are not immediately propagated to JS during its execution).
*/
Expand Down
Loading

0 comments on commit 6243a33

Please sign in to comment.