Skip to content

Commit 16e5343

Browse files
committed
Experiment with using an object literal for Fiber creation
Object literals should be faster at least on React Native with Hermes as the JS engine. It might also be interesting to confirm the old comments in this file from years ago are even still valid. Creating an object from a literal should be a simpler operation. It's a bit unfortunate that this introduces a bunch of copied code, but since we rearely update the fields on fibers, this seems like an okay tradeoff for a hot code path. An alternative would be some sort of macro system, but that doesn't seem worth the extra complexity.
1 parent 20e710a commit 16e5343

9 files changed

+231
-7
lines changed

packages/react-reconciler/src/ReactFiber.js

Lines changed: 219 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,17 @@ import {
2828
isHostSingletonType,
2929
} from './ReactFiberConfig';
3030
import {
31-
enableProfilerTimer,
32-
enableScopeAPI,
33-
enableLegacyHidden,
34-
forceConcurrentByDefaultForTesting,
3531
allowConcurrentByDefault,
36-
enableTransitionTracing,
32+
disableLegacyMode,
3733
enableDebugTracing,
3834
enableDO_NOT_USE_disableStrictPassiveEffect,
35+
enableLegacyHidden,
36+
enableObjectFiber,
37+
enableProfilerTimer,
3938
enableRenderableContext,
40-
disableLegacyMode,
39+
enableScopeAPI,
40+
enableTransitionTracing,
41+
forceConcurrentByDefaultForTesting,
4142
} from 'shared/ReactFeatureFlags';
4243
import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
4344
import {ConcurrentRoot} from './ReactRootTags';
@@ -222,7 +223,7 @@ function FiberNode(
222223
// is faster.
223224
// 5) It should be easy to port this to a C struct and keep a C implementation
224225
// compatible.
225-
function createFiber(
226+
function createFiberImplClass(
226227
tag: WorkTag,
227228
pendingProps: mixed,
228229
key: null | string,
@@ -232,6 +233,217 @@ function createFiber(
232233
return new FiberNode(tag, pendingProps, key, mode);
233234
}
234235

236+
function createFiberImplObjectDev(
237+
tag: WorkTag,
238+
pendingProps: mixed,
239+
key: null | string,
240+
mode: TypeOfMode,
241+
): Fiber {
242+
const fiber = {
243+
// Instance
244+
tag,
245+
key,
246+
elementType: null,
247+
type: null,
248+
stateNode: null,
249+
250+
// Fiber
251+
return: null,
252+
child: null,
253+
sibling: null,
254+
index: 0,
255+
256+
ref: null,
257+
refCleanup: null,
258+
259+
pendingProps,
260+
memoizedProps: null,
261+
updateQueue: null,
262+
memoizedState: null,
263+
dependencies: null,
264+
265+
mode,
266+
267+
// Effects
268+
flags: NoFlags,
269+
subtreeFlags: NoFlags,
270+
deletions: null,
271+
272+
lanes: NoLanes,
273+
childLanes: NoLanes,
274+
275+
alternate: null,
276+
277+
// __DEV__ only
278+
_debugInfo: null,
279+
_debugOwner: null,
280+
_debugNeedsRemount: false,
281+
_debugHookTypes: null,
282+
};
283+
if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
284+
Object.preventExtensions(fiber);
285+
}
286+
return fiber;
287+
}
288+
function createFiberImplObjectDevProfile(
289+
tag: WorkTag,
290+
pendingProps: mixed,
291+
key: null | string,
292+
mode: TypeOfMode,
293+
): Fiber {
294+
const fiber = {
295+
// Instance
296+
tag,
297+
key,
298+
elementType: null,
299+
type: null,
300+
stateNode: null,
301+
302+
// Fiber
303+
return: null,
304+
child: null,
305+
sibling: null,
306+
index: 0,
307+
308+
ref: null,
309+
refCleanup: null,
310+
311+
pendingProps,
312+
memoizedProps: null,
313+
updateQueue: null,
314+
memoizedState: null,
315+
dependencies: null,
316+
317+
mode,
318+
319+
// Effects
320+
flags: NoFlags,
321+
subtreeFlags: NoFlags,
322+
deletions: null,
323+
324+
lanes: NoLanes,
325+
childLanes: NoLanes,
326+
327+
alternate: null,
328+
329+
// enableProfilerTimer only
330+
actualDuration: 0,
331+
actualStartTime: -1,
332+
selfBaseDuration: 0,
333+
treeBaseDuration: 0,
334+
335+
// __DEV__ only
336+
_debugInfo: null,
337+
_debugOwner: null,
338+
_debugNeedsRemount: false,
339+
_debugHookTypes: null,
340+
};
341+
if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
342+
Object.preventExtensions(fiber);
343+
}
344+
return fiber;
345+
}
346+
function createFiberImplObjectProd(
347+
tag: WorkTag,
348+
pendingProps: mixed,
349+
key: null | string,
350+
mode: TypeOfMode,
351+
): Fiber {
352+
return {
353+
// Instance
354+
tag,
355+
key,
356+
elementType: null,
357+
type: null,
358+
stateNode: null,
359+
360+
// Fiber
361+
return: null,
362+
child: null,
363+
sibling: null,
364+
index: 0,
365+
366+
ref: null,
367+
refCleanup: null,
368+
369+
pendingProps,
370+
memoizedProps: null,
371+
updateQueue: null,
372+
memoizedState: null,
373+
dependencies: null,
374+
375+
mode,
376+
377+
// Effects
378+
flags: NoFlags,
379+
subtreeFlags: NoFlags,
380+
deletions: null,
381+
382+
lanes: NoLanes,
383+
childLanes: NoLanes,
384+
385+
alternate: null,
386+
};
387+
}
388+
function createFiberImplObjectProdProfile(
389+
tag: WorkTag,
390+
pendingProps: mixed,
391+
key: null | string,
392+
mode: TypeOfMode,
393+
): Fiber {
394+
return {
395+
// Instance
396+
tag,
397+
key,
398+
elementType: null,
399+
type: null,
400+
stateNode: null,
401+
402+
// Fiber
403+
return: null,
404+
child: null,
405+
sibling: null,
406+
index: 0,
407+
408+
ref: null,
409+
refCleanup: null,
410+
411+
pendingProps,
412+
memoizedProps: null,
413+
updateQueue: null,
414+
memoizedState: null,
415+
dependencies: null,
416+
417+
mode,
418+
419+
// Effects
420+
flags: NoFlags,
421+
subtreeFlags: NoFlags,
422+
deletions: null,
423+
424+
lanes: NoLanes,
425+
childLanes: NoLanes,
426+
427+
alternate: null,
428+
429+
// enableProfilerTimer only
430+
actualDuration: 0,
431+
actualStartTime: -1,
432+
selfBaseDuration: 0,
433+
treeBaseDuration: 0,
434+
};
435+
}
436+
437+
const createFiber = !enableObjectFiber
438+
? createFiberImplClass
439+
: __DEV__
440+
? enableProfilerTimer
441+
? createFiberImplObjectDevProfile
442+
: createFiberImplObjectDev
443+
: enableProfilerTimer
444+
? createFiberImplObjectProdProfile
445+
: createFiberImplObjectProd;
446+
235447
function shouldConstruct(Component: Function) {
236448
const prototype = Component.prototype;
237449
return !!(prototype && prototype.isReactComponent);

packages/shared/ReactFeatureFlags.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ export const enableTaint = __EXPERIMENTAL__;
8383

8484
export const enablePostpone = __EXPERIMENTAL__;
8585

86+
/**
87+
* Switches Fiber creation to a simple object instead of a constructor.
88+
*/
89+
export const enableObjectFiber = false;
90+
8691
export const enableTransitionTracing = false;
8792

8893
// No known bugs, but needs performance testing

packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ export const enableRenderableContext = __VARIANT__;
2727
export const enableUnifiedSyncLane = __VARIANT__;
2828
export const passChildrenWhenCloningPersistedNodes = __VARIANT__;
2929
export const useModernStrictMode = __VARIANT__;
30+
export const enableObjectFiber = __VARIANT__;

packages/shared/forks/ReactFeatureFlags.native-fb.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export const {
2525
enableComponentStackLocations,
2626
enableDeferRootSchedulingToMicrotask,
2727
enableInfiniteRenderLoopDetection,
28+
enableObjectFiber,
2829
enableRenderableContext,
2930
enableUnifiedSyncLane,
3031
passChildrenWhenCloningPersistedNodes,

packages/shared/forks/ReactFeatureFlags.native-oss.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export const enableSchedulingProfiler = __PROFILE__;
7272
export const enableLegacyCache = false;
7373
export const enableFetchInstrumentation = false;
7474
export const enablePostpone = false;
75+
export const enableObjectFiber = false;
7576
export const disableCommentsAsDOMContainers = true;
7677
export const disableInputAttributeSyncing = false;
7778
export const disableIEWorkarounds = true;

packages/shared/forks/ReactFeatureFlags.test-renderer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export const disableLegacyContext = true;
9090
export const disableDOMTestUtils = true;
9191
export const enableRenderableContext = true;
9292
export const enableReactTestRendererWarning = true;
93+
export const enableObjectFiber = false;
9394

9495
// Flow magic to verify the exports of this file match the original version.
9596
((((null: any): ExportsType): FeatureFlagsType): ExportsType);

packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export const disableStringRefs = false;
8484
export const enableReactTestRendererWarning = false;
8585
export const disableLegacyMode = false;
8686
export const disableDOMTestUtils = false;
87+
export const enableObjectFiber = false;
8788

8889
// Flow magic to verify the exports of this file match the original version.
8990
((((null: any): ExportsType): FeatureFlagsType): ExportsType);

packages/shared/forks/ReactFeatureFlags.test-renderer.www.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export const disableStringRefs = false;
8484
export const enableReactTestRendererWarning = false;
8585
export const disableLegacyMode = false;
8686
export const disableDOMTestUtils = false;
87+
export const enableObjectFiber = false;
8788

8889
// Flow magic to verify the exports of this file match the original version.
8990
((((null: any): ExportsType): FeatureFlagsType): ExportsType);

packages/shared/forks/ReactFeatureFlags.www.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ export const disableStringRefs = false;
114114
export const disableLegacyMode = __EXPERIMENTAL__;
115115

116116
export const disableDOMTestUtils = false;
117+
export const enableObjectFiber = false;
117118

118119
// Flow magic to verify the exports of this file match the original version.
119120
((((null: any): ExportsType): FeatureFlagsType): ExportsType);

0 commit comments

Comments
 (0)