@samitouri / QOS-React-2 / commits / a8555c308e

[Transition Tracing] Add Tracing Marker Stack (#24661)

When a suspense boundary suspends or commits, we need to notify the corresponding tracing markers so that they know when to log that they've completed. To do this, we add a stack of tracing markers. In the begin phase, we will push the tracing markers onto the stack, and during the complete/unwind phase we will pop the tracing markers off the stack In a later PR, we will store the active tracing markers on the suspense boundary, and during the commit phase we will process the active tracing markers by adding/removing the boundary as appropriate.

Luna Ruan committed Jun 9, 2022 at 17:10 UTC a8555c308e06eacf807ec47caafd1e0e789d2c54
8 files changed +124 -2
packages/react-reconciler/src/ReactFiberBeginWork.new.js
+7
@@ -258,6 +258,7 @@ import {
258 getOffscreenDeferredCache,
259 getSuspendedTransitions,
260 } from './ReactFiberTransition.new';
261 +import {pushTracingMarker} from './ReactFiberTracingMarkerComponent.new';
262
263 const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
264
@@ -887,6 +888,7 @@ function updateTracingMarkerComponent(
888 return null;
889 }
890
891 + pushTracingMarker(workInProgress);
892 const nextChildren = workInProgress.pendingProps.children;
893 reconcileChildren(current, workInProgress, nextChildren, renderLanes);
894 return workInProgress.child;
@@ -3678,6 +3680,11 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
3680 }
3681 break;
3682 }
3683 + case TracingMarkerComponent: {
3684 + if (enableTransitionTracing) {
3685 + pushTracingMarker(workInProgress);
3686 + }
3687 + }
3688 }
3689 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
3690 }
packages/react-reconciler/src/ReactFiberBeginWork.old.js
+7
@@ -258,6 +258,7 @@ import {
258 getOffscreenDeferredCache,
259 getSuspendedTransitions,
260 } from './ReactFiberTransition.old';
261 +import {pushTracingMarker} from './ReactFiberTracingMarkerComponent.old';
262
263 const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
264
@@ -887,6 +888,7 @@ function updateTracingMarkerComponent(
888 return null;
889 }
890
891 + pushTracingMarker(workInProgress);
892 const nextChildren = workInProgress.pendingProps.children;
893 reconcileChildren(current, workInProgress, nextChildren, renderLanes);
894 return workInProgress.child;
@@ -3678,6 +3680,11 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
3680 }
3681 break;
3682 }
3683 + case TracingMarkerComponent: {
3684 + if (enableTransitionTracing) {
3685 + pushTracingMarker(workInProgress);
3686 + }
3687 + }
3688 }
3689 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
3690 }
packages/react-reconciler/src/ReactFiberCompleteWork.new.js
+2
@@ -165,6 +165,7 @@ import {transferActualDuration} from './ReactProfilerTimer.new';
165 import {popCacheProvider} from './ReactFiberCacheComponent.new';
166 import {popTreeContext} from './ReactFiberTreeContext.new';
167 import {popRootTransition, popTransition} from './ReactFiberTransition.new';
168 +import {popTracingMarker} from './ReactFiberTracingMarkerComponent.new';
169
170 function markUpdate(workInProgress: Fiber) {
171 // Tag the fiber with an update effect. This turns a Placement into
@@ -1585,6 +1586,7 @@ function completeWork(
1586 case TracingMarkerComponent: {
1587 if (enableTransitionTracing) {
1588 // Bubble subtree flags before so we can set the flag property
1589 + popTracingMarker(workInProgress);
1590 bubbleProperties(workInProgress);
1591 }
1592 return null;
packages/react-reconciler/src/ReactFiberCompleteWork.old.js
+2
@@ -165,6 +165,7 @@ import {transferActualDuration} from './ReactProfilerTimer.old';
165 import {popCacheProvider} from './ReactFiberCacheComponent.old';
166 import {popTreeContext} from './ReactFiberTreeContext.old';
167 import {popRootTransition, popTransition} from './ReactFiberTransition.old';
168 +import {popTracingMarker} from './ReactFiberTracingMarkerComponent.old';
169
170 function markUpdate(workInProgress: Fiber) {
171 // Tag the fiber with an update effect. This turns a Placement into
@@ -1585,6 +1586,7 @@ function completeWork(
1586 case TracingMarkerComponent: {
1587 if (enableTransitionTracing) {
1588 // Bubble subtree flags before so we can set the flag property
1589 + popTracingMarker(workInProgress);
1590 bubbleProperties(workInProgress);
1591 }
1592 return null;
packages/react-reconciler/src/ReactFiberTracingMarkerComponent.new.js
+36
@@ -9,8 +9,10 @@
9
10 import type {TransitionTracingCallbacks, Fiber} from './ReactInternalTypes';
11 import type {OffscreenInstance} from './ReactFiberOffscreenComponent';
12 +import type {StackCursor} from './ReactFiberStack.new';
13
14 import {enableTransitionTracing} from 'shared/ReactFeatureFlags';
15 +import {createCursor, push, pop} from './ReactFiberStack.new';
16
17 export type SuspenseInfo = {name: string | null};
18
@@ -71,3 +73,37 @@ export function processTransitionCallbacks(
73 }
74 }
75 }
76 +
77 +// For every tracing marker, store a pointer to it. We will later access it
78 +// to get the set of suspense boundaries that need to resolve before the
79 +// tracing marker can be logged as complete
80 +// This code lives separate from the ReactFiberTransition code because
81 +// we push and pop on the tracing marker, not the suspense boundary
82 +const tracingMarkerStack: StackCursor<Array<Fiber> | null> = createCursor(null);
83 +
84 +export function pushTracingMarker(workInProgress: Fiber): void {
85 + if (enableTransitionTracing) {
86 + if (tracingMarkerStack.current === null) {
87 + push(tracingMarkerStack, [workInProgress], workInProgress);
88 + } else {
89 + push(
90 + tracingMarkerStack,
91 + tracingMarkerStack.current.concat(workInProgress),
92 + workInProgress,
93 + );
94 + }
95 + }
96 +}
97 +
98 +export function popTracingMarker(workInProgress: Fiber): void {
99 + if (enableTransitionTracing) {
100 + pop(tracingMarkerStack, workInProgress);
101 + }
102 +}
103 +
104 +export function getTracingMarkers(): Array<Fiber> | null {
105 + if (enableTransitionTracing) {
106 + return tracingMarkerStack.current;
107 + }
108 + return null;
109 +}
packages/react-reconciler/src/ReactFiberTracingMarkerComponent.old.js
+36
@@ -9,8 +9,10 @@
9
10 import type {TransitionTracingCallbacks, Fiber} from './ReactInternalTypes';
11 import type {OffscreenInstance} from './ReactFiberOffscreenComponent';
12 +import type {StackCursor} from './ReactFiberStack.old';
13
14 import {enableTransitionTracing} from 'shared/ReactFeatureFlags';
15 +import {createCursor, push, pop} from './ReactFiberStack.old';
16
17 export type SuspenseInfo = {name: string | null};
18
@@ -71,3 +73,37 @@ export function processTransitionCallbacks(
73 }
74 }
75 }
76 +
77 +// For every tracing marker, store a pointer to it. We will later access it
78 +// to get the set of suspense boundaries that need to resolve before the
79 +// tracing marker can be logged as complete
80 +// This code lives separate from the ReactFiberTransition code because
81 +// we push and pop on the tracing marker, not the suspense boundary
82 +const tracingMarkerStack: StackCursor<Array<Fiber> | null> = createCursor(null);
83 +
84 +export function pushTracingMarker(workInProgress: Fiber): void {
85 + if (enableTransitionTracing) {
86 + if (tracingMarkerStack.current === null) {
87 + push(tracingMarkerStack, [workInProgress], workInProgress);
88 + } else {
89 + push(
90 + tracingMarkerStack,
91 + tracingMarkerStack.current.concat(workInProgress),
92 + workInProgress,
93 + );
94 + }
95 + }
96 +}
97 +
98 +export function popTracingMarker(workInProgress: Fiber): void {
99 + if (enableTransitionTracing) {
100 + pop(tracingMarkerStack, workInProgress);
101 + }
102 +}
103 +
104 +export function getTracingMarkers(): Array<Fiber> | null {
105 + if (enableTransitionTracing) {
106 + return tracingMarkerStack.current;
107 + }
108 + return null;
109 +}
packages/react-reconciler/src/ReactFiberUnwindWork.new.js
+17 -1
@@ -25,10 +25,15 @@ import {
25 OffscreenComponent,
26 LegacyHiddenComponent,
27 CacheComponent,
28 + TracingMarkerComponent,
29 } from './ReactWorkTags';
30 import {DidCapture, NoFlags, ShouldCapture} from './ReactFiberFlags';
31 import {NoMode, ProfileMode} from './ReactTypeOfMode';
31 -import {enableProfilerTimer, enableCache} from 'shared/ReactFeatureFlags';
32 +import {
33 + enableProfilerTimer,
34 + enableCache,
35 + enableTransitionTracing,
36 +} from 'shared/ReactFeatureFlags';
37
38 import {popHostContainer, popHostContext} from './ReactFiberHostContext.new';
39 import {popSuspenseContext} from './ReactFiberSuspenseContext.new';
@@ -44,6 +49,7 @@ import {popCacheProvider} from './ReactFiberCacheComponent.new';
49 import {transferActualDuration} from './ReactProfilerTimer.new';
50 import {popTreeContext} from './ReactFiberTreeContext.new';
51 import {popRootTransition, popTransition} from './ReactFiberTransition.new';
52 +import {popTracingMarker} from './ReactFiberTracingMarkerComponent.new';
53
54 function unwindWork(
55 current: Fiber | null,
@@ -154,6 +160,11 @@ function unwindWork(
160 popCacheProvider(workInProgress, cache);
161 }
162 return null;
163 + case TracingMarkerComponent:
164 + if (enableTransitionTracing) {
165 + popTracingMarker(workInProgress);
166 + }
167 + return null;
168 default:
169 return null;
170 }
@@ -217,6 +228,11 @@ function unwindInterruptedWork(
228 popCacheProvider(interruptedWork, cache);
229 }
230 break;
231 + case TracingMarkerComponent:
232 + if (enableTransitionTracing) {
233 + popTracingMarker(interruptedWork);
234 + }
235 + break;
236 default:
237 break;
238 }
packages/react-reconciler/src/ReactFiberUnwindWork.old.js
+17 -1
@@ -25,10 +25,15 @@ import {
25 OffscreenComponent,
26 LegacyHiddenComponent,
27 CacheComponent,
28 + TracingMarkerComponent,
29 } from './ReactWorkTags';
30 import {DidCapture, NoFlags, ShouldCapture} from './ReactFiberFlags';
31 import {NoMode, ProfileMode} from './ReactTypeOfMode';
31 -import {enableProfilerTimer, enableCache} from 'shared/ReactFeatureFlags';
32 +import {
33 + enableProfilerTimer,
34 + enableCache,
35 + enableTransitionTracing,
36 +} from 'shared/ReactFeatureFlags';
37
38 import {popHostContainer, popHostContext} from './ReactFiberHostContext.old';
39 import {popSuspenseContext} from './ReactFiberSuspenseContext.old';
@@ -44,6 +49,7 @@ import {popCacheProvider} from './ReactFiberCacheComponent.old';
49 import {transferActualDuration} from './ReactProfilerTimer.old';
50 import {popTreeContext} from './ReactFiberTreeContext.old';
51 import {popRootTransition, popTransition} from './ReactFiberTransition.old';
52 +import {popTracingMarker} from './ReactFiberTracingMarkerComponent.old';
53
54 function unwindWork(
55 current: Fiber | null,
@@ -154,6 +160,11 @@ function unwindWork(
160 popCacheProvider(workInProgress, cache);
161 }
162 return null;
163 + case TracingMarkerComponent:
164 + if (enableTransitionTracing) {
165 + popTracingMarker(workInProgress);
166 + }
167 + return null;
168 default:
169 return null;
170 }
@@ -217,6 +228,11 @@ function unwindInterruptedWork(
228 popCacheProvider(interruptedWork, cache);
229 }
230 break;
231 + case TracingMarkerComponent:
232 + if (enableTransitionTracing) {
233 + popTracingMarker(interruptedWork);
234 + }
235 + break;
236 default:
237 break;
238 }