Skip to content

Commit 773eed7

Browse files
flarnierhagigi
authored andcommitted
Update user timing to record the timeout deadline with 'waiting' events (facebook#12479)
* Update user timing to record the timeout deadline with 'waiting' events **what is the change?:** When we are processing work during reconciliation, we have a "timeout" deadline to finish the work. It's a safety measure that forces things to finish up synchronously if they are taking too long. The "timeout" is different depending on the type of interaction which triggered the reconciliation. We currently have a shorter "timeout" for "interactive updates", meaning we will try to finish work faster if the reconciliation was triggered by a click or other user interaction. For collecting more data in our logs we want to differentiate the 'waiting for async callback...' events based on the "timeout" so I'm adding that to the logging. One interesting note - in one of the snapshot tests the "timeout" was super high. Going to look into that. **why make this change?:** Right now we are debugging cases where an interaction triggers a reconciliation and the "waiting for async callback...' events are too long, getting blocked because the main thread is too busy. We are keeping logs of these user timing events and want to filter to focus on the reconciliation triggered by interaction. **test plan:** Manually tested and also updated snapshot tests. (Flarnie will insert a screenshot) * Improve wording of message * ran prettier
1 parent 60fe8ae commit 773eed7

File tree

3 files changed

+34
-28
lines changed

3 files changed

+34
-28
lines changed

packages/react-reconciler/src/ReactDebugFiberPerf.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,13 +248,18 @@ export function startRequestCallbackTimer(): void {
248248
}
249249
}
250250

