Revert "[Scheduler] Profiling features (#16145)" (#16392)
This reverts commit a34ca7bce69c2f321daef0b8650ad6e7cfce366a.
Dan Abramov committed
Aug 14, 2019 at 20:02 UTC
4ba1412305be3c77b625a70e3c0b9a8638626bd0
18 files changed
+35
-919
.eslintrc.js
-2
@@ -142,8 +142,6 @@ module.exports = {
142
],
143
144
globals: {
145
- SharedArrayBuffer: true,
146
-
145
spyOnDev: true,
146
spyOnDevAndProd: true,
147
spyOnProd: true,
packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js
-1
@@ -136,7 +136,6 @@ describe('ReactDebugFiberPerf', () => {
136
require('shared/ReactFeatureFlags').enableProfilerTimer = false;
137
require('shared/ReactFeatureFlags').replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
138
require('shared/ReactFeatureFlags').debugRenderPhaseSideEffectsForStrictMode = false;
139
- require('scheduler/src/SchedulerFeatureFlags').enableProfiling = false;
139
140
// Import after the polyfill is set up:
141
React = require('react');
packages/scheduler/npm/umd/scheduler.development.js
-20
@@ -110,20 +110,6 @@
110
);
111
}
112
113
- function unstable_startLoggingProfilingEvents() {
114
- return global.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Scheduler.unstable_startLoggingProfilingEvents.apply(
115
- this,
116
- arguments
117
- );
118
- }
119
-
120
- function unstable_stopLoggingProfilingEvents() {
121
- return global.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Scheduler.unstable_stopLoggingProfilingEvents.apply(
122
- this,
123
- arguments
124
- );
125
- }
126
-
113
return Object.freeze({
114
unstable_now: unstable_now,
115
unstable_scheduleCallback: unstable_scheduleCallback,
@@ -138,8 +124,6 @@
124
unstable_pauseExecution: unstable_pauseExecution,
125
unstable_getFirstCallbackNode: unstable_getFirstCallbackNode,
126
unstable_forceFrameRate: unstable_forceFrameRate,
141
- unstable_startLoggingProfilingEvents: unstable_startLoggingProfilingEvents,
142
- unstable_stopLoggingProfilingEvents: unstable_stopLoggingProfilingEvents,
127
get unstable_IdlePriority() {
128
return global.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
129
.Scheduler.unstable_IdlePriority;
@@ -160,9 +144,5 @@
144
return global.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
145
.Scheduler.unstable_UserBlockingPriority;
146
},
163
- get unstable_sharedProfilingBuffer() {
164
- return global.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
165
- .Scheduler.unstable_getFirstCallbackNode;
166
- },
147
});
148
});
packages/scheduler/npm/umd/scheduler.production.min.js
-20
@@ -104,20 +104,6 @@
104
);
105
}
106
107
- function unstable_startLoggingProfilingEvents() {
108
- return global.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Scheduler.unstable_startLoggingProfilingEvents.apply(
109
- this,
110
- arguments
111
- );
112
- }
113
-
114
- function unstable_stopLoggingProfilingEvents() {
115
- return global.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Scheduler.unstable_stopLoggingProfilingEvents.apply(
116
- this,
117
- arguments
118
- );
119
- }
120
-
107
return Object.freeze({
108
unstable_now: unstable_now,
109
unstable_scheduleCallback: unstable_scheduleCallback,
@@ -132,8 +118,6 @@
118
unstable_pauseExecution: unstable_pauseExecution,
119
unstable_getFirstCallbackNode: unstable_getFirstCallbackNode,
120
unstable_forceFrameRate: unstable_forceFrameRate,
135
- unstable_startLoggingProfilingEvents: unstable_startLoggingProfilingEvents,
136
- unstable_stopLoggingProfilingEvents: unstable_stopLoggingProfilingEvents,
121
get unstable_IdlePriority() {
122
return global.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
123
.Scheduler.unstable_IdlePriority;
@@ -154,9 +138,5 @@
138
return global.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
139
.Scheduler.unstable_UserBlockingPriority;
140
},
157
- get unstable_sharedProfilingBuffer() {
158
- return global.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
159
- .Scheduler.unstable_getFirstCallbackNode;
160
- },
141
});
142
});
packages/scheduler/npm/umd/scheduler.profiling.min.js
-20
@@ -104,20 +104,6 @@
104
);
105
}
106
107
- function unstable_startLoggingProfilingEvents() {
108
- return global.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Scheduler.unstable_startLoggingProfilingEvents.apply(
109
- this,
110
- arguments
111
- );
112
- }
113
-
114
- function unstable_stopLoggingProfilingEvents() {
115
- return global.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Scheduler.unstable_stopLoggingProfilingEvents.apply(
116
- this,
117
- arguments
118
- );
119
- }
120
-
107
return Object.freeze({
108
unstable_now: unstable_now,
109
unstable_scheduleCallback: unstable_scheduleCallback,
@@ -132,8 +118,6 @@
118
unstable_pauseExecution: unstable_pauseExecution,
119
unstable_getFirstCallbackNode: unstable_getFirstCallbackNode,
120
unstable_forceFrameRate: unstable_forceFrameRate,
135
- unstable_startLoggingProfilingEvents: unstable_startLoggingProfilingEvents,
136
- unstable_stopLoggingProfilingEvents: unstable_stopLoggingProfilingEvents,
121
get unstable_IdlePriority() {
122
return global.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
123
.Scheduler.unstable_IdlePriority;
@@ -154,9 +138,5 @@
138
return global.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
139
.Scheduler.unstable_UserBlockingPriority;
140
},
157
- get unstable_sharedProfilingBuffer() {
158
- return global.React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
159
- .Scheduler.unstable_getFirstCallbackNode;
160
- },
141
});
142
});
packages/scheduler/src/Scheduler.js
+26
-131
@@ -8,14 +8,10 @@
8
9
/* eslint-disable no-var */
10
11
+import {enableSchedulerDebugging} from './SchedulerFeatureFlags';
12
import {
12
- enableSchedulerDebugging,
13
- enableProfiling,
14
-} from './SchedulerFeatureFlags';
15
-import {
16
- requestHostCallback as requestHostCallbackWithoutProfiling,
13
+ requestHostCallback,
14
requestHostTimeout,
18
- cancelHostCallback,
15
cancelHostTimeout,
16
shouldYieldToHost,
17
getCurrentTime,
@@ -25,26 +21,11 @@ import {
21
import {push, pop, peek} from './SchedulerMinHeap';
22
23
// TODO: Use symbols?
28
-import {
29
- ImmediatePriority,
30
- UserBlockingPriority,
31
- NormalPriority,
32
- LowPriority,
33
- IdlePriority,
34
-} from './SchedulerPriorities';
35
-import {
36
- sharedProfilingBuffer,
37
- markTaskRun,
38
- markTaskYield,
39
- markTaskCompleted,
40
- markTaskCanceled,
41
- markTaskErrored,
42
- markSchedulerSuspended,
43
- markSchedulerUnsuspended,
44
- markTaskStart,
45
- stopLoggingProfilingEvents,
46
- startLoggingProfilingEvents,
47
-} from './SchedulerProfiling';
24
+var ImmediatePriority = 1;
25
+var UserBlockingPriority = 2;
26
+var NormalPriority = 3;
27
+var LowPriority = 4;
28
+var IdlePriority = 5;
29
30
// Max 31 bit integer. The max integer size in V8 for 32-bit systems.
31
// Math.pow(2, 30) - 1
@@ -79,17 +60,15 @@ var isPerformingWork = false;
60
var isHostCallbackScheduled = false;
61
var isHostTimeoutScheduled = false;
62
82
-function requestHostCallbackWithProfiling(cb, time) {
83
- if (enableProfiling) {
84
- markSchedulerSuspended(time);
85
- requestHostCallbackWithoutProfiling(cb);
86
- }
63
+function flushTask(task, callback, currentTime) {
64
+ currentPriorityLevel = task.priorityLevel;
65
+ var didUserCallbackTimeout = task.expirationTime <= currentTime;
66
+ var continuationCallback = callback(didUserCallbackTimeout);
67
+ return typeof continuationCallback === 'function'
68
+ ? continuationCallback
69
+ : null;
70
}
71
89
-const requestHostCallback = enableProfiling
90
- ? requestHostCallbackWithProfiling
91
- : requestHostCallbackWithoutProfiling;
92
-
72
function advanceTimers(currentTime) {
73
// Check for tasks that are no longer delayed and add them to the queue.
74
let timer = peek(timerQueue);
@@ -102,10 +81,6 @@ function advanceTimers(currentTime) {
81
pop(timerQueue);
82
timer.sortIndex = timer.expirationTime;
83
push(taskQueue, timer);
105
- if (enableProfiling) {
106
- markTaskStart(timer);
107
- timer.isQueued = true;
108
- }
84
} else {
85
// Remaining timers are pending.
86
return;
@@ -121,7 +96,7 @@ function handleTimeout(currentTime) {
96
if (!isHostCallbackScheduled) {
97
if (peek(taskQueue) !== null) {
98
isHostCallbackScheduled = true;
124
- requestHostCallback(flushWork, currentTime);
99
+ requestHostCallback(flushWork);
100
} else {
101
const firstTimer = peek(timerQueue);
102
if (firstTimer !== null) {
@@ -132,10 +107,6 @@ function handleTimeout(currentTime) {
107
}
108
109
function flushWork(hasTimeRemaining, initialTime) {
135
- if (isHostCallbackScheduled) {
136
- markSchedulerUnsuspended(initialTime);
137
- }
138
-
110
// We'll need a host callback the next time work is scheduled.
111
isHostCallbackScheduled = false;
112
if (isHostTimeoutScheduled) {
@@ -164,24 +135,15 @@ function flushWork(hasTimeRemaining, initialTime) {
135
const callback = currentTask.callback;
136
if (callback !== null) {
137
currentTask.callback = null;
167
- currentPriorityLevel = currentTask.priorityLevel;
168
- const didUserCallbackTimeout =
169
- currentTask.expirationTime <= currentTime;
170
- markTaskRun(currentTask, currentTime);
171
- const continuationCallback = callback(didUserCallbackTimeout);
172
- currentTime = getCurrentTime();
173
- if (typeof continuationCallback === 'function') {
174
- currentTask.callback = continuationCallback;
175
- markTaskYield(currentTask, currentTime);
138
+ const continuation = flushTask(currentTask, callback, currentTime);
139
+ if (continuation !== null) {
140
+ currentTask.callback = continuation;
141
} else {
177
- if (enableProfiling) {
178
- markTaskCompleted(currentTask, currentTime);
179
- currentTask.isQueued = false;
180
- }
142
if (currentTask === peek(taskQueue)) {
143
pop(taskQueue);
144
}
145
}
146
+ currentTime = getCurrentTime();
147
advanceTimers(currentTime);
148
} else {
149
pop(taskQueue);
@@ -190,8 +152,6 @@ function flushWork(hasTimeRemaining, initialTime) {
152
}
153
// Return whether there's additional work
154
if (currentTask !== null) {
193
- markSchedulerSuspended(currentTime);
194
- isHostCallbackScheduled = true;
155
return true;
156
} else {
157
let firstTimer = peek(timerQueue);
@@ -200,18 +160,6 @@ function flushWork(hasTimeRemaining, initialTime) {
160
}
161
return false;
162
}
203
- } catch (error) {
204
- if (currentTask !== null) {
205
- if (enableProfiling) {
206
- const currentTime = getCurrentTime();
207
- markTaskErrored(currentTask, currentTime);
208
- currentTask.isQueued = false;
209
- }
210
- if (currentTask === peek(taskQueue)) {
211
- pop(taskQueue);
212
- }
213
- }
214
- throw error;
163
} finally {
164
currentTask = null;
165
currentPriorityLevel = previousPriorityLevel;
@@ -302,8 +250,6 @@ function unstable_scheduleCallback(priorityLevel, callback, options) {
250
251
var startTime;
252
var timeout;
305
- // TODO: Expose the current label when profiling, somehow
306
- // var label;
253
if (typeof options === 'object' && options !== null) {
254
var delay = options.delay;
255
if (typeof delay === 'number' && delay > 0) {
@@ -315,12 +261,6 @@ function unstable_scheduleCallback(priorityLevel, callback, options) {
261
typeof options.timeout === 'number'
262
? options.timeout
263
: timeoutForPriorityLevel(priorityLevel);
318
- // if (enableProfiling) {
319
- // var _label = options.label;
320
- // if (typeof _label === 'string') {
321
- // label = _label;
322
- // }
323
- // }
264
} else {
265
timeout = timeoutForPriorityLevel(priorityLevel);
266
startTime = currentTime;
@@ -329,7 +269,7 @@ function unstable_scheduleCallback(priorityLevel, callback, options) {
269
var expirationTime = startTime + timeout;
270
271
var newTask = {
332
- id: ++taskIdCounter,
272
+ id: taskIdCounter++,
273
callback,
274
priorityLevel,
275
startTime,
@@ -337,13 +277,6 @@ function unstable_scheduleCallback(priorityLevel, callback, options) {
277
sortIndex: -1,
278
};
279
340
- if (enableProfiling) {
341
- newTask.isQueued = false;
342
- // if (typeof options === 'object' && options !== null) {
343
- // newTask.label = label;
344
- // }
345
- }
346
-
280
if (startTime > currentTime) {
281
// This is a delayed task.
282
newTask.sortIndex = startTime;
@@ -362,15 +295,11 @@ function unstable_scheduleCallback(priorityLevel, callback, options) {
295
} else {
296
newTask.sortIndex = expirationTime;
297
push(taskQueue, newTask);
365
- if (enableProfiling) {
366
- markTaskStart(newTask, currentTime);
367
- newTask.isQueued = true;
368
- }
298
// Schedule a host callback, if needed. If we're already performing work,
299
// wait until the next time we yield.
300
if (!isHostCallbackScheduled && !isPerformingWork) {
301
isHostCallbackScheduled = true;
373
- requestHostCallback(flushWork, currentTime);
302
+ requestHostCallback(flushWork);
303
}
304
}
305
@@ -385,12 +314,7 @@ function unstable_continueExecution() {
314
isSchedulerPaused = false;
315
if (!isHostCallbackScheduled && !isPerformingWork) {
316
isHostCallbackScheduled = true;
388
- if (enableProfiling) {
389
- const currentTime = getCurrentTime();
390
- requestHostCallbackWithProfiling(flushWork, currentTime);
391
- } else {
392
- requestHostCallback(flushWork);
393
- }
317
+ requestHostCallback(flushWork);
318
}
319
}
320
@@ -399,26 +323,10 @@ function unstable_getFirstCallbackNode() {
323
}
324
325
function unstable_cancelCallback(task) {
402
- if (enableProfiling && task.isQueued) {
403
- const currentTime = getCurrentTime();
404
- markTaskCanceled(task, currentTime);
405
- task.isQueued = false;
406
- }
407
- if (task !== null && task === peek(taskQueue)) {
408
- pop(taskQueue);
409
- if (enableProfiling && !isPerformingWork && taskQueue.length === 0) {
410
- // The queue is now empty.
411
- const currentTime = getCurrentTime();
412
- markSchedulerUnsuspended(currentTime);
413
- isHostCallbackScheduled = false;
414
- cancelHostCallback();
415
- }
416
- } else {
417
- // Null out the callback to indicate the task has been canceled. (Can't
418
- // remove from the queue because you can't remove arbitrary nodes from an
419
- // array based heap, only the first one.)
420
- task.callback = null;
421
- }
326
+ // Null out the callback to indicate the task has been canceled. (Can't remove
327
+ // from the queue because you can't remove arbitrary nodes from an array based
328
+ // heap, only the first one.)
329
+ task.callback = null;
330
}
331
332
function unstable_getCurrentPriorityLevel() {
@@ -462,16 +370,3 @@ export {
370
getCurrentTime as unstable_now,
371
forceFrameRate as unstable_forceFrameRate,
372
};
465
-
466
-export const unstable_startLoggingProfilingEvents = enableProfiling
467
- ? startLoggingProfilingEvents
468
- : null;
469
-
470
-export const unstable_stopLoggingProfilingEvents = enableProfiling
471
- ? stopLoggingProfilingEvents
472
- : null;
473
-
474
-// Expose a shared array buffer that contains profiling information.
475
-export const unstable_sharedProfilingBuffer = enableProfiling
476
- ? sharedProfilingBuffer
477
- : null;
packages/scheduler/src/SchedulerFeatureFlags.js
-1
@@ -11,4 +11,3 @@ export const enableIsInputPending = false;
11
export const requestIdleCallbackBeforeFirstFrame = false;
12
export const requestTimerEventBeforeFirstFrame = false;
13
export const enableMessageLoopImplementation = false;
14
-export const enableProfiling = __PROFILE__;
packages/scheduler/src/SchedulerPriorities.js
deleted
-18
@@ -1,18 +0,0 @@
1
-/**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @flow
8
- */
9
-
10
-export type PriorityLevel = 0 | 1 | 2 | 3 | 4 | 5;
11
-
12
-// TODO: Use symbols?
13
-export const NoPriority = 0;
14
-export const ImmediatePriority = 1;
15
-export const UserBlockingPriority = 2;
16
-export const NormalPriority = 3;
17
-export const LowPriority = 4;
18
-export const IdlePriority = 5;
packages/scheduler/src/SchedulerProfiling.js
deleted
-210
@@ -1,210 +0,0 @@
1
-/**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @flow
8
- */
9
-
10
-import type {PriorityLevel} from './SchedulerPriorities';
11
-import {enableProfiling} from './SchedulerFeatureFlags';
12
-
13
-import {NoPriority} from './SchedulerPriorities';
14
-
15
-let runIdCounter: number = 0;
16
-let mainThreadIdCounter: number = 0;
17
-
18
-const profilingStateSize = 4;
19
-export const sharedProfilingBuffer =
20
- // $FlowFixMe Flow doesn't know about SharedArrayBuffer
21
- typeof SharedArrayBuffer === 'function'
22
- ? new SharedArrayBuffer(profilingStateSize * Int32Array.BYTES_PER_ELEMENT)
23
- : // $FlowFixMe Flow doesn't know about ArrayBuffer
24
- new ArrayBuffer(profilingStateSize * Int32Array.BYTES_PER_ELEMENT);
25
-
26
-const profilingState = enableProfiling
27
- ? new Int32Array(sharedProfilingBuffer)
28
- : null;
29
-
30
-const PRIORITY = 0;
31
-const CURRENT_TASK_ID = 1;
32
-const CURRENT_RUN_ID = 2;
33
-const QUEUE_SIZE = 3;
34
-
35
-if (enableProfiling && profilingState !== null) {
36
- profilingState[PRIORITY] = NoPriority;
37
- // This is maintained with a counter, because the size of the priority queue
38
- // array might include canceled tasks.
39
- profilingState[QUEUE_SIZE] = 0;
40
- profilingState[CURRENT_TASK_ID] = 0;
41
-}
42
-
43
-const INITIAL_EVENT_LOG_SIZE = 1000;
44
-
45
-let eventLogSize = 0;
46
-let eventLogBuffer = null;
47
-let eventLog = null;
48
-let eventLogIndex = 0;
49
-
50
-const TaskStartEvent = 1;
51
-const TaskCompleteEvent = 2;
52
-const TaskErrorEvent = 3;
53
-const TaskCancelEvent = 4;
54
-const TaskRunEvent = 5;
55
-const TaskYieldEvent = 6;
56
-const SchedulerSuspendEvent = 7;
57
-const SchedulerResumeEvent = 8;
58
-
59
-function logEvent(entries) {
60
- if (eventLog !== null) {
61
- const offset = eventLogIndex;
62
- eventLogIndex += entries.length;
63
- if (eventLogIndex + 1 > eventLogSize) {
64
- eventLogSize = eventLogIndex + 1;
65
- const newEventLog = new Int32Array(
66
- eventLogSize * Int32Array.BYTES_PER_ELEMENT,
67
- );
68
- newEventLog.set(eventLog);
69
- eventLogBuffer = newEventLog.buffer;
70
- eventLog = newEventLog;
71
- }
72
- eventLog.set(entries, offset);
73
- }
74
-}
75
-
76
-export function startLoggingProfilingEvents(): void {
77
- eventLogSize = INITIAL_EVENT_LOG_SIZE;
78
- eventLogBuffer = new ArrayBuffer(eventLogSize * Int32Array.BYTES_PER_ELEMENT);
79
- eventLog = new Int32Array(eventLogBuffer);
80
- eventLogIndex = 0;
81
-}
82
-
83
-export function stopLoggingProfilingEvents(): ArrayBuffer | null {
84
- const buffer = eventLogBuffer;
85
- eventLogBuffer = eventLog = null;
86
- return buffer;
87
-}
88
-
89
-export function markTaskStart(
90
- task: {id: number, priorityLevel: PriorityLevel},
91
- time: number,
92
-) {
93
- if (enableProfiling) {
94
- if (profilingState !== null) {
95
- profilingState[QUEUE_SIZE]++;
96
- }
97
- if (eventLog !== null) {
98
- logEvent([TaskStartEvent, time, task.id, task.priorityLevel]);
99
- }
100
- }
101
-}
102
-
103
-export function markTaskCompleted(
104
- task: {
105
- id: number,
106
- priorityLevel: PriorityLevel,
107
- },
108
- time: number,
109
-) {
110
- if (enableProfiling) {
111
- if (profilingState !== null) {
112
- profilingState[PRIORITY] = NoPriority;
113
- profilingState[CURRENT_TASK_ID] = 0;
114
- profilingState[QUEUE_SIZE]--;
115
- }
116
-
117
- if (eventLog !== null) {
118
- logEvent([TaskCompleteEvent, time, task.id]);
119
- }
120
- }
121
-}
122
-
123
-export function markTaskCanceled(
124
- task: {
125
- id: number,
126
- priorityLevel: PriorityLevel,
127
- },
128
- time: number,
129
-) {
130
- if (enableProfiling) {
131
- if (profilingState !== null) {
132
- profilingState[QUEUE_SIZE]--;
133
- }
134
-
135
- if (eventLog !== null) {
136
- logEvent([TaskCancelEvent, time, task.id]);
137
- }
138
- }
139
-}
140
-
141
-export function markTaskErrored(
142
- task: {
143
- id: number,
144
- priorityLevel: PriorityLevel,
145
- },
146
- time: number,
147
-) {
148
- if (enableProfiling) {
149
- if (profilingState !== null) {
150
- profilingState[PRIORITY] = NoPriority;
151
- profilingState[CURRENT_TASK_ID] = 0;
152
- profilingState[QUEUE_SIZE]--;
153
- }
154
-
155
- if (eventLog !== null) {
156
- logEvent([TaskErrorEvent, time, task.id]);
157
- }
158
- }
159
-}
160
-
161
-export function markTaskRun(
162
- task: {id: number, priorityLevel: PriorityLevel},
163
- time: number,
164
-) {
165
- if (enableProfiling) {
166
- runIdCounter++;
167
-
168
- if (profilingState !== null) {
169
- profilingState[PRIORITY] = task.priorityLevel;
170
- profilingState[CURRENT_TASK_ID] = task.id;
171
- profilingState[CURRENT_RUN_ID] = runIdCounter;
172
- }
173
-
174
- if (eventLog !== null) {
175
- logEvent([TaskRunEvent, time, task.id, runIdCounter]);
176
- }
177
- }
178
-}
179
-
180
-export function markTaskYield(task: {id: number}, time: number) {
181
- if (enableProfiling) {
182
- if (profilingState !== null) {
183
- profilingState[PRIORITY] = NoPriority;
184
- profilingState[CURRENT_TASK_ID] = 0;
185
- profilingState[CURRENT_RUN_ID] = 0;
186
- }
187
-
188
- if (eventLog !== null) {
189
- logEvent([TaskYieldEvent, time, task.id, runIdCounter]);
190
- }
191
- }
192
-}
193
-
194
-export function markSchedulerSuspended(time: number) {
195
- if (enableProfiling) {
196
- mainThreadIdCounter++;
197
-
198
- if (eventLog !== null) {
199
- logEvent([SchedulerSuspendEvent, time, mainThreadIdCounter]);
200
- }
201
- }
202
-}
203
-
204
-export function markSchedulerUnsuspended(time: number) {
205
- if (enableProfiling) {
206
- if (eventLog !== null) {
207
- logEvent([SchedulerResumeEvent, time, mainThreadIdCounter]);
208
- }
209
- }
210
-}
packages/scheduler/src/__tests__/SchedulerDOM-test.js
+3
-7
@@ -59,15 +59,11 @@ describe('SchedulerDOM', () => {
59
runPostMessageCallbacks(config);
60
}
61
62
- let frameSize;
63
- let startOfLatestFrame;
64
- let currentTime;
62
+ let frameSize = 33;
63
+ let startOfLatestFrame = 0;
64
+ let currentTime = 0;
65
66
beforeEach(() => {
67
- frameSize = 33;
68
- startOfLatestFrame = 0;
69
- currentTime = 0;
70
-
67
delete global.performance;
68
global.requestAnimationFrame = function(cb) {
69
return rAFCallbacks.push(() => {
packages/scheduler/src/__tests__/SchedulerProfiling-test.js
deleted
-449
@@ -1,449 +0,0 @@
1
-/**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @emails react-core
8
- * @jest-environment node
9
- */
10
-
11
-/* eslint-disable no-for-of-loops/no-for-of-loops */
12
-
13
-'use strict';
14
-
15
-let Scheduler;
16
-let sharedProfilingArray;
17
-// let runWithPriority;
18
-let ImmediatePriority;
19
-let UserBlockingPriority;
20
-let NormalPriority;
21
-let LowPriority;
22
-let IdlePriority;
23
-let scheduleCallback;
24
-let cancelCallback;
25
-// let wrapCallback;
26
-// let getCurrentPriorityLevel;
27
-// let shouldYield;
28
-
29
-function priorityLevelToString(priorityLevel) {
30
- switch (priorityLevel) {
31
- case ImmediatePriority:
32
- return 'Immediate';
33
- case UserBlockingPriority:
34
- return 'User-blocking';
35
- case NormalPriority:
36
- return 'Normal';
37
- case LowPriority:
38
- return 'Low';
39
- case IdlePriority:
40
- return 'Idle';
41
- default:
42
- return null;
43
- }
44
-}
45
-
46
-describe('Scheduler', () => {
47
- if (!__PROFILE__) {
48
- // The tests in this suite only apply when profiling is on
49
- it('profiling APIs are not available', () => {
50
- Scheduler = require('scheduler');
51
- expect(Scheduler.unstable_stopLoggingProfilingEvents).toBe(null);
52
- expect(Scheduler.unstable_sharedProfilingBuffer).toBe(null);
53
- });
54
- return;
55
- }
56
-
57
- beforeEach(() => {
58
- jest.resetModules();
59
- jest.mock('scheduler', () => require('scheduler/unstable_mock'));
60
- Scheduler = require('scheduler');
61
-
62
- sharedProfilingArray = new Int32Array(
63
- Scheduler.unstable_sharedProfilingBuffer,
64
- );
65
-
66
- // runWithPriority = Scheduler.unstable_runWithPriority;
67
- ImmediatePriority = Scheduler.unstable_ImmediatePriority;
68
- UserBlockingPriority = Scheduler.unstable_UserBlockingPriority;
69
- NormalPriority = Scheduler.unstable_NormalPriority;
70
- LowPriority = Scheduler.unstable_LowPriority;
71
- IdlePriority = Scheduler.unstable_IdlePriority;
72
- scheduleCallback = Scheduler.unstable_scheduleCallback;
73
- cancelCallback = Scheduler.unstable_cancelCallback;
74
- // wrapCallback = Scheduler.unstable_wrapCallback;
75
- // getCurrentPriorityLevel = Scheduler.unstable_getCurrentPriorityLevel;
76
- // shouldYield = Scheduler.unstable_shouldYield;
77
- });
78
-
79
- const PRIORITY = 0;
80
- const CURRENT_TASK_ID = 1;
81
- const CURRENT_RUN_ID = 2;
82
- const QUEUE_SIZE = 3;
83
-
84
- afterEach(() => {
85
- if (sharedProfilingArray[QUEUE_SIZE] !== 0) {
86
- throw Error(
87
- 'Test exited, but the shared profiling buffer indicates that a task ' +
88
- 'is still running',
89
- );
90
- }
91
- });
92
-
93
- const TaskStartEvent = 1;
94
- const TaskCompleteEvent = 2;
95
- const TaskErrorEvent = 3;
96
- const TaskCancelEvent = 4;
97
- const TaskRunEvent = 5;
98
- const TaskYieldEvent = 6;
99
- const SchedulerSuspendEvent = 7;
100
- const SchedulerResumeEvent = 8;
101
-
102
- function stopProfilingAndPrintFlamegraph() {
103
- const eventLog = new Int32Array(
104
- Scheduler.unstable_stopLoggingProfilingEvents(),
105
- );
106
-
107
- const tasks = new Map();
108
- const mainThreadRuns = [];
109
-
110
- let i = 0;
111
- processLog: while (i < eventLog.length) {
112
- const instruction = eventLog[i];
113
- const time = eventLog[i + 1];
114
- switch (instruction) {
115
- case 0: {
116
- break processLog;
117
- }
118
- case TaskStartEvent: {
119
- const taskId = eventLog[i + 2];
120
- const priorityLevel = eventLog[i + 3];
121
- const task = {
122
- id: taskId,
123
- priorityLevel,
124
- label: null,
125
- start: time,
126
- end: -1,
127
- exitStatus: null,
128
- runs: [],
129
- };
130
- tasks.set(taskId, task);
131
- i += 4;
132
- break;
133
- }
134
- case TaskCompleteEvent: {
135
- const taskId = eventLog[i + 2];
136
- const task = tasks.get(taskId);
137
- if (task === undefined) {
138
- throw Error('Task does not exist.');
139
- }
140
- task.end = time;
141
- task.exitStatus = 'completed';
142
- i += 3;
143
- break;
144
- }
145
- case TaskErrorEvent: {
146
- const taskId = eventLog[i + 2];
147
- const task = tasks.get(taskId);
148
- if (task === undefined) {
149
- throw Error('Task does not exist.');
150
- }
151
- task.end = time;
152
- task.exitStatus = 'errored';
153
- i += 3;
154
- break;
155
- }
156
- case TaskCancelEvent: {
157
- const taskId = eventLog[i + 2];
158
- const task = tasks.get(taskId);
159
- if (task === undefined) {
160
- throw Error('Task does not exist.');
161
- }
162
- task.end = time;
163
- task.exitStatus = 'canceled';
164
- i += 3;
165
- break;
166
- }
167
- case TaskRunEvent:
168
- case TaskYieldEvent: {
169
- const taskId = eventLog[i + 2];
170
- const task = tasks.get(taskId);
171
- if (task === undefined) {
172
- throw Error('Task does not exist.');
173
- }
174
- task.runs.push(time);
175
- i += 4;
176
- break;
177
- }
178
- case SchedulerSuspendEvent:
179
- case SchedulerResumeEvent: {
180
- mainThreadRuns.push(time);
181
- i += 3;
182
- break;
183
- }
184
- default: {
185
- throw Error('Unknown instruction type: ' + instruction);
186
- }
187
- }
188
- }
189
-
190
- // Now we can render the tasks as a flamegraph.
191
- const labelColumnWidth = 30;
192
- const msPerChar = 50;
193
-
194
- let result = '';
195
-
196
- const mainThreadLabelColumn = '!!! Main thread ';
197
- let mainThreadTimelineColumn = '';
198
- let isMainThreadBusy = false;
199
- for (const time of mainThreadRuns) {
200
- const index = time / msPerChar;
201
- mainThreadTimelineColumn += (isMainThreadBusy ? '█' : ' ').repeat(
202
- index - mainThreadTimelineColumn.length,
203
- );
204
- isMainThreadBusy = !isMainThreadBusy;
205
- }
206
- result += `${mainThreadLabelColumn}│${mainThreadTimelineColumn}\n`;
207
-
208
- const tasksByPriority = Array.from(tasks.values()).sort(
209
- (t1, t2) => t1.priorityLevel - t2.priorityLevel,
210
- );
211
-
212
- for (const task of tasksByPriority) {
213
- let label = task.label;
214
- if (label === undefined) {
215
- label = 'Task';
216
- }
217
- let labelColumn = `Task ${task.id} [${priorityLevelToString(
218
- task.priorityLevel,
219
- )}]`;
220
- labelColumn += ' '.repeat(labelColumnWidth - labelColumn.length - 1);
221
-
222
- // Add empty space up until the start mark
223
- let timelineColumn = ' '.repeat(task.start / msPerChar);
224
-
225
- let isRunning = false;
226
- for (const time of task.runs) {
227
- const index = time / msPerChar;
228
- timelineColumn += (isRunning ? '█' : '░').repeat(
229
- index - timelineColumn.length,
230
- );
231
- isRunning = !isRunning;
232
- }
233
-
234
- const endIndex = task.end / msPerChar;
235
- timelineColumn += (isRunning ? '█' : '░').repeat(
236
- endIndex - timelineColumn.length,
237
- );
238
-
239
- if (task.exitStatus !== 'completed') {
240
- timelineColumn += `🡐 ${task.exitStatus}`;
241
- }
242
-
243
- result += `${labelColumn}│${timelineColumn}\n`;
244
- }
245
-
246
- return '\n' + result;
247
- }
248
-
249
- function getProfilingInfo() {
250
- const queueSize = sharedProfilingArray[QUEUE_SIZE];
251
- if (queueSize === 0) {
252
- return 'Empty Queue';
253
- }
254
- const priorityLevel = sharedProfilingArray[PRIORITY];
255
- if (priorityLevel === 0) {
256
- return 'Suspended, Queue Size: ' + queueSize;
257
- }
258
- return (
259
- `Task: ${sharedProfilingArray[CURRENT_TASK_ID]}, ` +
260
- `Run: ${sharedProfilingArray[CURRENT_RUN_ID]}, ` +
261
- `Priority: ${priorityLevelToString(priorityLevel)}, ` +
262
- `Queue Size: ${sharedProfilingArray[QUEUE_SIZE]}`
263
- );
264
- }
265
-
266
- it('creates a basic flamegraph', () => {
267
- Scheduler.unstable_startLoggingProfilingEvents();
268
-
269
- Scheduler.unstable_advanceTime(100);
270
- scheduleCallback(
271
- NormalPriority,
272
- () => {
273
- Scheduler.unstable_advanceTime(300);
274
- Scheduler.unstable_yieldValue(getProfilingInfo());
275
- scheduleCallback(
276
- UserBlockingPriority,
277
- () => {
278
- Scheduler.unstable_yieldValue(getProfilingInfo());
279
- Scheduler.unstable_advanceTime(300);
280
- },
281
- {label: 'Bar'},
282
- );
283
- Scheduler.unstable_advanceTime(100);
284
- Scheduler.unstable_yieldValue('Yield');
285
- return () => {
286
- Scheduler.unstable_yieldValue(getProfilingInfo());
287
- Scheduler.unstable_advanceTime(300);
288
- };
289
- },
290
- {label: 'Foo'},
291
- );
292
- expect(Scheduler).toFlushAndYieldThrough([
293
- 'Task: 1, Run: 1, Priority: Normal, Queue Size: 1',
294
- 'Yield',
295
- ]);
296
- Scheduler.unstable_advanceTime(100);
297
- expect(Scheduler).toFlushAndYield([
298
- 'Task: 2, Run: 2, Priority: User-blocking, Queue Size: 2',
299
- 'Task: 1, Run: 3, Priority: Normal, Queue Size: 1',
300
- ]);
301
-
302
- expect(getProfilingInfo()).toEqual('Empty Queue');
303
-
304
- expect(stopProfilingAndPrintFlamegraph()).toEqual(
305
- `
306
-!!! Main thread │ ██
307
-Task 2 [User-blocking] │ ░░░░██████
308
-Task 1 [Normal] │ ████████░░░░░░░░██████
309
-`,
310
- );
311
- });
312
-
313
- it('marks when a task is canceled', () => {
314
- Scheduler.unstable_startLoggingProfilingEvents();
315
-
316
- const task = scheduleCallback(NormalPriority, () => {
317
- Scheduler.unstable_yieldValue(getProfilingInfo());
318
- Scheduler.unstable_advanceTime(300);
319
- Scheduler.unstable_yieldValue('Yield');
320
- return () => {
321
- Scheduler.unstable_yieldValue('Continuation');
322
- Scheduler.unstable_advanceTime(200);
323
- };
324
- });
325
-
326
- expect(Scheduler).toFlushAndYieldThrough([
327
- 'Task: 1, Run: 1, Priority: Normal, Queue Size: 1',
328
- 'Yield',
329
- ]);
330
- Scheduler.unstable_advanceTime(100);
331
-
332
- cancelCallback(task);
333
-
334
- // Advance more time. This should not affect the size of the main
335
- // thread row, since the Scheduler queue is empty.
336
- Scheduler.unstable_advanceTime(1000);
337
- expect(Scheduler).toFlushWithoutYielding();
338
-
339
- // The main thread row should end when the callback is cancelled.
340
- expect(stopProfilingAndPrintFlamegraph()).toEqual(
341
- `
342
-!!! Main thread │ ██
343
-Task 1 [Normal] │██████░░🡐 canceled
344
-`,
345
- );
346
- });
347
-
348
- it('marks when a task errors', () => {
349
- Scheduler.unstable_startLoggingProfilingEvents();
350
-
351
- scheduleCallback(NormalPriority, () => {
352
- Scheduler.unstable_advanceTime(300);
353
- throw Error('Oops');
354
- });
355
-
356
- expect(Scheduler).toFlushAndThrow('Oops');
357
- Scheduler.unstable_advanceTime(100);
358
-
359
- // Advance more time. This should not affect the size of the main
360
- // thread row, since the Scheduler queue is empty.
361
- Scheduler.unstable_advanceTime(1000);
362
- expect(Scheduler).toFlushWithoutYielding();
363
-
364
- // The main thread row should end when the callback is cancelled.
365
- expect(stopProfilingAndPrintFlamegraph()).toEqual(
366
- `
367
-!!! Main thread │
368
-Task 1 [Normal] │██████🡐 errored
369
-`,
370
- );
371
- });
372
-
373
- it('handles cancelling a task that already finished', () => {
374
- Scheduler.unstable_startLoggingProfilingEvents();
375
-
376
- const task = scheduleCallback(NormalPriority, () => {
377
- Scheduler.unstable_yieldValue('A');
378
- Scheduler.unstable_advanceTime(1000);
379
- });
380
- expect(Scheduler).toFlushAndYield(['A']);
381
- cancelCallback(task);
382
- expect(stopProfilingAndPrintFlamegraph()).toEqual(
383
- `
384
-!!! Main thread │
385
-Task 1 [Normal] │████████████████████
386
-`,
387
- );
388
- });
389
-
390
- it('handles cancelling a task multiple times', () => {
391
- Scheduler.unstable_startLoggingProfilingEvents();
392
-
393
- scheduleCallback(
394
- NormalPriority,
395
- () => {
396
- Scheduler.unstable_yieldValue('A');
397
- Scheduler.unstable_advanceTime(1000);
398
- },
399
- {label: 'A'},
400
- );
401
- Scheduler.unstable_advanceTime(200);
402
- const task = scheduleCallback(
403
- NormalPriority,
404
- () => {
405
- Scheduler.unstable_yieldValue('B');
406
- Scheduler.unstable_advanceTime(1000);
407
- },
408
- {label: 'B'},
409
- );
410
- Scheduler.unstable_advanceTime(400);
411
- cancelCallback(task);
412
- cancelCallback(task);
413
- cancelCallback(task);
414
- expect(Scheduler).toFlushAndYield(['A']);
415
- expect(stopProfilingAndPrintFlamegraph()).toEqual(
416
- `
417
-!!! Main thread │████████████
418
-Task 1 [Normal] │░░░░░░░░░░░░████████████████████
419
-Task 2 [Normal] │ ░░░░░░░░🡐 canceled
420
-`,
421
- );
422
- });
423
-
424
- it('handles cancelling a delayed task', () => {
425
- Scheduler.unstable_startLoggingProfilingEvents();
426
- const task = scheduleCallback(
427
- NormalPriority,
428
- () => Scheduler.unstable_yieldValue('A'),
429
- {delay: 1000},
430
- );
431
- cancelCallback(task);
432
- expect(Scheduler).toFlushWithoutYielding();
433
- expect(stopProfilingAndPrintFlamegraph()).toEqual(
434
- `
435
-!!! Main thread │
436
-`,
437
- );
438
- });
439
-
440
- it('resizes event log buffer if there are many events', () => {
441
- const tasks = [];
442
- for (let i = 0; i < 5000; i++) {
443
- tasks.push(scheduleCallback(NormalPriority, () => {}));
444
- }
445
- expect(getProfilingInfo()).toEqual('Suspended, Queue Size: 5000');
446
- tasks.forEach(task => cancelCallback(task));
447
- expect(getProfilingInfo()).toEqual('Empty Queue');
448
- });
449
-});
packages/scheduler/src/forks/SchedulerFeatureFlags.www.js
-2
@@ -13,5 +13,3 @@ export const {
13
requestTimerEventBeforeFirstFrame,
14
enableMessageLoopImplementation,
15
} = require('SchedulerFeatureFlags');
16
-
17
-export const enableProfiling = __PROFILE__;
packages/scheduler/src/forks/SchedulerHostConfig.default.js
+5
-11
@@ -53,9 +53,8 @@ if (
53
}
54
}
55
};
56
- const initialTime = Date.now();
56
getCurrentTime = function() {
58
- return Date.now() - initialTime;
57
+ return Date.now();
58
};
59
requestHostCallback = function(cb) {
60
if (_callback !== null) {
@@ -112,15 +111,10 @@ if (
111
typeof requestIdleCallback === 'function' &&
112
typeof cancelIdleCallback === 'function';
113
115
- if (
116
- typeof performance === 'object' &&
117
- typeof performance.now === 'function'
118
- ) {
119
- getCurrentTime = () => performance.now();
120
- } else {
121
- const initialTime = Date.now();
122
- getCurrentTime = () => Date.now() - initialTime;
123
- }
114
+ getCurrentTime =
115
+ typeof performance === 'object' && typeof performance.now === 'function'
116
+ ? () => performance.now()
117
+ : () => Date.now();
118
119
let isRAFLoopRunning = false;
120
let isMessageLoopRunning = false;
scripts/rollup/bundles.js
+1
-7
@@ -411,13 +411,7 @@ const bundles = [
411
412
/******* React Scheduler (experimental) *******/
413
{
414
- bundleTypes: [
415
- NODE_DEV,
416
- NODE_PROD,
417
- FB_WWW_DEV,
418
- FB_WWW_PROD,
419
- FB_WWW_PROFILING,
420
- ],
414
+ bundleTypes: [NODE_DEV, NODE_PROD, FB_WWW_DEV, FB_WWW_PROD],
415
moduleType: ISOMORPHIC,
416
entry: 'scheduler',
417
global: 'Scheduler',
scripts/rollup/validate/eslintrc.cjs.js
-5
@@ -21,11 +21,6 @@ module.exports = {
21
process: true,
22
setImmediate: true,
23
Buffer: true,
24
-
25
- // Scheduler profiling
26
- SharedArrayBuffer: true,
27
- Int32Array: true,
28
- ArrayBuffer: true,
24
},
25
parserOptions: {
26
ecmaVersion: 5,
scripts/rollup/validate/eslintrc.fb.js
-5
@@ -22,11 +22,6 @@ module.exports = {
22
// Node.js Server Rendering
23
setImmediate: true,
24
Buffer: true,
25
-
26
- // Scheduler profiling
27
- SharedArrayBuffer: true,
28
- Int32Array: true,
29
- ArrayBuffer: true,
25
},
26
parserOptions: {
27
ecmaVersion: 5,
scripts/rollup/validate/eslintrc.rn.js
-5
@@ -21,11 +21,6 @@ module.exports = {
21
// Fabric. See https://github.com/facebook/react/pull/15490
22
// for more information
23
nativeFabricUIManager: true,
24
-
25
- // Scheduler profiling
26
- SharedArrayBuffer: true,
27
- Int32Array: true,
28
- ArrayBuffer: true,
24
},
25
parserOptions: {
26
ecmaVersion: 5,
scripts/rollup/validate/eslintrc.umd.js
-5
@@ -24,11 +24,6 @@ module.exports = {
24
define: true,
25
require: true,
26
global: true,
27
-
28
- // Scheduler profiling
29
- SharedArrayBuffer: true,
30
- Int32Array: true,
31
- ArrayBuffer: true,
27
},
28
parserOptions: {
29
ecmaVersion: 5,