Skip to content

Commit 0cb0be9

Browse files
committed
Introduce a faster version of the addProperties function (#28969)
## Summary This PR introduces a faster version of the `addProperties` function. This new function is basically the `diffProperties` with `prevProps` set to `null`, propagated constants, and all the unreachable code paths collapsed. ## How did you test this change? I've tested this change with [the benchmark app](https://github.com/react-native-community/RNNewArchitectureApp/tree/new-architecture-benchmarks) and got ~4.4% improvement in the view creation time. DiffTrain build for commit 73bcdfb.
1 parent 10db98e commit 0cb0be9

File tree

10 files changed

+317
-82
lines changed

10 files changed

+317
-82
lines changed

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/JSXDEVRuntime-dev.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<4c8919e8adb15c1f31e630f08e73d86f>>
10+
* @generated SignedSource<<af4ef85b8fe75e4033608d078d795833>>
1111
*/
1212

1313
'use strict';
@@ -25,7 +25,8 @@ var dynamicFlags = dynamicFlagsUntyped; // We destructure each value before re-e
2525

2626
var enableComponentStackLocations = dynamicFlags.enableComponentStackLocations,
2727
enableRenderableContext = dynamicFlags.enableRenderableContext,
28-
disableDefaultPropsExceptForClasses = dynamicFlags.disableDefaultPropsExceptForClasses; // The rest of the flags are static for better dead code elimination.
28+
disableDefaultPropsExceptForClasses = dynamicFlags.disableDefaultPropsExceptForClasses;
29+
// The rest of the flags are static for better dead code elimination.
2930
var enableDebugTracing = false;
3031
var enableScopeAPI = false;
3132
var enableLegacyHidden = false;

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/JSXRuntime-dev.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<659c779c0ac134a5010cd8f6556b1b17>>
10+
* @generated SignedSource<<ce4cd05ddf193df647a49f1ddbcc0aed>>
1111
*/
1212

1313
'use strict';
@@ -25,7 +25,8 @@ var dynamicFlags = dynamicFlagsUntyped; // We destructure each value before re-e
2525

2626
var enableComponentStackLocations = dynamicFlags.enableComponentStackLocations,
2727
enableRenderableContext = dynamicFlags.enableRenderableContext,
28-
disableDefaultPropsExceptForClasses = dynamicFlags.disableDefaultPropsExceptForClasses; // The rest of the flags are static for better dead code elimination.
28+
disableDefaultPropsExceptForClasses = dynamicFlags.disableDefaultPropsExceptForClasses;
29+
// The rest of the flags are static for better dead code elimination.
2930
var enableDebugTracing = false;
3031
var enableScopeAPI = false;
3132
var enableLegacyHidden = false;

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/cjs/React-dev.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<0f88cc3fda756e3467304abd247a3db7>>
10+
* @generated SignedSource<<f47b166be53dccb56c8e3adcf1ba0dfb>>
1111
*/
1212

1313
'use strict';
@@ -27,7 +27,7 @@ if (
2727
}
2828
var dynamicFlagsUntyped = require('ReactNativeInternalFeatureFlags');
2929

30-
var ReactVersion = '19.0.0-beta-6a68f48e';
30+
var ReactVersion = '19.0.0-beta-45cd200f';
3131

3232
// Re-export dynamic flags from the internal module.
3333
var dynamicFlags = dynamicFlagsUntyped; // We destructure each value before re-exporting to avoid a dynamic look-up on
@@ -36,7 +36,8 @@ var dynamicFlags = dynamicFlagsUntyped; // We destructure each value before re-e
3636
var enableAsyncActions = dynamicFlags.enableAsyncActions,
3737
enableComponentStackLocations = dynamicFlags.enableComponentStackLocations,
3838
enableRenderableContext = dynamicFlags.enableRenderableContext,
39-
disableDefaultPropsExceptForClasses = dynamicFlags.disableDefaultPropsExceptForClasses; // The rest of the flags are static for better dead code elimination.
39+
disableDefaultPropsExceptForClasses = dynamicFlags.disableDefaultPropsExceptForClasses;
40+
// The rest of the flags are static for better dead code elimination.
4041
var enableDebugTracing = false;
4142
var enableScopeAPI = false;
4243
var enableLegacyHidden = false;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
4508873393058e86bed308b56e49ec883ece59d1
1+
73bcdfbae57545aa8f88ecdf67426275610b5573

compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-dev.fb.js

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<3b1926ec8be22ff21a461aebe15a8dec>>
10+
* @generated SignedSource<<438e1cd98ae204c6c07245d77bdf2eb2>>
1111
*/
1212

1313
'use strict';
@@ -2003,7 +2003,8 @@ var alwaysThrottleRetries = dynamicFlags.alwaysThrottleRetries,
20032003
enableUnifiedSyncLane = dynamicFlags.enableUnifiedSyncLane,
20042004
passChildrenWhenCloningPersistedNodes = dynamicFlags.passChildrenWhenCloningPersistedNodes,
20052005
useModernStrictMode = dynamicFlags.useModernStrictMode,
2006-
disableDefaultPropsExceptForClasses = dynamicFlags.disableDefaultPropsExceptForClasses; // The rest of the flags are static for better dead code elimination.
2006+
disableDefaultPropsExceptForClasses = dynamicFlags.disableDefaultPropsExceptForClasses,
2007+
enableAddPropertiesFastPath = dynamicFlags.enableAddPropertiesFastPath; // The rest of the flags are static for better dead code elimination.
20072008
var enableSchedulingProfiler = true;
20082009
var enableProfilerTimer = true;
20092010
var enableProfilerCommitHooks = true;
@@ -2352,14 +2353,70 @@ function diffProperties(updatePayload, prevProps, nextProps, validAttributes) {
23522353

23532354
return updatePayload;
23542355
}
2356+
2357+
function fastAddProperties(updatePayload, nextProps, validAttributes) {
2358+
var attributeConfig;
2359+
var nextProp;
2360+
2361+
for (var propKey in nextProps) {
2362+
nextProp = nextProps[propKey];
2363+
2364+
if (nextProp === undefined) {
2365+
continue;
2366+
}
2367+
2368+
attributeConfig = validAttributes[propKey];
2369+
2370+
if (attributeConfig === undefined) {
2371+
continue;
2372+
}
2373+
2374+
if (typeof nextProp === 'function') {
2375+
nextProp = true;
2376+
}
2377+
2378+
if (typeof attributeConfig !== 'object') {
2379+
if (!updatePayload) {
2380+
updatePayload = {};
2381+
}
2382+
2383+
updatePayload[propKey] = nextProp;
2384+
continue;
2385+
}
2386+
2387+
if (typeof attributeConfig.process === 'function') {
2388+
if (!updatePayload) {
2389+
updatePayload = {};
2390+
}
2391+
2392+
updatePayload[propKey] = attributeConfig.process(nextProp);
2393+
continue;
2394+
}
2395+
2396+
if (isArray(nextProp)) {
2397+
for (var i = 0; i < nextProp.length; i++) {
2398+
updatePayload = fastAddProperties(updatePayload, nextProp[i], attributeConfig);
2399+
}
2400+
2401+
continue;
2402+
}
2403+
2404+
updatePayload = fastAddProperties(updatePayload, nextProp, attributeConfig);
2405+
}
2406+
2407+
return updatePayload;
2408+
}
23552409
/**
23562410
* addProperties adds all the valid props to the payload after being processed.
23572411
*/
23582412

23592413

23602414
function addProperties(updatePayload, props, validAttributes) {
2361-
// TODO: Fast path
2362-
return diffProperties(updatePayload, emptyObject$1, props, validAttributes);
2415+
if (enableAddPropertiesFastPath) {
2416+
return fastAddProperties(updatePayload, props, validAttributes);
2417+
} else {
2418+
return diffProperties(updatePayload, emptyObject$1, props, validAttributes);
2419+
}
23632420
}
23642421
/**
23652422
* clearProperties clears all the previous props by adding a null sentinel
@@ -26075,7 +26132,7 @@ identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, transition
2607526132
return root;
2607626133
}
2607726134

26078-
var ReactVersion = '19.0.0-beta-197956b7';
26135+
var ReactVersion = '19.0.0-beta-8a57d9cf';
2607926136

2608026137
/*
2608126138
* The `'' + value` pattern (used in perf-sensitive code) throws for Symbol

compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/implementations/ReactFabric-prod.fb.js

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<ad84473bdbce0975ceaaac6469a759ac>>
10+
* @generated SignedSource<<97e06df55397eea2903e5bffade5f61e>>
1111
*/
1212

1313
"use strict";
@@ -983,6 +983,7 @@ var alwaysThrottleRetries = dynamicFlagsUntyped.alwaysThrottleRetries,
983983
dynamicFlagsUntyped.passChildrenWhenCloningPersistedNodes,
984984
disableDefaultPropsExceptForClasses =
985985
dynamicFlagsUntyped.disableDefaultPropsExceptForClasses,
986+
enableAddPropertiesFastPath = dynamicFlagsUntyped.enableAddPropertiesFastPath,
986987
emptyObject$1 = {},
987988
removedKeys = null,
988989
removedKeyCount = 0,
@@ -1091,12 +1092,7 @@ function diffNestedProperty(
10911092
function addNestedProperty(updatePayload, nextProp, validAttributes) {
10921093
if (!nextProp) return updatePayload;
10931094
if (!isArrayImpl(nextProp))
1094-
return diffProperties(
1095-
updatePayload,
1096-
emptyObject$1,
1097-
nextProp,
1098-
validAttributes
1099-
);
1095+
return addProperties(updatePayload, nextProp, validAttributes);
11001096
for (var i = 0; i < nextProp.length; i++)
11011097
updatePayload = addNestedProperty(
11021098
updatePayload,
@@ -1206,6 +1202,44 @@ function diffProperties(updatePayload, prevProps, nextProps, validAttributes) {
12061202
)))));
12071203
return updatePayload;
12081204
}
1205+
function fastAddProperties(updatePayload, nextProps, validAttributes) {
1206+
var propKey;
1207+
for (propKey in nextProps) {
1208+
var nextProp = nextProps[propKey];
1209+
if (void 0 !== nextProp) {
1210+
var attributeConfig = validAttributes[propKey];
1211+
if (void 0 !== attributeConfig)
1212+
if (
1213+
("function" === typeof nextProp && (nextProp = !0),
1214+
"object" !== typeof attributeConfig)
1215+
)
1216+
updatePayload || (updatePayload = {}),
1217+
(updatePayload[propKey] = nextProp);
1218+
else if ("function" === typeof attributeConfig.process)
1219+
updatePayload || (updatePayload = {}),
1220+
(updatePayload[propKey] = attributeConfig.process(nextProp));
1221+
else if (isArrayImpl(nextProp))
1222+
for (var i = 0; i < nextProp.length; i++)
1223+
updatePayload = fastAddProperties(
1224+
updatePayload,
1225+
nextProp[i],
1226+
attributeConfig
1227+
);
1228+
else
1229+
updatePayload = fastAddProperties(
1230+
updatePayload,
1231+
nextProp,
1232+
attributeConfig
1233+
);
1234+
}
1235+
}
1236+
return updatePayload;
1237+
}
1238+
function addProperties(updatePayload, props, validAttributes) {
1239+
return enableAddPropertiesFastPath
1240+
? fastAddProperties(updatePayload, props, validAttributes)
1241+
: diffProperties(updatePayload, emptyObject$1, props, validAttributes);
1242+
}
12091243
function batchedUpdatesImpl(fn, bookkeeping) {
12101244
return fn(bookkeeping);
12111245
}
@@ -1604,9 +1638,8 @@ var scheduleTimeout = setTimeout,
16041638
cancelTimeout = clearTimeout;
16051639
function cloneHiddenInstance(instance) {
16061640
var node = instance.node;
1607-
var JSCompiler_inline_result = diffProperties(
1641+
var JSCompiler_inline_result = addProperties(
16081642
null,
1609-
emptyObject$1,
16101643
{ style: { display: "none" } },
16111644
instance.canonical.viewConfig.validAttributes
16121645
);
@@ -7351,9 +7384,8 @@ function completeWork(current, workInProgress, renderLanes) {
73517384
current = nextReactTag;
73527385
nextReactTag += 2;
73537386
renderLanes = getViewConfigForType(renderLanes);
7354-
newChildSet = diffProperties(
7387+
newChildSet = addProperties(
73557388
null,
7356-
emptyObject$1,
73577389
newProps,
73587390
renderLanes.validAttributes
73597391
);
@@ -10613,7 +10645,7 @@ var roots = new Map(),
1061310645
devToolsConfig$jscomp$inline_1118 = {
1061410646
findFiberByHostInstance: getInstanceFromNode,
1061510647
bundleType: 0,
10616-
version: "19.0.0-beta-9a489885",
10648+
version: "19.0.0-beta-5fd3967c",
1061710649
rendererPackageName: "react-native-renderer",
1061810650
rendererConfig: {
1061910651
getInspectorDataForInstance: getInspectorDataForInstance,
@@ -10656,7 +10688,7 @@ var internals$jscomp$inline_1385 = {
1065610688
scheduleRoot: null,
1065710689
setRefreshHandler: null,
1065810690
getCurrentFiber: null,
10659-
reconcilerVersion: "19.0.0-beta-9a489885"
10691+
reconcilerVersion: "19.0.0-beta-5fd3967c"
1066010692
};
1066110693
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
1066210694
var hook$jscomp$inline_1386 = __REACT_DEVTOOLS_GLOBAL_HOOK__;

0 commit comments

Comments
 (0)