/
githubmr
/
facebook-react
Обзор
Документация
Войти
/
githubmr
/
facebook-react
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
v18.2.0
packages/react-reconciler/src/ReactProfilerTimer.new.js
238 строк
6 KB
Brian Vaughn
Store commit durations on HostRoot for DevTools access (#20983)
16 мар 2021, 20:53
Не верифицирован
16 мар 2021, 20:53
466b26c
Код
Авторство
О чём код?
/** * Copyright (c) Facebook, Inc. and its 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 {Fiber} from './ReactInternalTypes'; import { enableProfilerCommitHooks, enableProfilerNestedUpdatePhase, enableProfilerTimer, } from 'shared/ReactFeatureFlags'; import {HostRoot, Profiler} from './ReactWorkTags'; // Intentionally not named imports because Rollup would use dynamic dispatch for // CommonJS interop named imports. import * as Scheduler from 'scheduler'; const {unstable_now: now} = Scheduler; export type ProfilerTimer = { getCommitTime(): number, isCurrentUpdateNested(): boolean, markNestedUpdateScheduled(): void, recordCommitTime(): void, startProfilerTimer(fiber: Fiber): void, stopProfilerTimerIfRunning(fiber: Fiber): void, stopProfilerTimerIfRunningAndRecordDelta(fiber: Fiber): void, syncNestedUpdateFlag(): void, ... }; let commitTime: number = 0; let layoutEffectStartTime: number = -1; let profilerStartTime: number = -1; let passiveEffectStartTime: number = -1; /** * Tracks whether the current update was a nested/cascading update (scheduled from a layout effect). * * The overall sequence is: * 1. render * 2. commit (and call `onRender`, `onCommit`) * 3. check for nested updates * 4. flush passive effects (and call `onPostCommit`) * * Nested updates are identified in step 3 above, * but step 4 still applies to the work that was just committed. * We use two flags to track nested updates then: * one tracks whether the upcoming update is a nested update, * and the other tracks whether the current update was a nested update. * The first value gets synced to the second at the start of the render phase. */ let currentUpdateIsNested: boolean = false; let nestedUpdateScheduled: boolean = false; function isCurrentUpdateNested(): boolean { return currentUpdateIsNested; } function markNestedUpdateScheduled(): void { if (enableProfilerNestedUpdatePhase) { nestedUpdateScheduled = true; } } function resetNestedUpdateFlag(): void { if (enableProfilerNestedUpdatePhase) { currentUpdateIsNested = false; nestedUpdateScheduled = false; } } function syncNestedUpdateFlag(): void { if (enableProfilerNestedUpdatePhase) { currentUpdateIsNested = nestedUpdateScheduled; nestedUpdateScheduled = false; } } function getCommitTime(): number { return commitTime; } function recordCommitTime(): void { if (!enableProfilerTimer) { return; } commitTime = now(); } function startProfilerTimer(fiber: Fiber): void { if (!enableProfilerTimer) { return; } profilerStartTime = now(); if (((fiber.actualStartTime: any): number) < 0) { fiber.actualStartTime = now(); } } function stopProfilerTimerIfRunning(fiber: Fiber): void { if (!enableProfilerTimer) { return; } profilerStartTime = -1; } function stopProfilerTimerIfRunningAndRecordDelta( fiber: Fiber, overrideBaseTime: boolean, ): void { if (!enableProfilerTimer) { return; } if (profilerStartTime >= 0) { const elapsedTime = now() - profilerStartTime; fiber.actualDuration += elapsedTime; if (overrideBaseTime) { fiber.selfBaseDuration = elapsedTime; } profilerStartTime = -1; } } function recordLayoutEffectDuration(fiber: Fiber): void { if (!enableProfilerTimer || !enableProfilerCommitHooks) { return; } if (layoutEffectStartTime >= 0) { const elapsedTime = now() - layoutEffectStartTime; layoutEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor // Or the root (for the DevTools Profiler to read) let parentFiber = fiber.return; while (parentFiber !== null) { switch (parentFiber.tag) { case HostRoot: const root = parentFiber.stateNode; root.effectDuration += elapsedTime; return; case Profiler: const parentStateNode = parentFiber.stateNode; parentStateNode.effectDuration += elapsedTime; return; } parentFiber = parentFiber.return; } } } function recordPassiveEffectDuration(fiber: Fiber): void { if (!enableProfilerTimer || !enableProfilerCommitHooks) { return; } if (passiveEffectStartTime >= 0) { const elapsedTime = now() - passiveEffectStartTime; passiveEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor // Or the root (for the DevTools Profiler to read) let parentFiber = fiber.return; while (parentFiber !== null) { switch (parentFiber.tag) { case HostRoot: const root = parentFiber.stateNode; if (root !== null) { root.passiveEffectDuration += elapsedTime; } return; case Profiler: const parentStateNode = parentFiber.stateNode; if (parentStateNode !== null) { // Detached fibers have their state node cleared out. // In this case, the return pointer is also cleared out, // so we won't be able to report the time spent in this Profiler's subtree. parentStateNode.passiveEffectDuration += elapsedTime; } return; } parentFiber = parentFiber.return; } } } function startLayoutEffectTimer(): void { if (!enableProfilerTimer || !enableProfilerCommitHooks) { return; } layoutEffectStartTime = now(); } function startPassiveEffectTimer(): void { if (!enableProfilerTimer || !enableProfilerCommitHooks) { return; } passiveEffectStartTime = now(); } function transferActualDuration(fiber: Fiber): void { // Transfer time spent rendering these children so we don't lose it // after we rerender. This is used as a helper in special cases // where we should count the work of multiple passes. let child = fiber.child; while (child) { fiber.actualDuration += child.actualDuration; child = child.sibling; } } export { getCommitTime, isCurrentUpdateNested, markNestedUpdateScheduled, recordCommitTime, recordLayoutEffectDuration, recordPassiveEffectDuration, resetNestedUpdateFlag, startLayoutEffectTimer, startPassiveEffectTimer, startProfilerTimer, stopProfilerTimerIfRunning, stopProfilerTimerIfRunningAndRecordDelta, syncNestedUpdateFlag, transferActualDuration, };