251-
export function stopRequestCallbackTimer(didExpire: boolean): void {
251+
export function stopRequestCallbackTimer(
252+
didExpire: boolean,
253+
expirationTime: number,
254+
): void {
252255
if (enableUserTimingAPI) {
253256
if (supportsUserTiming) {
254257
isWaitingForCallback = false;
255258
const warning = didExpire ? 'React was blocked by main thread' : null;
256259
endMark(
257-
'(Waiting for async callback...)',
260+
`(Waiting for async callback... will force flush in ${
261+
expirationTime
262+
} ms)`,
258263
'(Waiting for async callback...)',
259264
warning,
260265
);

packages/react-reconciler/src/ReactFiberScheduler.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1448,7 +1448,8 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
14481448

14491449
if (enableUserTimingAPI && deadline !== null) {
14501450
const didExpire = nextFlushedExpirationTime < recalculateCurrentTime();
1451-
stopRequestCallbackTimer(didExpire);
1451+
const timeout = expirationTimeToMs(nextFlushedExpirationTime);
1452+
stopRequestCallbackTimer(didExpire, timeout);
14521453
}
14531454

14541455
if (isAsync) {

packages/react-reconciler/src/__tests__/__snapshots__/ReactIncrementalPerf-test.internal.js.snap

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

33
exports[`ReactDebugFiberPerf captures all lifecycles 1`] = `
4-
"⚛ (Waiting for async callback...)
4+
"⚛ (Waiting for async callback... will force flush in 5230 ms)
55
66
// Mount
77
⚛ (React Tree Reconciliation)
@@ -15,7 +15,7 @@ exports[`ReactDebugFiberPerf captures all lifecycles 1`] = `
1515
⚛ (Calling Lifecycle Methods: 1 Total)
1616
⚛ AllLifecycles.componentDidMount
1717
18-
⚛ (Waiting for async callback...)
18+
⚛ (Waiting for async callback... will force flush in 5230 ms)
1919
2020
// Update
2121
⚛ (React Tree Reconciliation)
@@ -31,7 +31,7 @@ exports[`ReactDebugFiberPerf captures all lifecycles 1`] = `
3131
⚛ (Calling Lifecycle Methods: 2 Total)
3232
⚛ AllLifecycles.componentDidUpdate
3333
34-
⚛ (Waiting for async callback...)
34+
⚛ (Waiting for async callback... will force flush in 5230 ms)
3535
3636
// Unmount
3737
⚛ (React Tree Reconciliation)
@@ -45,7 +45,7 @@ exports[`ReactDebugFiberPerf captures all lifecycles 1`] = `
4545
`;
4646

4747
exports[`ReactDebugFiberPerf deduplicates lifecycle names during commit to reduce overhead 1`] = `
48-
"⚛ (Waiting for async callback...)
48+
"⚛ (Waiting for async callback... will force flush in 5230 ms)
4949
5050
// The commit phase should mention A and B just once
5151
⚛ (React Tree Reconciliation)
@@ -62,7 +62,7 @@ exports[`ReactDebugFiberPerf deduplicates lifecycle names during commit to reduc
6262
⚛ A.componentDidUpdate
6363
⚛ B.componentDidUpdate
6464
65-
⚛ (Waiting for async callback...)
65+
⚛ (Waiting for async callback... will force flush in 5230 ms)
6666
6767
// Because of deduplication, we don't know B was cascading,
6868
// but we should still see the warning for the commit phase.
@@ -112,7 +112,7 @@ exports[`ReactDebugFiberPerf does not schedule an extra callback if setState is
112112
`;
113113

114114
exports[`ReactDebugFiberPerf does not treat setState from cWM or cWRP as cascading 1`] = `
115-
"⚛ (Waiting for async callback...)
115+
"⚛ (Waiting for async callback... will force flush in 5230 ms)
116116
117117
// Should not print a warning
118118
⚛ (React Tree Reconciliation)
@@ -125,7 +125,7 @@ exports[`ReactDebugFiberPerf does not treat setState from cWM or cWRP as cascadi
125125
⚛ (Committing Host Effects: 1 Total)
126126
⚛ (Calling Lifecycle Methods: 0 Total)
127127
128-
⚛ (Waiting for async callback...)
128+
⚛ (Waiting for async callback... will force flush in 5230 ms)
129129
130130
// Should not print a warning
131131
⚛ (React Tree Reconciliation)
@@ -141,7 +141,7 @@ exports[`ReactDebugFiberPerf does not treat setState from cWM or cWRP as cascadi
141141
`;
142142

143143
exports[`ReactDebugFiberPerf measures a simple reconciliation 1`] = `
144-
"⚛ (Waiting for async callback...)
144+
"⚛ (Waiting for async callback... will force flush in 5230 ms)
145145
146146
// Mount
147147
⚛ (React Tree Reconciliation)
@@ -153,7 +153,7 @@ exports[`ReactDebugFiberPerf measures a simple reconciliation 1`] = `
153153
⚛ (Committing Host Effects: 1 Total)
154154
⚛ (Calling Lifecycle Methods: 0 Total)
155155
156-
⚛ (Waiting for async callback...)
156+
⚛ (Waiting for async callback... will force flush in 5230 ms)
157157
158158
// Update
159159
⚛ (React Tree Reconciliation)
@@ -165,7 +165,7 @@ exports[`ReactDebugFiberPerf measures a simple reconciliation 1`] = `
165165
⚛ (Committing Host Effects: 2 Total)
166166
⚛ (Calling Lifecycle Methods: 2 Total)
167167
168-
⚛ (Waiting for async callback...)
168+
⚛ (Waiting for async callback... will force flush in 5230 ms)
169169
170170
// Unmount
171171
⚛ (React Tree Reconciliation)
@@ -178,22 +178,22 @@ exports[`ReactDebugFiberPerf measures a simple reconciliation 1`] = `
178178
`;
179179

180180
exports[`ReactDebugFiberPerf measures deferred work in chunks 1`] = `
181-
"⚛ (Waiting for async callback...)
181+
"⚛ (Waiting for async callback... will force flush in 5230 ms)
182182
183183
// Start mounting Parent and A
184184
⚛ (React Tree Reconciliation)
185185
⚛ Parent [mount]
186186
⚛ A [mount]
187187
⚛ Child [mount]
188188
189-
⚛ (Waiting for async callback...)
189+
⚛ (Waiting for async callback... will force flush in 5230 ms)
190190
191191
// Mount B just a little (but not enough to memoize)
192192
⚛ (React Tree Reconciliation)
193193
⚛ Parent [mount]
194194
⚛ B [mount]
195195
196-
⚛ (Waiting for async callback...)
196+
⚛ (Waiting for async callback... will force flush in 5230 ms)
197197
198198
// Complete B and Parent
199199
⚛ (React Tree Reconciliation)
@@ -218,7 +218,7 @@ exports[`ReactDebugFiberPerf measures deprioritized work 1`] = `
218218
⚛ (Committing Host Effects: 1 Total)
219219
⚛ (Calling Lifecycle Methods: 0 Total)
220220
221-
⚛ (Waiting for async callback...)
221+
⚛ (Waiting for async callback... will force flush in 10737418210 ms)
222222
223223
// Flush the child
224224
⚛ (React Tree Reconciliation)
@@ -232,7 +232,7 @@ exports[`ReactDebugFiberPerf measures deprioritized work 1`] = `
232232
`;
233233

234234
exports[`ReactDebugFiberPerf recovers from caught errors 1`] = `
235-
"⚛ (Waiting for async callback...)
235+
"⚛ (Waiting for async callback... will force flush in 5230 ms)
236236
237237
// Stop on Baddie and restart from Boundary
238238
⚛ (React Tree Reconciliation)
@@ -262,7 +262,7 @@ exports[`ReactDebugFiberPerf recovers from caught errors 1`] = `
262262
`;
263263

264264
exports[`ReactDebugFiberPerf recovers from fatal errors 1`] = `
265-
"⚛ (Waiting for async callback...)
265+
"⚛ (Waiting for async callback... will force flush in 5230 ms)
266266
267267
// Will fatal
268268
⚛ (React Tree Reconciliation)
@@ -276,7 +276,7 @@ exports[`ReactDebugFiberPerf recovers from fatal errors 1`] = `
276276
⚛ (Committing Host Effects: 1 Total)
277277
⚛ (Calling Lifecycle Methods: 0 Total)
278278
279-
⚛ (Waiting for async callback...)
279+
⚛ (Waiting for async callback... will force flush in 5230 ms)
280280
281281
// Will reconcile from a clean state
282282
⚛ (React Tree Reconciliation)
@@ -291,7 +291,7 @@ exports[`ReactDebugFiberPerf recovers from fatal errors 1`] = `
291291
`;
292292

293293
exports[`ReactDebugFiberPerf skips parents during setState 1`] = `
294-
"⚛ (Waiting for async callback...)
294+
"⚛ (Waiting for async callback... will force flush in 5230 ms)
295295
296296
// Should include just A and B, no Parents
297297
⚛ (React Tree Reconciliation)
@@ -306,7 +306,7 @@ exports[`ReactDebugFiberPerf skips parents during setState 1`] = `
306306
`;
307307

308308
exports[`ReactDebugFiberPerf supports portals 1`] = `
309-
"⚛ (Waiting for async callback...)
309+
"⚛ (Waiting for async callback... will force flush in 5230 ms)
310310
311311
⚛ (React Tree Reconciliation)
312312
⚛ Parent [mount]
@@ -320,7 +320,7 @@ exports[`ReactDebugFiberPerf supports portals 1`] = `
320320
`;
321321

322322
exports[`ReactDebugFiberPerf supports returns 1`] = `
323-
"⚛ (Waiting for async callback...)
323+
"⚛ (Waiting for async callback... will force flush in 5230 ms)
324324
325325
⚛ (React Tree Reconciliation)
326326
⚛ App [mount]
@@ -339,12 +339,12 @@ exports[`ReactDebugFiberPerf supports returns 1`] = `
339339
`;
340340

341341
exports[`ReactDebugFiberPerf warns if an in-progress update is interrupted 1`] = `
342-
"⚛ (Waiting for async callback...)
342+
"⚛ (Waiting for async callback... will force flush in 5230 ms)
343343
344344
⚛ (React Tree Reconciliation)
345345
⚛ Foo [mount]
346346
347-
⚛ (Waiting for async callback...)
347+
⚛ (Waiting for async callback... will force flush in 5230 ms)
348348
⛔ (React Tree Reconciliation) Warning: A top-level update interrupted the previous render
349349
⚛ Foo [mount]
350350
⚛ (Committing Changes)
@@ -362,7 +362,7 @@ exports[`ReactDebugFiberPerf warns if an in-progress update is interrupted 1`] =
362362
`;
363363

364364
exports[`ReactDebugFiberPerf warns if async work expires (starvation) 1`] = `
365-
"⛔ (Waiting for async callback...) Warning: React was blocked by main thread
365+
"⛔ (Waiting for async callback... will force flush in 5230 ms) Warning: React was blocked by main thread
366366
367367
⚛ (React Tree Reconciliation)
368368
⚛ Foo [mount]
@@ -375,7 +375,7 @@ exports[`ReactDebugFiberPerf warns if async work expires (starvation) 1`] = `
375375
`;
376376

377377
exports[`ReactDebugFiberPerf warns on cascading renders from setState 1`] = `
378-
"⚛ (Waiting for async callback...)
378+
"⚛ (Waiting for async callback... will force flush in 5230 ms)
379379
380380
// Should print a warning
381381
⚛ (React Tree Reconciliation)
@@ -399,7 +399,7 @@ exports[`ReactDebugFiberPerf warns on cascading renders from setState 1`] = `
399399
`;
400400

401401
exports[`ReactDebugFiberPerf warns on cascading renders from top-level render 1`] = `
402-
"⚛ (Waiting for async callback...)
402+
"⚛ (Waiting for async callback... will force flush in 5230 ms)
403403
404404
// Rendering the first root
405405
⚛ (React Tree Reconciliation)

0 commit comments

Comments
 (0)