From bb9a24d9fc5faa57a85750cd3bb94546baa405ac Mon Sep 17 00:00:00 2001 From: Dmytro Rykun Date: Thu, 30 Jan 2025 11:16:42 +0000 Subject: [PATCH] Use fastAddProperties in diffing (#32243) ## Summary `fastAddProperties` has shown some perf benefits when used for creating props payload for new components. In this PR we'll try to use it for diffing props for existing components. It would be good enough if it simply doesn't regress perf. We'll be able to delete the old `addProperties`, and make `fastAddProperties` the default behaviour. ## How did you test this change? ``` yarn lint yarn flow native yarn test packages/react-native-renderer -r=xplat --variant=false yarn test packages/react-native-renderer -r=xplat --variant=true ``` --- .../src/ReactNativeAttributePayloadFabric.js | 11 +++++++++-- packages/shared/ReactFeatureFlags.js | 2 ++ .../forks/ReactFeatureFlags.native-fb-dynamic.js | 1 + packages/shared/forks/ReactFeatureFlags.native-fb.js | 1 + packages/shared/forks/ReactFeatureFlags.native-oss.js | 1 + .../shared/forks/ReactFeatureFlags.test-renderer.js | 1 + .../ReactFeatureFlags.test-renderer.native-fb.js | 1 + .../forks/ReactFeatureFlags.test-renderer.www.js | 1 + .../shared/forks/ReactFeatureFlags.www-dynamic.js | 1 + packages/shared/forks/ReactFeatureFlags.www.js | 1 + 10 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/react-native-renderer/src/ReactNativeAttributePayloadFabric.js b/packages/react-native-renderer/src/ReactNativeAttributePayloadFabric.js index f97c31e3980b6..8b8e45e7514f1 100644 --- a/packages/react-native-renderer/src/ReactNativeAttributePayloadFabric.js +++ b/packages/react-native-renderer/src/ReactNativeAttributePayloadFabric.js @@ -14,7 +14,10 @@ import { } from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface'; import isArray from 'shared/isArray'; -import {enableShallowPropDiffing} from 'shared/ReactFeatureFlags'; +import { + enableShallowPropDiffing, + enableFastAddPropertiesInDiffing, +} from 'shared/ReactFeatureFlags'; import type {AttributeConfiguration} from './ReactNativeTypes'; @@ -218,7 +221,11 @@ function addNestedProperty( if (!isArray(nextProp)) { // Add each property of the leaf. - return addProperties(updatePayload, nextProp, validAttributes); + if (enableFastAddPropertiesInDiffing) { + return fastAddProperties(updatePayload, nextProp, validAttributes); + } else { + return addProperties(updatePayload, nextProp, validAttributes); + } } for (let i = 0; i < nextProp.length; i++) { diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index 6a77c29ff32e2..a94f3402de4f8 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -157,6 +157,8 @@ export const enableInfiniteRenderLoopDetection = false; */ export const enableUseResourceEffectHook = false; +export const enableFastAddPropertiesInDiffing = true; + // ----------------------------------------------------------------------------- // Ready for next major. // diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js b/packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js index b6e3b098dbb40..cff57d26ecd95 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js @@ -28,3 +28,4 @@ export const enableSiblingPrerendering = __VARIANT__; export const enableUseResourceEffectHook = __VARIANT__; export const enableOwnerStacks = __VARIANT__; export const enableRemoveConsolePatches = __VARIANT__; +export const enableFastAddPropertiesInDiffing = __VARIANT__; diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index c1d23e898ca83..31b3333966410 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -30,6 +30,7 @@ export const { enableSiblingPrerendering, enableOwnerStacks, enableRemoveConsolePatches, + enableFastAddPropertiesInDiffing, } = dynamicFlags; // The rest of the flags are static for better dead code elimination. diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index afe18430eba9d..84307ce62746c 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -72,6 +72,7 @@ export const enableYieldingBeforePassive = false; export const enableThrottledScheduling = false; export const enableViewTransition = false; +export const enableFastAddPropertiesInDiffing = false; // Profiling Only export const enableProfilerTimer = __PROFILE__; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index 5b4c33f331231..90725f666e1a1 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -71,6 +71,7 @@ export const enableYieldingBeforePassive = true; export const enableThrottledScheduling = false; export const enableViewTransition = false; +export const enableFastAddPropertiesInDiffing = true; // TODO: This must be in sync with the main ReactFeatureFlags file because // the Test Renderer's value must be the same as the one used by the diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js index ebc8c5eb97796..b4df6f248f9fd 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js @@ -69,6 +69,7 @@ export const enableYieldingBeforePassive = false; export const enableThrottledScheduling = false; export const enableViewTransition = false; export const enableRemoveConsolePatches = false; +export const enableFastAddPropertiesInDiffing = false; // Flow magic to verify the exports of this file match the original version. ((((null: any): ExportsType): FeatureFlagsType): ExportsType); diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js index c7c0e627305f0..a09e479f1732b 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js @@ -84,6 +84,7 @@ export const enableYieldingBeforePassive = false; export const enableThrottledScheduling = false; export const enableViewTransition = false; export const enableRemoveConsolePatches = false; +export const enableFastAddPropertiesInDiffing = false; // Flow magic to verify the exports of this file match the original version. ((((null: any): ExportsType): FeatureFlagsType): ExportsType); diff --git a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js index b75a0a91756e1..ca097b5a9efa0 100644 --- a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js +++ b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js @@ -38,6 +38,7 @@ export const enableSiblingPrerendering = __VARIANT__; export const enableUseResourceEffectHook = __VARIANT__; export const enableRemoveConsolePatches = __VARIANT__; +export const enableFastAddPropertiesInDiffing = __VARIANT__; // TODO: These flags are hard-coded to the default values used in open source. // Update the tests so that they pass in either mode, then set these diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index 58a7bcd26f9d6..223872618e603 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -37,6 +37,7 @@ export const { transitionLaneExpirationMs, enableOwnerStacks, enableRemoveConsolePatches, + enableFastAddPropertiesInDiffing, } = dynamicFeatureFlags; // On WWW, __EXPERIMENTAL__ is used for a new modern build.