mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
* Facebook -> Meta in copyright rg --files | xargs sed -i 's#Copyright (c) Facebook, Inc. and its affiliates.#Copyright (c) Meta Platforms, Inc. and affiliates.#g' * Manual tweaks
180 lines
4.1 KiB
JavaScript
180 lines
4.1 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow
|
|
*/
|
|
|
|
import type {PriorityLevel} from './SchedulerPriorities';
|
|
import {enableProfiling} from './SchedulerFeatureFlags';
|
|
|
|
let runIdCounter: number = 0;
|
|
let mainThreadIdCounter: number = 0;
|
|
|
|
// Bytes per element is 4
|
|
const INITIAL_EVENT_LOG_SIZE = 131072;
|
|
const MAX_EVENT_LOG_SIZE = 524288; // Equivalent to 2 megabytes
|
|
|
|
let eventLogSize = 0;
|
|
let eventLogBuffer = null;
|
|
let eventLog = null;
|
|
let eventLogIndex = 0;
|
|
|
|
const TaskStartEvent = 1;
|
|
const TaskCompleteEvent = 2;
|
|
const TaskErrorEvent = 3;
|
|
const TaskCancelEvent = 4;
|
|
const TaskRunEvent = 5;
|
|
const TaskYieldEvent = 6;
|
|
const SchedulerSuspendEvent = 7;
|
|
const SchedulerResumeEvent = 8;
|
|
|
|
function logEvent(entries: Array<number | PriorityLevel>) {
|
|
if (eventLog !== null) {
|
|
const offset = eventLogIndex;
|
|
eventLogIndex += entries.length;
|
|
if (eventLogIndex + 1 > eventLogSize) {
|
|
eventLogSize *= 2;
|
|
if (eventLogSize > MAX_EVENT_LOG_SIZE) {
|
|
// Using console['error'] to evade Babel and ESLint
|
|
console['error'](
|
|
"Scheduler Profiling: Event log exceeded maximum size. Don't " +
|
|
'forget to call `stopLoggingProfilingEvents()`.',
|
|
);
|
|
stopLoggingProfilingEvents();
|
|
return;
|
|
}
|
|
const newEventLog = new Int32Array(eventLogSize * 4);
|
|
// $FlowFixMe[incompatible-call] found when upgrading Flow
|
|
newEventLog.set(eventLog);
|
|
eventLogBuffer = newEventLog.buffer;
|
|
eventLog = newEventLog;
|
|
}
|
|
eventLog.set(entries, offset);
|
|
}
|
|
}
|
|
|
|
export function startLoggingProfilingEvents(): void {
|
|
eventLogSize = INITIAL_EVENT_LOG_SIZE;
|
|
eventLogBuffer = new ArrayBuffer(eventLogSize * 4);
|
|
eventLog = new Int32Array(eventLogBuffer);
|
|
eventLogIndex = 0;
|
|
}
|
|
|
|
export function stopLoggingProfilingEvents(): ArrayBuffer | null {
|
|
const buffer = eventLogBuffer;
|
|
eventLogSize = 0;
|
|
eventLogBuffer = null;
|
|
eventLog = null;
|
|
eventLogIndex = 0;
|
|
return buffer;
|
|
}
|
|
|
|
export function markTaskStart(
|
|
task: {
|
|
id: number,
|
|
priorityLevel: PriorityLevel,
|
|
...
|
|
},
|
|
ms: number,
|
|
) {
|
|
if (enableProfiling) {
|
|
if (eventLog !== null) {
|
|
// performance.now returns a float, representing milliseconds. When the
|
|
// event is logged, it's coerced to an int. Convert to microseconds to
|
|
// maintain extra degrees of precision.
|
|
logEvent([TaskStartEvent, ms * 1000, task.id, task.priorityLevel]);
|
|
}
|
|
}
|
|
}
|
|
|
|
export function markTaskCompleted(
|
|
task: {
|
|
id: number,
|
|
priorityLevel: PriorityLevel,
|
|
...
|
|
},
|
|
ms: number,
|
|
) {
|
|
if (enableProfiling) {
|
|
if (eventLog !== null) {
|
|
logEvent([TaskCompleteEvent, ms * 1000, task.id]);
|
|
}
|
|
}
|
|
}
|
|
|
|
export function markTaskCanceled(
|
|
task: {
|
|
id: number,
|
|
priorityLevel: PriorityLevel,
|
|
...
|
|
},
|
|
ms: number,
|
|
) {
|
|
if (enableProfiling) {
|
|
if (eventLog !== null) {
|
|
logEvent([TaskCancelEvent, ms * 1000, task.id]);
|
|
}
|
|
}
|
|
}
|
|
|
|
export function markTaskErrored(
|
|
task: {
|
|
id: number,
|
|
priorityLevel: PriorityLevel,
|
|
...
|
|
},
|
|
ms: number,
|
|
) {
|
|
if (enableProfiling) {
|
|
if (eventLog !== null) {
|
|
logEvent([TaskErrorEvent, ms * 1000, task.id]);
|
|
}
|
|
}
|
|
}
|
|
|
|
export function markTaskRun(
|
|
task: {
|
|
id: number,
|
|
priorityLevel: PriorityLevel,
|
|
...
|
|
},
|
|
ms: number,
|
|
) {
|
|
if (enableProfiling) {
|
|
runIdCounter++;
|
|
|
|
if (eventLog !== null) {
|
|
logEvent([TaskRunEvent, ms * 1000, task.id, runIdCounter]);
|
|
}
|
|
}
|
|
}
|
|
|
|
export function markTaskYield(task: {id: number, ...}, ms: number) {
|
|
if (enableProfiling) {
|
|
if (eventLog !== null) {
|
|
logEvent([TaskYieldEvent, ms * 1000, task.id, runIdCounter]);
|
|
}
|
|
}
|
|
}
|
|
|
|
export function markSchedulerSuspended(ms: number) {
|
|
if (enableProfiling) {
|
|
mainThreadIdCounter++;
|
|
|
|
if (eventLog !== null) {
|
|
logEvent([SchedulerSuspendEvent, ms * 1000, mainThreadIdCounter]);
|
|
}
|
|
}
|
|
}
|
|
|
|
export function markSchedulerUnsuspended(ms: number) {
|
|
if (enableProfiling) {
|
|
if (eventLog !== null) {
|
|
logEvent([SchedulerResumeEvent, ms * 1000, mainThreadIdCounter]);
|
|
}
|
|
}
|
|
}
|