From e5f6b91d294d0c1260ce5079ed0192b43ccd3e82 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 23 Feb 2021 11:31:29 -0500 Subject: [PATCH] Add Lane labels to scheduling profiler marks (#20808) This commit changes scheduling profiler marks from a format like '--schedule-render-1' to '--schedule-render-1-Sync' (where 1 is the numeric value of the Sync lane). This will enable the profiler itself to show more meaningful labels for updates and render work. The commit also refactors and adds additional tests for the scheduling profiler package. It also updates the preprocessor to 'support' instant events. These are no-ops for us, but adding recognition of the event type will prevent profiles imported from e.g. Chrome Canary from throwing with an 'unrecognized event' error. (This will resolve issue #20767.) --- .../src/EventTooltip.js | 8 +- .../src/constants.js | 3 +- .../__snapshots__/preprocessData-test.js.snap | 1380 ----------------- .../__tests__/preprocessData-test.internal.js | 602 +++++++ .../__tests__/preprocessData-test.js | 352 ----- .../src/import-worker/preprocessData.js | 41 +- .../src/types.js | 2 + .../webpack.config.js | 3 +- .../src/ReactFiberLane.new.js | 65 +- .../src/ReactFiberLane.old.js | 65 +- .../src/SchedulingProfiler.js | 22 +- .../SchedulingProfiler-test.internal.js | 150 +- .../SchedulingProfilerLabels-test.internal.js | 179 +++ 13 files changed, 1055 insertions(+), 1817 deletions(-) delete mode 100644 packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/__snapshots__/preprocessData-test.js.snap create mode 100644 packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/preprocessData-test.internal.js delete mode 100644 packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/preprocessData-test.js create mode 100644 packages/react-reconciler/src/__tests__/SchedulingProfilerLabels-test.internal.js diff --git a/packages/react-devtools-scheduling-profiler/src/EventTooltip.js b/packages/react-devtools-scheduling-profiler/src/EventTooltip.js index 52fb66d981c4b..608309c4a3caa 100644 --- a/packages/react-devtools-scheduling-profiler/src/EventTooltip.js +++ b/packages/react-devtools-scheduling-profiler/src/EventTooltip.js @@ -249,7 +249,7 @@ const TooltipReactMeasure = ({ return null; } - const {batchUID, duration, timestamp, lanes} = measure; + const {batchUID, duration, timestamp, lanes, laneLabels} = measure; const [startTime, stopTime] = getBatchRange(batchUID, data); return ( @@ -265,7 +265,11 @@ const TooltipReactMeasure = ({
Lane{lanes.length === 1 ? '' : 's'}:
-
{lanes.join(', ')}
+
+ {laneLabels.length > 0 + ? `${laneLabels.join(', ')} (${lanes.join(', ')})` + : lanes.join(', ')} +
); diff --git a/packages/react-devtools-scheduling-profiler/src/constants.js b/packages/react-devtools-scheduling-profiler/src/constants.js index 2e463ae632d95..e5f9336d73e78 100644 --- a/packages/react-devtools-scheduling-profiler/src/constants.js +++ b/packages/react-devtools-scheduling-profiler/src/constants.js @@ -11,5 +11,6 @@ export { COMFORTABLE_LINE_HEIGHT, COMPACT_LINE_HEIGHT, } from 'react-devtools-shared/src/constants.js'; +import {TotalLanes} from 'react-reconciler/src/ReactFiberLane.new'; -export const REACT_TOTAL_NUM_LANES = 31; +export const REACT_TOTAL_NUM_LANES = TotalLanes; diff --git a/packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/__snapshots__/preprocessData-test.js.snap b/packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/__snapshots__/preprocessData-test.js.snap deleted file mode 100644 index 4055b6d45e239..0000000000000 --- a/packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/__snapshots__/preprocessData-test.js.snap +++ /dev/null @@ -1,1380 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`preprocessData should process complete set of events (page load sample data) 1`] = ` -Object { - "duration": 2586.895, - "events": Array [ - Object { - "componentStack": "", - "lanes": Array [ - 9, - ], - "timestamp": 278.073, - "type": "schedule-render", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "0", - "timestamp": 658.345, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "1", - "timestamp": 660.739, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "2", - "timestamp": 662.554, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "3", - "timestamp": 663.455, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "4", - "timestamp": 664.202, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "0", - "timestamp": 666.68, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "1", - "timestamp": 667.201, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "2", - "timestamp": 667.74, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "3", - "timestamp": 668.282, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "4", - "timestamp": 668.848, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at SuspenseList - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "0", - "timestamp": 671.335, - "type": "suspense-suspend", - }, - Object { - "componentName": "ForceUpdateDemo_ForceUpdateDemo", - "componentStack": " - at ForceUpdateDemo_ForceUpdateDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:18:98) - at App", - "isCascading": true, - "lanes": Array [ - 0, - ], - "timestamp": 679.438, - "type": "schedule-state-update", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "1", - "timestamp": 1794.922, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "1", - "timestamp": 1795.374, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "0", - "timestamp": 1797.166, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "2", - "timestamp": 1797.811, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "3", - "timestamp": 1798.163, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "4", - "timestamp": 1798.505, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "2", - "timestamp": 1866.249, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "2", - "timestamp": 1866.542, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "2", - "timestamp": 1866.858, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "0", - "timestamp": 1867.816, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "3", - "timestamp": 1868.638, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "4", - "timestamp": 1868.966, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "3", - "timestamp": 1980.273, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "3", - "timestamp": 1980.522, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "3", - "timestamp": 1980.946, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "3", - "timestamp": 1981.164, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "0", - "timestamp": 1982.079, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "4", - "timestamp": 1983.17, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "4", - "timestamp": 2379.587, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "4", - "timestamp": 2379.895, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "4", - "timestamp": 2380.242, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "4", - "timestamp": 2380.487, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "4", - "timestamp": 2380.735, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "0", - "timestamp": 2381.772, - "type": "suspense-suspend", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "0", - "timestamp": 2579.186, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "0", - "timestamp": 2579.487, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at SuspenseList - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "0", - "timestamp": 2579.735, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "0", - "timestamp": 2580.042, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "0", - "timestamp": 2580.29, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "0", - "timestamp": 2580.546, - "type": "suspense-resolved", - }, - Object { - "componentName": "ResourceButton", - "componentStack": " - at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295) - at Suspense - at div - at div - at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713) - at App", - "id": "0", - "timestamp": 2580.8, - "type": "suspense-resolved", - }, - ], - "flamechart": Array [], - "measures": Array [ - Object { - "batchUID": 0, - "depth": 0, - "duration": 402.58299999999997, - "lanes": Array [ - 9, - ], - "timestamp": 285.293, - "type": "render-idle", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 5.235000000000014, - "lanes": Array [ - 9, - ], - "timestamp": 285.293, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 8.16799999999995, - "lanes": Array [ - 9, - ], - "timestamp": 297.708, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 4.989000000000033, - "lanes": Array [ - 9, - ], - "timestamp": 310.457, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 6.470000000000027, - "lanes": Array [ - 9, - ], - "timestamp": 357.767, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 6.633000000000038, - "lanes": Array [ - 9, - ], - "timestamp": 371.486, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 9.889999999999986, - "lanes": Array [ - 9, - ], - "timestamp": 385.05, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.8589999999999804, - "lanes": Array [ - 9, - ], - "timestamp": 398.06, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.261000000000024, - "lanes": Array [ - 9, - ], - "timestamp": 406.666, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.700999999999965, - "lanes": Array [ - 9, - ], - "timestamp": 414.218, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.793000000000006, - "lanes": Array [ - 9, - ], - "timestamp": 422.141, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.706999999999994, - "lanes": Array [ - 9, - ], - "timestamp": 430.185, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.406999999999982, - "lanes": Array [ - 9, - ], - "timestamp": 439.552, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.649000000000001, - "lanes": Array [ - 9, - ], - "timestamp": 447.294, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.736000000000047, - "lanes": Array [ - 9, - ], - "timestamp": 455.215, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.6959999999999695, - "lanes": Array [ - 9, - ], - "timestamp": 463.259, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.700999999999965, - "lanes": Array [ - 9, - ], - "timestamp": 471.247, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.55499999999995, - "lanes": Array [ - 9, - ], - "timestamp": 479.362, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.7900000000000205, - "lanes": Array [ - 9, - ], - "timestamp": 487.195, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.617000000000019, - "lanes": Array [ - 9, - ], - "timestamp": 495.354, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.241999999999962, - "lanes": Array [ - 9, - ], - "timestamp": 503.706, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.81899999999996, - "lanes": Array [ - 9, - ], - "timestamp": 513.106, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 9.269999999999982, - "lanes": Array [ - 9, - ], - "timestamp": 521.667, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.758000000000038, - "lanes": Array [ - 9, - ], - "timestamp": 531.185, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.735000000000014, - "lanes": Array [ - 9, - ], - "timestamp": 539.213, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.730000000000018, - "lanes": Array [ - 9, - ], - "timestamp": 547.223, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.697000000000003, - "lanes": Array [ - 9, - ], - "timestamp": 555.234, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.715000000000032, - "lanes": Array [ - 9, - ], - "timestamp": 563.232, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.760999999999967, - "lanes": Array [ - 9, - ], - "timestamp": 571.212, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.618000000000052, - "lanes": Array [ - 9, - ], - "timestamp": 579.324, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.737999999999943, - "lanes": Array [ - 9, - ], - "timestamp": 587.201, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.739000000000033, - "lanes": Array [ - 9, - ], - "timestamp": 595.209, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.732000000000085, - "lanes": Array [ - 9, - ], - "timestamp": 603.194, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.712999999999965, - "lanes": Array [ - 9, - ], - "timestamp": 611.212, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.3700000000000045, - "lanes": Array [ - 9, - ], - "timestamp": 619.574, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.73599999999999, - "lanes": Array [ - 9, - ], - "timestamp": 627.188, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.729000000000042, - "lanes": Array [ - 9, - ], - "timestamp": 635.193, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.908999999999992, - "lanes": Array [ - 9, - ], - "timestamp": 643.206, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 7.6159999999999854, - "lanes": Array [ - 9, - ], - "timestamp": 651.339, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 5.334999999999923, - "lanes": Array [ - 9, - ], - "timestamp": 659.445, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 5.5890000000000555, - "lanes": Array [ - 9, - ], - "timestamp": 664.952, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 1.58400000000006, - "lanes": Array [ - 9, - ], - "timestamp": 670.784, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 14.552000000000021, - "lanes": Array [ - 9, - ], - "timestamp": 673.324, - "type": "commit", - }, - Object { - "batchUID": 0, - "depth": 1, - "duration": 2.6889999999999645, - "lanes": Array [ - 9, - ], - "timestamp": 677.236, - "type": "layout-effects", - }, - Object { - "batchUID": 1, - "depth": 1, - "duration": 3.5559999999999263, - "lanes": Array [ - 0, - ], - "timestamp": 684.104, - "type": "render-idle", - }, - Object { - "batchUID": 1, - "depth": 1, - "duration": 2.2169999999999845, - "lanes": Array [ - 0, - ], - "timestamp": 684.104, - "type": "render", - }, - Object { - "batchUID": 1, - "depth": 1, - "duration": 1.3120000000000118, - "lanes": Array [ - 0, - ], - "timestamp": 686.348, - "type": "commit", - }, - Object { - "batchUID": 1, - "depth": 2, - "duration": 0.020999999999958163, - "lanes": Array [ - 0, - ], - "timestamp": 687.267, - "type": "layout-effects", - }, - Object { - "batchUID": 2, - "depth": 0, - "duration": 6.119000000000142, - "lanes": Array [ - 10, - ], - "timestamp": 1796.042, - "type": "render-idle", - }, - Object { - "batchUID": 2, - "depth": 0, - "duration": 3.4329999999999927, - "lanes": Array [ - 10, - ], - "timestamp": 1796.042, - "type": "render", - }, - Object { - "batchUID": 2, - "depth": 0, - "duration": 2.589000000000169, - "lanes": Array [ - 10, - ], - "timestamp": 1799.572, - "type": "commit", - }, - Object { - "batchUID": 2, - "depth": 1, - "duration": 0.020999999999958163, - "lanes": Array [ - 10, - ], - "timestamp": 1801.605, - "type": "layout-effects", - }, - Object { - "batchUID": 3, - "depth": 0, - "duration": 4.116999999999962, - "lanes": Array [ - 11, - ], - "timestamp": 1866.998, - "type": "render-idle", - }, - Object { - "batchUID": 3, - "depth": 0, - "duration": 2.6679999999998927, - "lanes": Array [ - 11, - ], - "timestamp": 1866.998, - "type": "render", - }, - Object { - "batchUID": 3, - "depth": 0, - "duration": 1.4200000000000728, - "lanes": Array [ - 11, - ], - "timestamp": 1869.695, - "type": "commit", - }, - Object { - "batchUID": 3, - "depth": 1, - "duration": 0.020000000000209184, - "lanes": Array [ - 11, - ], - "timestamp": 1870.764, - "type": "layout-effects", - }, - Object { - "batchUID": 4, - "depth": 0, - "duration": 3.7679999999998017, - "lanes": Array [ - 12, - ], - "timestamp": 1981.361, - "type": "render-idle", - }, - Object { - "batchUID": 4, - "depth": 0, - "duration": 2.438999999999851, - "lanes": Array [ - 12, - ], - "timestamp": 1981.361, - "type": "render", - }, - Object { - "batchUID": 4, - "depth": 0, - "duration": 1.2579999999998108, - "lanes": Array [ - 12, - ], - "timestamp": 1983.871, - "type": "commit", - }, - Object { - "batchUID": 4, - "depth": 1, - "duration": 0.027000000000043656, - "lanes": Array [ - 12, - ], - "timestamp": 1984.931, - "type": "layout-effects", - }, - Object { - "batchUID": 5, - "depth": 0, - "duration": 3.8899999999998727, - "lanes": Array [ - 13, - ], - "timestamp": 2380.969, - "type": "render-idle", - }, - Object { - "batchUID": 5, - "depth": 0, - "duration": 2.3099999999999454, - "lanes": Array [ - 13, - ], - "timestamp": 2380.969, - "type": "render", - }, - Object { - "batchUID": 5, - "depth": 0, - "duration": 1.5209999999997308, - "lanes": Array [ - 13, - ], - "timestamp": 2383.338, - "type": "commit", - }, - Object { - "batchUID": 5, - "depth": 1, - "duration": 0.01999999999998181, - "lanes": Array [ - 13, - ], - "timestamp": 2384.535, - "type": "layout-effects", - }, - Object { - "batchUID": 6, - "depth": 0, - "duration": 5.942999999999756, - "lanes": Array [ - 14, - ], - "timestamp": 2580.952, - "type": "render-idle", - }, - Object { - "batchUID": 6, - "depth": 0, - "duration": 3.424999999999727, - "lanes": Array [ - 14, - ], - "timestamp": 2580.952, - "type": "render", - }, - Object { - "batchUID": 6, - "depth": 0, - "duration": 2.4470000000001164, - "lanes": Array [ - 14, - ], - "timestamp": 2584.448, - "type": "commit", - }, - Object { - "batchUID": 6, - "depth": 1, - "duration": 0.027000000000043656, - "lanes": Array [ - 14, - ], - "timestamp": 2586.122, - "type": "layout-effects", - }, - ], - "otherUserTimingMarks": Array [ - Object { - "name": "navigationStart", - "timestamp": -29.357, - }, - Object { - "name": "fetchStart", - "timestamp": -26.92, - }, - Object { - "name": "requestStart", - "timestamp": -21.171, - }, - Object { - "name": "responseEnd", - "timestamp": -15.655, - }, - Object { - "name": "unloadEventStart", - "timestamp": -0.74, - }, - Object { - "name": "unloadEventEnd", - "timestamp": 39.608, - }, - Object { - "name": "requestStart", - "timestamp": 107.649, - }, - Object { - "name": "requestStart", - "timestamp": 108.385, - }, - Object { - "name": "loadEventStart", - "timestamp": 307.056, - }, - Object { - "name": "loadEventEnd", - "timestamp": 308.242, - }, - Object { - "name": "requestStart", - "timestamp": 341.329, - }, - Object { - "name": "requestStart", - "timestamp": 344.02, - }, - Object { - "name": "requestStart", - "timestamp": 387.585, - }, - ], - "startTime": 8993778496, -} -`; - -exports[`preprocessData should process forced update event 1`] = ` -Object { - "duration": 67.461, - "events": Array [ - Object { - "componentName": "ForceUpdateDemo_ForceUpdateDemo", - "componentStack": " - at ForceUpdateDemo_ForceUpdateDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:18:98) - at App", - "isCascading": false, - "lanes": Array [ - 4, - ], - "timestamp": 63.355, - "type": "schedule-force-update", - }, - ], - "flamechart": Array [], - "measures": Array [ - Object { - "batchUID": 0, - "depth": 0, - "duration": 2.1910000000000025, - "lanes": Array [ - 4, - ], - "timestamp": 65.27, - "type": "render-idle", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 0.9770000000000039, - "lanes": Array [ - 4, - ], - "timestamp": 65.27, - "type": "render", - }, - Object { - "batchUID": 0, - "depth": 0, - "duration": 1.1670000000000016, - "lanes": Array [ - 4, - ], - "timestamp": 66.294, - "type": "commit", - }, - Object { - "batchUID": 0, - "depth": 1, - "duration": 0.018000000000000682, - "lanes": Array [ - 4, - ], - "timestamp": 67.325, - "type": "layout-effects", - }, - ], - "otherUserTimingMarks": Array [], - "startTime": 40806924876, -} -`; diff --git a/packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/preprocessData-test.internal.js b/packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/preprocessData-test.internal.js new file mode 100644 index 0000000000000..df81af097ba54 --- /dev/null +++ b/packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/preprocessData-test.internal.js @@ -0,0 +1,602 @@ +/** + * 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. + */ + +'use strict'; + +import preprocessData, { + getLanesFromTransportDecimalBitmask, +} from '../preprocessData'; +import {REACT_TOTAL_NUM_LANES} from '../../constants'; + +describe(getLanesFromTransportDecimalBitmask, () => { + it('should return array of lane numbers from bitmask string', () => { + expect(getLanesFromTransportDecimalBitmask('1')).toEqual([0]); + expect(getLanesFromTransportDecimalBitmask('512')).toEqual([9]); + expect(getLanesFromTransportDecimalBitmask('3')).toEqual([0, 1]); + expect(getLanesFromTransportDecimalBitmask('1234')).toEqual([ + 1, + 4, + 6, + 7, + 10, + ]); // 2 + 16 + 64 + 128 + 1024 + expect( + getLanesFromTransportDecimalBitmask('1073741824'), // 0b1000000000000000000000000000000 + ).toEqual([30]); + expect( + getLanesFromTransportDecimalBitmask('2147483647'), // 0b1111111111111111111111111111111 + ).toEqual(Array.from(Array(31).keys())); + }); + + it('should return empty array if laneBitmaskString is not a bitmask', () => { + expect(getLanesFromTransportDecimalBitmask('')).toEqual([]); + expect(getLanesFromTransportDecimalBitmask('hello')).toEqual([]); + expect(getLanesFromTransportDecimalBitmask('-1')).toEqual([]); + expect(getLanesFromTransportDecimalBitmask('-0')).toEqual([]); + }); + + it('should ignore lanes outside REACT_TOTAL_NUM_LANES', () => { + // Sanity check; this test may need to be updated when the no. of fiber + // lanes are changed. + expect(REACT_TOTAL_NUM_LANES).toBe(31); + + expect( + getLanesFromTransportDecimalBitmask( + '4294967297', // 2^32 + 1 + ), + ).toEqual([0]); + }); +}); + +describe(preprocessData, () => { + let React; + let ReactDOM; + + let act; + let clearedMarks; + let featureDetectionMarkName = null; + let marks; + + function polyfillJSDomUserTiming() { + featureDetectionMarkName = null; + + clearedMarks = []; + marks = []; + + // This is not a true polyfill, but it gives us enough to capture marks. + // Reference: https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API + + // JSDom already implements global.performance and it can't be overridden. + // However it only supports now() and timeOrigin() so we need to "upgrade it" in place. + + if (!global.performance) { + global.performance = {}; + } + + global.performance.clearMarks = function clearMarks(markName) { + clearedMarks.push(markName); + marks = marks.filter(mark => mark !== markName); + }; + + global.performance.mark = function mark(markName, markOptions) { + if (featureDetectionMarkName === null) { + featureDetectionMarkName = markName; + } + marks.push(markName); + if (markOptions != null) { + // This is triggers the feature detection. + markOptions.startTime++; + } + }; + } + + // These should be dynamic to mimic a real profile, + // but reprooducible between test runs. + let pid = 0; + let tid = 0; + let startTime = 0; + + function createUserTimingEntry(data) { + return { + pid: ++pid, + tid: ++tid, + ts: ++startTime, + ...data, + }; + } + + function createUserTimingData(sampleMarks) { + const cpuProfilerSample = createUserTimingEntry({ + args: {data: {startTime: ++startTime}}, + cat: 'disabled-by-default-v8.cpu_profiler', + id: '0x1', + name: 'Profile', + ph: 'P', + }); + + const randomSample = createUserTimingEntry({ + dur: 100, + tdur: 200, + ph: 'X', + cat: 'disabled-by-default-devtools.timeline', + name: 'RunTask', + args: {}, + }); + + const userTimingData = [cpuProfilerSample, randomSample]; + + sampleMarks.forEach(markName => { + userTimingData.push({ + pid: ++pid, + tid: ++tid, + ts: ++startTime, + args: {data: {navigationId: 'fake-navigation-id'}}, + cat: 'blink.user_timing', + name: markName, + ph: 'R', + }); + }); + + return userTimingData; + } + + beforeEach(() => { + jest.resetModules(); + + polyfillJSDomUserTiming(); + + React = require('react'); + ReactDOM = require('react-dom'); + + const TestUtils = require('react-dom/test-utils'); + act = TestUtils.act; + + tid = 0; + pid = 0; + startTime = 0; + }); + + afterEach(() => { + // Verify all logged marks also get cleared. + expect(marks).toHaveLength(0); + + delete global.performance; + }); + + it('should throw given an empty timeline', () => { + expect(() => preprocessData([])).toThrow(); + }); + + it('should throw given a timeline with no Profile event', () => { + const randomSample = createUserTimingEntry({ + dur: 100, + tdur: 200, + ph: 'X', + cat: 'disabled-by-default-devtools.timeline', + name: 'RunTask', + args: {}, + }); + + expect(() => preprocessData([randomSample])).toThrow(); + }); + + it('should return empty data given a timeline with no React scheduling profiling marks', () => { + const cpuProfilerSample = createUserTimingEntry({ + args: {data: {startTime: ++startTime}}, + cat: 'disabled-by-default-v8.cpu_profiler', + id: '0x1', + name: 'Profile', + ph: 'P', + }); + + const randomSample = createUserTimingEntry({ + dur: 100, + tdur: 200, + ph: 'X', + cat: 'disabled-by-default-devtools.timeline', + name: 'RunTask', + args: {}, + }); + + expect(preprocessData([cpuProfilerSample, randomSample])).toStrictEqual({ + duration: 0.002, + events: [], + flamechart: [], + measures: [], + otherUserTimingMarks: [], + startTime: 1, + }); + }); + + // NOTE This test doesn't have to be gated because it has hard-coded profiler samples. + it('should process legacy data format (before lane labels were added)', () => { + const cpuProfilerSample = createUserTimingEntry({ + args: {data: {startTime: ++startTime}}, + cat: 'disabled-by-default-v8.cpu_profiler', + id: '0x1', + name: 'Profile', + ph: 'P', + }); + + expect( + // Data below is hard-coded based on an older profile sample. + // Should be fine since this is explicitly a legacy-format test. + preprocessData([ + cpuProfilerSample, + createUserTimingEntry({ + cat: 'blink.user_timing', + name: '--schedule-render-512-', + }), + createUserTimingEntry({ + cat: 'blink.user_timing', + name: '--render-start-512', + }), + createUserTimingEntry({ + cat: 'blink.user_timing', + name: '--render-stop', + }), + createUserTimingEntry({ + cat: 'blink.user_timing', + name: '--commit-start-512', + }), + createUserTimingEntry({ + cat: 'blink.user_timing', + name: '--layout-effects-start-512', + }), + createUserTimingEntry({ + cat: 'blink.user_timing', + name: '--layout-effects-stop', + }), + createUserTimingEntry({ + cat: 'blink.user_timing', + name: '--commit-stop', + }), + ]), + ).toStrictEqual({ + duration: 0.008, + events: [ + { + componentStack: '', + laneLabels: [], + lanes: [9], + timestamp: 0.002, + type: 'schedule-render', + }, + ], + flamechart: [], + measures: [ + { + batchUID: 0, + depth: 0, + duration: 0.005, + laneLabels: [], + lanes: [9], + timestamp: 0.003, + type: 'render-idle', + }, + { + batchUID: 0, + depth: 0, + duration: 0.001, + laneLabels: [], + lanes: [9], + timestamp: 0.003, + type: 'render', + }, + { + batchUID: 0, + depth: 0, + duration: 0.003, + laneLabels: [], + lanes: [9], + timestamp: 0.005, + type: 'commit', + }, + { + batchUID: 0, + depth: 1, + duration: 0.001, + laneLabels: [], + lanes: [9], + timestamp: 0.006, + type: 'layout-effects', + }, + ], + otherUserTimingMarks: [], + startTime: 1, + }); + }); + + // @gate enableSchedulingProfiler + it('should process a sample legacy render sequence', () => { + ReactDOM.render(
, document.createElement('div')); + + const reactVersion = require('shared/ReactVersion').default; + + const userTimingData = createUserTimingData(clearedMarks); + expect(preprocessData(userTimingData)).toStrictEqual({ + duration: 0.011, + events: [ + { + componentStack: '', + laneLabels: ['Sync'], + lanes: [0], + timestamp: 0.005, + type: 'schedule-render', + }, + ], + flamechart: [], + measures: [ + { + batchUID: 0, + depth: 0, + duration: 0.004999999999999999, + laneLabels: ['Sync'], + lanes: [0], + timestamp: 0.006, + type: 'render-idle', + }, + { + batchUID: 0, + depth: 0, + duration: 0.001, + laneLabels: ['Sync'], + lanes: [0], + timestamp: 0.006, + type: 'render', + }, + { + batchUID: 0, + depth: 0, + duration: 0.002999999999999999, + laneLabels: ['Sync'], + lanes: [0], + timestamp: 0.008, + type: 'commit', + }, + { + batchUID: 0, + depth: 1, + duration: 0.0010000000000000009, + laneLabels: ['Sync'], + lanes: [0], + timestamp: 0.009, + type: 'layout-effects', + }, + ], + otherUserTimingMarks: [ + { + name: '__v3', + timestamp: 0.003, + }, + { + name: `--react-init-${reactVersion}`, + timestamp: 0.004, + }, + ], + startTime: 1, + }); + }); + + // @gate experimental && enableSchedulingProfiler + it('should process a sample createRoot render sequence', () => { + function App() { + const [didMount, setDidMount] = React.useState(false); + React.useEffect(() => { + if (!didMount) { + setDidMount(true); + } + }); + return true; + } + + const root = ReactDOM.createRoot(document.createElement('div')); + act(() => root.render()); + + const userTimingData = createUserTimingData(clearedMarks); + expect(preprocessData(userTimingData)).toStrictEqual({ + duration: 0.022, + events: [ + { + componentStack: '', + laneLabels: ['Default'], + lanes: [7], + timestamp: 0.005, + type: 'schedule-render', + }, + { + componentName: 'App', + componentStack: '', + isCascading: false, + laneLabels: ['Default'], + lanes: [7], + timestamp: 0.013, + type: 'schedule-state-update', + }, + ], + flamechart: [], + measures: [ + { + batchUID: 0, + depth: 0, + duration: 0.004999999999999999, + laneLabels: ['Default'], + lanes: [7], + timestamp: 0.006, + type: 'render-idle', + }, + { + batchUID: 0, + depth: 0, + duration: 0.001, + laneLabels: ['Default'], + lanes: [7], + timestamp: 0.006, + type: 'render', + }, + { + batchUID: 0, + depth: 0, + duration: 0.002999999999999999, + laneLabels: ['Default'], + lanes: [7], + timestamp: 0.008, + type: 'commit', + }, + { + batchUID: 0, + depth: 1, + duration: 0.0010000000000000009, + laneLabels: ['Default'], + lanes: [7], + timestamp: 0.009, + type: 'layout-effects', + }, + { + batchUID: 0, + depth: 0, + duration: 0.002, + laneLabels: ['Default'], + lanes: [7], + timestamp: 0.012, + type: 'passive-effects', + }, + { + batchUID: 1, + depth: 0, + duration: 0.005000000000000001, + laneLabels: ['Default'], + lanes: [7], + timestamp: 0.015, + type: 'render-idle', + }, + { + batchUID: 1, + depth: 0, + duration: 0.0010000000000000009, + laneLabels: ['Default'], + lanes: [7], + timestamp: 0.015, + type: 'render', + }, + { + batchUID: 1, + depth: 0, + duration: 0.002999999999999999, + laneLabels: ['Default'], + lanes: [7], + timestamp: 0.017, + type: 'commit', + }, + { + batchUID: 1, + depth: 1, + duration: 0.0010000000000000009, + laneLabels: ['Default'], + lanes: [7], + timestamp: 0.018, + type: 'layout-effects', + }, + { + batchUID: 1, + depth: 0, + duration: 0.0009999999999999974, + laneLabels: ['Default'], + lanes: [7], + timestamp: 0.021, + type: 'passive-effects', + }, + ], + otherUserTimingMarks: [ + { + name: '__v3', + timestamp: 0.003, + }, + { + name: '--react-init-17.0.2', + timestamp: 0.004, + }, + ], + startTime: 1, + }); + }); + + // @gate enableSchedulingProfiler + it('should error if events and measures are incomplete', () => { + const container = document.createElement('div'); + ReactDOM.render(
, container); + + const invalidMarks = clearedMarks.filter( + mark => !mark.includes('render-stop'), + ); + const invalidUserTimingData = createUserTimingData(invalidMarks); + + const error = spyOnDevAndProd(console, 'error'); + preprocessData(invalidUserTimingData); + expect(error).toHaveBeenCalled(); + }); + + // @gate enableSchedulingProfiler + it('should error if work is completed without being started', () => { + const container = document.createElement('div'); + ReactDOM.render(
, container); + + const invalidMarks = clearedMarks.filter( + mark => !mark.includes('render-start'), + ); + const invalidUserTimingData = createUserTimingData(invalidMarks); + + const error = spyOnDevAndProd(console, 'error'); + preprocessData(invalidUserTimingData); + expect(error).toHaveBeenCalled(); + }); + + it('should populate other user timing marks', () => { + const userTimingData = createUserTimingData([]); + userTimingData.push( + createUserTimingEntry({ + args: {}, + cat: 'blink.user_timing', + id: '0xcdf75f7c', + name: 'VCWithoutImage: root', + ph: 'n', + scope: 'blink.user_timing', + }), + ); + userTimingData.push( + createUserTimingEntry({ + cat: 'blink.user_timing', + name: '--a-mark-that-looks-like-one-of-ours', + ph: 'R', + }), + ); + userTimingData.push( + createUserTimingEntry({ + cat: 'blink.user_timing', + name: 'Some other mark', + ph: 'R', + }), + ); + + expect(preprocessData(userTimingData).otherUserTimingMarks).toStrictEqual([ + { + name: 'VCWithoutImage: root', + timestamp: 0.003, + }, + { + name: '--a-mark-that-looks-like-one-of-ours', + timestamp: 0.004, + }, + { + name: 'Some other mark', + timestamp: 0.005, + }, + ]); + }); + + // TODO: Add test for flamechart parsing +}); diff --git a/packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/preprocessData-test.js b/packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/preprocessData-test.js deleted file mode 100644 index 8626252cee19f..0000000000000 --- a/packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/preprocessData-test.js +++ /dev/null @@ -1,352 +0,0 @@ -/** - * 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. - */ - -'use strict'; - -import preprocessData, { - getLanesFromTransportDecimalBitmask, -} from '../preprocessData'; -import {REACT_TOTAL_NUM_LANES} from '../../constants'; - -// Disable quotes rule in the whole file as we paste raw JSON as test inputs and -// Prettier will already format the remaining quotes. -/* eslint-disable quotes */ - -describe(getLanesFromTransportDecimalBitmask, () => { - it('should return array of lane numbers from bitmask string', () => { - expect(getLanesFromTransportDecimalBitmask('1')).toEqual([0]); - expect(getLanesFromTransportDecimalBitmask('512')).toEqual([9]); - expect(getLanesFromTransportDecimalBitmask('3')).toEqual([0, 1]); - expect(getLanesFromTransportDecimalBitmask('1234')).toEqual([ - 1, - 4, - 6, - 7, - 10, - ]); // 2 + 16 + 64 + 128 + 1024 - expect( - getLanesFromTransportDecimalBitmask('1073741824'), // 0b1000000000000000000000000000000 - ).toEqual([30]); - expect( - getLanesFromTransportDecimalBitmask('2147483647'), // 0b1111111111111111111111111111111 - ).toEqual(Array.from(Array(31).keys())); - }); - - it('should return empty array if laneBitmaskString is not a bitmask', () => { - expect(getLanesFromTransportDecimalBitmask('')).toEqual([]); - expect(getLanesFromTransportDecimalBitmask('hello')).toEqual([]); - expect(getLanesFromTransportDecimalBitmask('-1')).toEqual([]); - expect(getLanesFromTransportDecimalBitmask('-0')).toEqual([]); - }); - - it('should ignore lanes outside REACT_TOTAL_NUM_LANES', () => { - // Sanity check; this test may need to be updated when the no. of fiber - // lanes are changed. - expect(REACT_TOTAL_NUM_LANES).toBe(31); - - expect( - getLanesFromTransportDecimalBitmask( - '4294967297', // 2^32 + 1 - ), - ).toEqual([0]); - }); -}); - -describe(preprocessData, () => { - it('should throw given an empty timeline', () => { - expect(() => preprocessData([])).toThrow(); - }); - - it('should throw given a timeline with no Profile event', () => { - expect(() => - // prettier-ignore - preprocessData([ - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--schedule-render-512-","ph":"R","pid":9312,"tid":10252,"ts":8994056569,"tts":1816966}, - ]), - ).toThrow(); - }); - - it('should return empty data given a timeline with no React scheduling profiling marks', () => { - expect( - // prettier-ignore - preprocessData([ - {"args":{"data":{"startTime":8993778496}},"cat":"disabled-by-default-v8.cpu_profiler","id":"0x1","name":"Profile","ph":"P","pid":9312,"tid":10252,"ts":8993778520,"tts":1614266}, - {"pid":57632,"tid":38659,"ts":874860756135,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":18,"tdur":19,"tts":8700284918,"args":{}}, - {"pid":57632,"tid":38659,"ts":874860756158,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":30,"tdur":30,"tts":8700284941,"args":{}}, - {"pid":57632,"tid":38659,"ts":874860756192,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":21,"tdur":20,"tts":8700284976,"args":{}}, - {"pid":57632,"tid":38659,"ts":874860756216,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":6,"tdur":5,"tts":8700285000,"args":{}}, - {"pid":57632,"tid":38659,"ts":874860756224,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":7,"tdur":6,"tts":8700285008,"args":{}}, - {"pid":57632,"tid":38659,"ts":874860756233,"ph":"X","cat":"disabled-by-default-devtools.timeline","name":"RunTask","dur":5,"tdur":4,"tts":8700285017,"args":{}}, - ]), - ).toEqual({ - startTime: 8993778496, - duration: 865866977.737, - events: [], - measures: [], - flamechart: [], - otherUserTimingMarks: [], - }); - }); - - it('should error if events and measures are incomplete', () => { - const error = spyOnDevAndProd(console, 'error'); - // prettier-ignore - preprocessData([ - {"args":{"data":{"startTime":8993778496}},"cat":"disabled-by-default-v8.cpu_profiler","id":"0x1","name":"Profile","ph":"P","pid":9312,"tid":10252,"ts":8993778520,"tts":1614266}, - {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--render-start-8","ph":"R","pid":1852,"tid":12484,"ts":42351664678,"tts":1512475}, - ]); - expect(error).toHaveBeenCalled(); - }); - - it('should error if work is completed without being started', () => { - const error = spyOnDevAndProd(console, 'error'); - // prettier-ignore - preprocessData([ - {"args":{"data":{"startTime":8993778496}},"cat":"disabled-by-default-v8.cpu_profiler","id":"0x1","name":"Profile","ph":"P","pid":9312,"tid":10252,"ts":8993778520,"tts":1614266}, - {"args":{"data":{"navigationId":"E082C30FBDA3ACEE0E7B5FD75F8B7F0D"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":17232,"tid":13628,"ts":264686513020,"tts":4082554}, - ]); - expect(error).toHaveBeenCalled(); - }); - - it('should process complete set of events (page load sample data)', () => { - expect( - // prettier-ignore - preprocessData([ - {"args":{"data":{"documentLoaderURL":"https://concurrent-demo.now.sh/","isLoadingMainFrame":true,"navigationId":"43BC238A4FB7548146D3CD739C9C9434"},"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"navigationStart","ph":"R","pid":9312,"tid":10252,"ts":8993749139,"tts":1646191}, - {"args":{"data":{"startTime":8993778496}},"cat":"disabled-by-default-v8.cpu_profiler","id":"0x1","name":"Profile","ph":"P","pid":9312,"tid":10252,"ts":8993778520,"tts":1614266}, - {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"fetchStart","ph":"R","pid":9312,"tid":10252,"ts":8993751576,"tts":1646197}, - {"args":{},"cat":"blink.user_timing","name":"requestStart","ph":"R","pid":9312,"tid":10252,"ts":8993757325,"tts":1612760}, - {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"responseEnd","ph":"R","pid":9312,"tid":10252,"ts":8993762841,"tts":1652151}, - {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"unloadEventStart","ph":"R","pid":9312,"tid":10252,"ts":8993777756,"tts":1646416}, - {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"unloadEventEnd","ph":"R","pid":9312,"tid":10252,"ts":8993818104,"tts":1646419}, - {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing,rail","name":"domLoading","ph":"R","pid":9312,"tid":10252,"ts":8993820215,"tts":1647488}, - {"args":{},"cat":"blink.user_timing","name":"requestStart","ph":"R","pid":9312,"tid":10252,"ts":8993886145,"tts":1771277}, - {"args":{},"cat":"blink.user_timing","name":"requestStart","ph":"R","pid":9312,"tid":10252,"ts":8993886881,"tts":1778953}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--schedule-render-512-","ph":"R","pid":9312,"tid":10252,"ts":8994056569,"tts":1816966}, - {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing,rail","name":"domInteractive","ph":"R","pid":9312,"tid":10252,"ts":8994058638,"tts":1818851}, - {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing,rail","name":"domContentLoadedEventStart","ph":"R","pid":9312,"tid":10252,"ts":8994058898,"tts":1819078}, - {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing,rail","name":"domContentLoadedEventEnd","ph":"R","pid":9312,"tid":10252,"ts":8994060045,"tts":1820100}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994063789,"tts":1823183}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994069024,"tts":1826507}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994076204,"tts":1830657}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994084372,"tts":1837590}, - {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing,rail","name":"domComplete","ph":"R","pid":9312,"tid":10252,"ts":8994085517,"tts":1838615}, - {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"loadEventStart","ph":"R","pid":9312,"tid":10252,"ts":8994085552,"tts":1838649}, - {"args":{"frame":"FD65D9AFD04B1295CEA36B883F0FA82F"},"cat":"blink.user_timing","name":"loadEventEnd","ph":"R","pid":9312,"tid":10252,"ts":8994086738,"tts":1839690}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994088953,"tts":1840749}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994093942,"tts":1844455}, - {"args":{},"cat":"blink.user_timing","name":"requestStart","ph":"R","pid":9312,"tid":10252,"ts":8994119825,"tts":1877483}, - {"args":{},"cat":"blink.user_timing","name":"requestStart","ph":"R","pid":9312,"tid":10252,"ts":8994122516,"tts":1886344}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994136263,"tts":1871212}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994142733,"tts":1875838}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994149982,"tts":1880208}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994156615,"tts":1885309}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994163546,"tts":1887453}, - {"args":{},"cat":"blink.user_timing","name":"requestStart","ph":"R","pid":9312,"tid":10252,"ts":8994166081,"tts":1895751}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994173436,"tts":1894442}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994176556,"tts":1897176}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994184415,"tts":1904263}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994185162,"tts":1904938}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994192423,"tts":1910624}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994192714,"tts":1910872}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994200415,"tts":1917859}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994200637,"tts":1918062}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994208430,"tts":1924894}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994208681,"tts":1925124}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994216388,"tts":1932117}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994218048,"tts":1933622}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994225455,"tts":1940076}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994225790,"tts":1940391}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994233439,"tts":1947224}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994233711,"tts":1947473}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994241447,"tts":1954160}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994241755,"tts":1954426}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994249451,"tts":1961213}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994249743,"tts":1961494}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994257444,"tts":1968141}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994257858,"tts":1968525}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994265413,"tts":1975172}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994265691,"tts":1975416}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994273481,"tts":1981826}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994273850,"tts":1982112}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994281467,"tts":1988537}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994282202,"tts":1988894}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994289444,"tts":1994103}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994291602,"tts":1995165}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994299421,"tts":2000342}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994300163,"tts":2001009}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994309433,"tts":2005662}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994309681,"tts":2005897}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994317439,"tts":2012641}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994317709,"tts":2012890}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994325444,"tts":2019235}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994325719,"tts":2019477}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994333449,"tts":2026367}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994333730,"tts":2026617}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994341427,"tts":2033147}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994341728,"tts":2033411}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994349443,"tts":2040163}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994349708,"tts":2040409}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994357469,"tts":2047136}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994357820,"tts":2047465}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994365438,"tts":2054203}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994365697,"tts":2054434}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994373435,"tts":2061259}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994373705,"tts":2061502}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994381444,"tts":2068300}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994381690,"tts":2068529}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994389422,"tts":2075272}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994389708,"tts":2075518}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994397421,"tts":2082156}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994398070,"tts":2082726}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994405440,"tts":2088860}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994405684,"tts":2089091}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994413420,"tts":2095780}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994413689,"tts":2096021}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994421418,"tts":2102791}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994421702,"tts":2103047}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994429611,"tts":2110142}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994429835,"tts":2110349}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994436841,"tts":2115594}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994437451,"tts":2116087}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994437941,"tts":2116287}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-1-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994439235,"tts":2117153}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-2-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994441050,"tts":2118088}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994441951,"tts":2118783}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994442698,"tts":2119371}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994443276,"tts":2119875}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994443448,"tts":2120040}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994445176,"tts":2121499}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-1-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994445697,"tts":2121968}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-2-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994446236,"tts":2122460}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994446778,"tts":2122951}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994447344,"tts":2123444}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-yield","ph":"R","pid":9312,"tid":10252,"ts":8994449037,"tts":2124925}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994449280,"tts":2125142}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at SuspenseList\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994449831,"tts":2125639}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8994450864,"tts":2126555}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994451820,"tts":2127417}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-512","ph":"R","pid":9312,"tid":10252,"ts":8994455732,"tts":2130777}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--schedule-state-update-1-ForceUpdateDemo_ForceUpdateDemo-\n at ForceUpdateDemo_ForceUpdateDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:18:98)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8994457934,"tts":2132671}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8994458421,"tts":2133089}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-1","ph":"R","pid":9312,"tid":10252,"ts":8994462600,"tts":2136847}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8994464817,"tts":2138817}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-1","ph":"R","pid":9312,"tid":10252,"ts":8994464844,"tts":2138843}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-1","ph":"R","pid":9312,"tid":10252,"ts":8994465763,"tts":2139664}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8994465784,"tts":2139686}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8994466156,"tts":2140023}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8994466372,"tts":2140208}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-1-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995573418,"tts":2205582}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-1-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995573870,"tts":2205980}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-1024","ph":"R","pid":9312,"tid":10252,"ts":8995574538,"tts":2206568}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995575662,"tts":2207534}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-2-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995576307,"tts":2208142}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995576659,"tts":2208445}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995577001,"tts":2208736}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8995577971,"tts":2209602}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-1024","ph":"R","pid":9312,"tid":10252,"ts":8995578068,"tts":2209689}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-1024","ph":"R","pid":9312,"tid":10252,"ts":8995580101,"tts":2211495}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8995580122,"tts":2211515}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8995580657,"tts":2211995}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-2-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995644745,"tts":2217336}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-2-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995645038,"tts":2217571}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-2-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995645354,"tts":2217861}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-2048","ph":"R","pid":9312,"tid":10252,"ts":8995645494,"tts":2217999}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995646312,"tts":2218721}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995647134,"tts":2219450}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995647462,"tts":2219740}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8995648162,"tts":2220335}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-2048","ph":"R","pid":9312,"tid":10252,"ts":8995648191,"tts":2220363}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-2048","ph":"R","pid":9312,"tid":10252,"ts":8995649260,"tts":2221320}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8995649280,"tts":2221340}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8995649611,"tts":2221636}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995758769,"tts":2228839}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995759018,"tts":2229064}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995759442,"tts":2229424}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-3-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995759660,"tts":2229627}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-4096","ph":"R","pid":9312,"tid":10252,"ts":8995759857,"tts":2229803}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995760575,"tts":2230456}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8995761666,"tts":2231399}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8995762296,"tts":2231965}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-4096","ph":"R","pid":9312,"tid":10252,"ts":8995762367,"tts":2232017}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-4096","ph":"R","pid":9312,"tid":10252,"ts":8995763427,"tts":2232966}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8995763454,"tts":2232993}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8995763625,"tts":2233154}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158083,"tts":2252466}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158391,"tts":2252730}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158738,"tts":2253038}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996158983,"tts":2253239}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-4-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996159231,"tts":2253447}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-8192","ph":"R","pid":9312,"tid":10252,"ts":8996159465,"tts":2253624}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-suspend-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996160268,"tts":2254312}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8996161775,"tts":2255670}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-8192","ph":"R","pid":9312,"tid":10252,"ts":8996161834,"tts":2255716}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-8192","ph":"R","pid":9312,"tid":10252,"ts":8996163031,"tts":2256754}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8996163051,"tts":2256773}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8996163355,"tts":2257045}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996357682,"tts":2267920}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996357983,"tts":2268179}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at SuspenseList\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996358231,"tts":2268389}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996358538,"tts":2268679}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996358786,"tts":2268867}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996359042,"tts":2269066}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--suspense-resolved-0-ResourceButton-\n at ResourceButton (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:295)\n at Suspense\n at div\n at div\n at SuspenseDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:36:713)\n at App","ph":"R","pid":9312,"tid":10252,"ts":8996359296,"tts":2269264}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-start-16384","ph":"R","pid":9312,"tid":10252,"ts":8996359448,"tts":2269412}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":9312,"tid":10252,"ts":8996362873,"tts":2272363}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-start-16384","ph":"R","pid":9312,"tid":10252,"ts":8996362944,"tts":2272420}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-start-16384","ph":"R","pid":9312,"tid":10252,"ts":8996364618,"tts":2273869}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":9312,"tid":10252,"ts":8996364645,"tts":2273895}, - {"args":{"data":{"navigationId":"43BC238A4FB7548146D3CD739C9C9434"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":9312,"tid":10252,"ts":8996365391,"tts":2274547}, - ]), - ).toMatchSnapshot(); - }); - - it('should process forced update event', () => { - expect( - // prettier-ignore - preprocessData([ - {"args":{"data":{"startTime":40806924876}},"cat":"disabled-by-default-v8.cpu_profiler","id":"0x2","name":"Profile","ph":"P","pid":1852,"tid":12484,"ts":40806924880,"tts":996658}, - {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--schedule-forced-update-16-ForceUpdateDemo_ForceUpdateDemo-\n at ForceUpdateDemo_ForceUpdateDemo (https://concurrent-demo.now.sh/static/js/main.c9f122eb.chunk.js:18:98)\n at App","ph":"R","pid":1852,"tid":12484,"ts":40806988231,"tts":1037762}, - {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--render-start-16","ph":"R","pid":1852,"tid":12484,"ts":40806990146,"tts":1038890}, - {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--render-stop","ph":"R","pid":1852,"tid":12484,"ts":40806991123,"tts":1039401}, - {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--commit-start-16","ph":"R","pid":1852,"tid":12484,"ts":40806991170,"tts":1039447}, - {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--layout-effects-start-16","ph":"R","pid":1852,"tid":12484,"ts":40806992201,"tts":1040023}, - {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--layout-effects-stop","ph":"R","pid":1852,"tid":12484,"ts":40806992219,"tts":1040041}, - {"args":{"data":{"navigationId":"1065756F5FDAD64BE45CA86B0BBC1F8B"}},"cat":"blink.user_timing","name":"--commit-stop","ph":"R","pid":1852,"tid":12484,"ts":40806992337,"tts":1040149}, - ]), - ).toMatchSnapshot(); - }); - - it('should populate other user timing marks', () => { - expect( - // prettier-ignore - preprocessData([ - {"args":{},"cat":"blink.user_timing","id":"0xcdf75f7c","name":"VCWithoutImage: root","ph":"n","pid":55132,"scope":"blink.user_timing","tid":775,"ts":458734963394}, - {"args":{"data":{"startTime":458738069897}},"cat":"disabled-by-default-v8.cpu_profiler","id":"0x4","name":"Profile","ph":"P","pid":55132,"tid":775,"ts":458738069898,"tts":27896428}, - {"args":{"data":{"navigationId":"B8774C733A75946C099FE21F8A0E8D38"}},"cat":"blink.user_timing","name":"--a-mark-that-looks-like-one-of-ours","ph":"R","pid":55132,"tid":775,"ts":458738256356,"tts":28082555}, - {"args":{"data":{"navigationId":"B8774C733A75946C099FE21F8A0E8D38"}},"cat":"blink.user_timing","name":"Some other mark","ph":"R","pid":55132,"tid":775,"ts":458738261491,"tts":28087691}, - ]).otherUserTimingMarks, - ).toMatchInlineSnapshot(` - Array [ - Object { - "name": "VCWithoutImage: root", - "timestamp": -3106.503, - }, - Object { - "name": "--a-mark-that-looks-like-one-of-ours", - "timestamp": 186.459, - }, - Object { - "name": "Some other mark", - "timestamp": 191.594, - }, - ] - `); - }); - - // TODO: Add test for flamechart parsing -}); diff --git a/packages/react-devtools-scheduling-profiler/src/import-worker/preprocessData.js b/packages/react-devtools-scheduling-profiler/src/import-worker/preprocessData.js index e5239fd78d1fa..da4153f677de3 100644 --- a/packages/react-devtools-scheduling-profiler/src/import-worker/preprocessData.js +++ b/packages/react-devtools-scheduling-profiler/src/import-worker/preprocessData.js @@ -82,6 +82,7 @@ function markWorkStarted( type: ReactMeasureType, startTime: Milliseconds, lanes: ReactLane[], + laneLabels: Array, currentProfilerData: ReactProfilerData, state: ProcessorState, ) { @@ -96,6 +97,7 @@ function markWorkStarted( batchUID, depth, lanes, + laneLabels, timestamp: startTime, duration: 0, }); @@ -168,18 +170,20 @@ function processTimelineEvent( // React Events - schedule if (name.startsWith('--schedule-render-')) { - const [laneBitmaskString, ...splitComponentStack] = name + const [laneBitmaskString, laneLabels, ...splitComponentStack] = name .substr(18) .split('-'); currentProfilerData.events.push({ type: 'schedule-render', lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString), + laneLabels: laneLabels ? laneLabels.split(',') : [], componentStack: splitComponentStack.join('-'), timestamp: startTime, }); } else if (name.startsWith('--schedule-forced-update-')) { const [ laneBitmaskString, + laneLabels, componentName, ...splitComponentStack ] = name.substr(25).split('-'); @@ -189,6 +193,7 @@ function processTimelineEvent( currentProfilerData.events.push({ type: 'schedule-force-update', lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString), + laneLabels: laneLabels ? laneLabels.split(',') : [], componentName, componentStack: splitComponentStack.join('-'), timestamp: startTime, @@ -197,6 +202,7 @@ function processTimelineEvent( } else if (name.startsWith('--schedule-state-update-')) { const [ laneBitmaskString, + laneLabels, componentName, ...splitComponentStack ] = name.substr(24).split('-'); @@ -206,6 +212,7 @@ function processTimelineEvent( currentProfilerData.events.push({ type: 'schedule-state-update', lanes: getLanesFromTransportDecimalBitmask(laneBitmaskString), + laneLabels: laneLabels ? laneLabels.split(',') : [], componentName, componentStack: splitComponentStack.join('-'), timestamp: startTime, @@ -255,7 +262,7 @@ function processTimelineEvent( state.nextRenderShouldGenerateNewBatchID = false; state.batchUID = ((state.uidCounter++: any): BatchUID); } - const laneBitmaskString = name.substr(15); + const [laneBitmaskString, laneLabels] = name.substr(15).split('-'); const lanes = getLanesFromTransportDecimalBitmask(laneBitmaskString); throwIfIncomplete('render', state.measureStack); if (getLastType(state.measureStack) !== 'render-idle') { @@ -263,11 +270,19 @@ function processTimelineEvent( 'render-idle', startTime, lanes, + laneLabels ? laneLabels.split(',') : [], currentProfilerData, state, ); } - markWorkStarted('render', startTime, lanes, currentProfilerData, state); + markWorkStarted( + 'render', + startTime, + lanes, + laneLabels ? laneLabels.split(',') : [], + currentProfilerData, + state, + ); } else if ( name.startsWith('--render-stop') || name.startsWith('--render-yield') @@ -297,9 +312,16 @@ function processTimelineEvent( // React Measures - commits else if (name.startsWith('--commit-start-')) { state.nextRenderShouldGenerateNewBatchID = true; - const laneBitmaskString = name.substr(15); + const [laneBitmaskString, laneLabels] = name.substr(15).split('-'); const lanes = getLanesFromTransportDecimalBitmask(laneBitmaskString); - markWorkStarted('commit', startTime, lanes, currentProfilerData, state); + markWorkStarted( + 'commit', + startTime, + lanes, + laneLabels ? laneLabels.split(',') : [], + currentProfilerData, + state, + ); } else if (name.startsWith('--commit-stop')) { markWorkCompleted( 'commit', @@ -317,12 +339,13 @@ function processTimelineEvent( // React Measures - layout effects else if (name.startsWith('--layout-effects-start-')) { - const laneBitmaskString = name.substr(23); + const [laneBitmaskString, laneLabels] = name.substr(23).split('-'); const lanes = getLanesFromTransportDecimalBitmask(laneBitmaskString); markWorkStarted( 'layout-effects', startTime, lanes, + laneLabels ? laneLabels.split(',') : [], currentProfilerData, state, ); @@ -337,12 +360,13 @@ function processTimelineEvent( // React Measures - passive effects else if (name.startsWith('--passive-effects-start-')) { - const laneBitmaskString = name.substr(24); + const [laneBitmaskString, laneLabels] = name.substr(24).split('-'); const lanes = getLanesFromTransportDecimalBitmask(laneBitmaskString); markWorkStarted( 'passive-effects', startTime, lanes, + laneLabels ? laneLabels.split(',') : [], currentProfilerData, state, ); @@ -366,6 +390,9 @@ function processTimelineEvent( // TODO: Begin user timing measure } else if (ph === 'e') { // TODO: End user timing measure + } else if (ph === 'i' || ph === 'I') { + // Instant events. + // Note that the capital "I" is a deprecated value that exists in Chrome Canary traces. } // eslint-disable-line brace-style // Unrecognized event diff --git a/packages/react-devtools-scheduling-profiler/src/types.js b/packages/react-devtools-scheduling-profiler/src/types.js index a5a1c0d43b221..833df582a5296 100644 --- a/packages/react-devtools-scheduling-profiler/src/types.js +++ b/packages/react-devtools-scheduling-profiler/src/types.js @@ -30,6 +30,7 @@ type BaseReactEvent = {| type BaseReactScheduleEvent = {| ...BaseReactEvent, +lanes: ReactLane[], + +laneLabels: string[], |}; export type ReactScheduleRenderEvent = {| ...BaseReactScheduleEvent, @@ -86,6 +87,7 @@ export type BatchUID = number; export type ReactMeasure = {| +type: ReactMeasureType, +lanes: ReactLane[], + +laneLabels: string[], +timestamp: Milliseconds, +duration: Milliseconds, +batchUID: BatchUID, diff --git a/packages/react-devtools-scheduling-profiler/webpack.config.js b/packages/react-devtools-scheduling-profiler/webpack.config.js index b69a5d1b411ee..9a167dda3f7e3 100644 --- a/packages/react-devtools-scheduling-profiler/webpack.config.js +++ b/packages/react-devtools-scheduling-profiler/webpack.config.js @@ -56,6 +56,7 @@ const config = { __DEV__, __PROFILE__: false, __EXPERIMENTAL__: true, + __VARIANT__: false, 'process.env.DEVTOOLS_VERSION': `"${DEVTOOLS_VERSION}"`, }), new HtmlWebpackPlugin({ @@ -112,7 +113,7 @@ const config = { if (shouldUseDevServer) { config.devServer = { hot: true, - port: 8080, + port: 8081, clientLogLevel: 'warning', stats: 'errors-only', }; diff --git a/packages/react-reconciler/src/ReactFiberLane.new.js b/packages/react-reconciler/src/ReactFiberLane.new.js index 5f14a3140e30f..7e577abb228e2 100644 --- a/packages/react-reconciler/src/ReactFiberLane.new.js +++ b/packages/react-reconciler/src/ReactFiberLane.new.js @@ -36,7 +36,7 @@ export type Lane = number; export type LaneMap = Array; import invariant from 'shared/invariant'; -import {enableCache} from 'shared/ReactFeatureFlags'; +import {enableCache, enableSchedulingProfiler} from 'shared/ReactFeatureFlags'; import { ImmediatePriority as ImmediateSchedulerPriority, @@ -73,7 +73,10 @@ const OffscreenLanePriority: LanePriority = 1; export const NoLanePriority: LanePriority = 0; -const TotalLanes = 31; +// Lane values below should be kept in sync with getLabelsForLanes(), used by react-devtools-scheduling-profiler. +// If those values are changed that package should be rebuilt and redeployed. + +export const TotalLanes = 31; export const NoLanes: Lanes = /* */ 0b0000000000000000000000000000000; export const NoLane: Lane = /* */ 0b0000000000000000000000000000000; @@ -82,10 +85,10 @@ export const SyncLane: Lane = /* */ 0b0000000000000000000 export const SyncBatchedLane: Lane = /* */ 0b0000000000000000000000000000010; export const InputDiscreteHydrationLane: Lane = /* */ 0b0000000000000000000000000000100; -const InputDiscreteLane: Lanes = /* */ 0b0000000000000000000000000001000; +export const InputDiscreteLane: Lanes = /* */ 0b0000000000000000000000000001000; const InputContinuousHydrationLane: Lane = /* */ 0b0000000000000000000000000010000; -const InputContinuousLane: Lanes = /* */ 0b0000000000000000000000000100000; +export const InputContinuousLane: Lanes = /* */ 0b0000000000000000000000000100000; export const DefaultHydrationLane: Lane = /* */ 0b0000000000000000000000001000000; export const DefaultLane: Lanes = /* */ 0b0000000000000000000000010000000; @@ -124,6 +127,60 @@ const IdleLane: Lanes = /* */ 0b0100000000000000000 export const OffscreenLane: Lane = /* */ 0b1000000000000000000000000000000; +// This function is used for the experimental scheduling profiler (react-devtools-scheduling-profiler) +// It should be kept in sync with the Lanes values above. +export function getLabelsForLanes(lanes: Lanes): Array | void { + if (enableSchedulingProfiler) { + const labels = []; + if (lanes & SyncLane) { + labels.push('Sync'); + } + if (lanes & SyncBatchedLane) { + labels.push('SyncBatched'); + } + if (lanes & InputDiscreteHydrationLane) { + labels.push('InputDiscreteHydration'); + } + if (lanes & InputDiscreteLane) { + labels.push('InputDiscrete'); + } + if (lanes & InputContinuousHydrationLane) { + labels.push('InputContinuousHydration'); + } + if (lanes & InputContinuousLane) { + labels.push('InputContinuous'); + } + if (lanes & DefaultHydrationLane) { + labels.push('DefaultHydration'); + } + if (lanes & DefaultLane) { + labels.push('Default'); + } + if (lanes & TransitionHydrationLane) { + labels.push('TransitionHydration'); + } + if (lanes & TransitionLanes) { + labels.push('Transition(s)'); + } + if (lanes & RetryLanes) { + labels.push('Retry(s)'); + } + if (lanes & SelectiveHydrationLane) { + labels.push('SelectiveHydration'); + } + if (lanes & IdleHydrationLane) { + labels.push('IdleHydration'); + } + if (lanes & IdleLane) { + labels.push('Idle'); + } + if (lanes & OffscreenLane) { + labels.push('Offscreen'); + } + return labels; + } +} + export const NoTimestamp = -1; let currentUpdateLanePriority: LanePriority = NoLanePriority; diff --git a/packages/react-reconciler/src/ReactFiberLane.old.js b/packages/react-reconciler/src/ReactFiberLane.old.js index 3c3eab4c8612f..af73a5e565871 100644 --- a/packages/react-reconciler/src/ReactFiberLane.old.js +++ b/packages/react-reconciler/src/ReactFiberLane.old.js @@ -36,7 +36,7 @@ export type Lane = number; export type LaneMap = Array; import invariant from 'shared/invariant'; -import {enableCache} from 'shared/ReactFeatureFlags'; +import {enableCache, enableSchedulingProfiler} from 'shared/ReactFeatureFlags'; import { ImmediatePriority as ImmediateSchedulerPriority, @@ -73,7 +73,10 @@ const OffscreenLanePriority: LanePriority = 1; export const NoLanePriority: LanePriority = 0; -const TotalLanes = 31; +// Lane values below should be kept in sync with getLabelsForLanes(), used by react-devtools-scheduling-profiler. +// If those values are changed that package should be rebuilt and redeployed. + +export const TotalLanes = 31; export const NoLanes: Lanes = /* */ 0b0000000000000000000000000000000; export const NoLane: Lane = /* */ 0b0000000000000000000000000000000; @@ -82,10 +85,10 @@ export const SyncLane: Lane = /* */ 0b0000000000000000000 export const SyncBatchedLane: Lane = /* */ 0b0000000000000000000000000000010; export const InputDiscreteHydrationLane: Lane = /* */ 0b0000000000000000000000000000100; -const InputDiscreteLane: Lanes = /* */ 0b0000000000000000000000000001000; +export const InputDiscreteLane: Lanes = /* */ 0b0000000000000000000000000001000; const InputContinuousHydrationLane: Lane = /* */ 0b0000000000000000000000000010000; -const InputContinuousLane: Lanes = /* */ 0b0000000000000000000000000100000; +export const InputContinuousLane: Lanes = /* */ 0b0000000000000000000000000100000; export const DefaultHydrationLane: Lane = /* */ 0b0000000000000000000000001000000; export const DefaultLane: Lanes = /* */ 0b0000000000000000000000010000000; @@ -124,6 +127,60 @@ const IdleLane: Lanes = /* */ 0b0100000000000000000 export const OffscreenLane: Lane = /* */ 0b1000000000000000000000000000000; +// This function is used for the experimental scheduling profiler (react-devtools-scheduling-profiler) +// It should be kept in sync with the Lanes values above. +export function getLabelsForLanes(lanes: Lanes): Array | void { + if (enableSchedulingProfiler) { + const labels = []; + if (lanes & SyncLane) { + labels.push('Sync'); + } + if (lanes & SyncBatchedLane) { + labels.push('SyncBatched'); + } + if (lanes & InputDiscreteHydrationLane) { + labels.push('InputDiscreteHydration'); + } + if (lanes & InputDiscreteLane) { + labels.push('InputDiscrete'); + } + if (lanes & InputContinuousHydrationLane) { + labels.push('InputContinuousHydration'); + } + if (lanes & InputContinuousLane) { + labels.push('InputContinuous'); + } + if (lanes & DefaultHydrationLane) { + labels.push('DefaultHydration'); + } + if (lanes & DefaultLane) { + labels.push('Default'); + } + if (lanes & TransitionHydrationLane) { + labels.push('TransitionHydration'); + } + if (lanes & TransitionLanes) { + labels.push('Transition(s)'); + } + if (lanes & RetryLanes) { + labels.push('Retry(s)'); + } + if (lanes & SelectiveHydrationLane) { + labels.push('SelectiveHydration'); + } + if (lanes & IdleHydrationLane) { + labels.push('IdleHydration'); + } + if (lanes & IdleLane) { + labels.push('Idle'); + } + if (lanes & OffscreenLane) { + labels.push('Offscreen'); + } + return labels; + } +} + export const NoTimestamp = -1; let currentUpdateLanePriority: LanePriority = NoLanePriority; diff --git a/packages/react-reconciler/src/SchedulingProfiler.js b/packages/react-reconciler/src/SchedulingProfiler.js index 0779b870a274b..ccc41f9854876 100644 --- a/packages/react-reconciler/src/SchedulingProfiler.js +++ b/packages/react-reconciler/src/SchedulingProfiler.js @@ -11,10 +11,20 @@ import type {Lane, Lanes} from './ReactFiberLane.old'; import type {Fiber} from './ReactInternalTypes'; import type {Wakeable} from 'shared/ReactTypes'; -import {enableSchedulingProfiler} from 'shared/ReactFeatureFlags'; +import { + enableNewReconciler, + enableSchedulingProfiler, +} from 'shared/ReactFeatureFlags'; import ReactVersion from 'shared/ReactVersion'; import getComponentName from 'shared/getComponentName'; +import {getLabelsForLanes as getLabelsForLanes_old} from 'react-reconciler/src/ReactFiberLane.old'; +import {getLabelsForLanes as getLabelsForLanes_new} from 'react-reconciler/src/ReactFiberLane.new'; + +const getLabelsForLanes = enableNewReconciler + ? getLabelsForLanes_new + : getLabelsForLanes_old; + /** * If performance exists and supports the subset of the User Timing API that we * require. @@ -49,8 +59,14 @@ if (enableSchedulingProfiler) { } } -function formatLanes(laneOrLanes: Lane | Lanes): string { - return ((laneOrLanes: any): number).toString(); +export function formatLanes(laneOrLanes: Lane | Lanes): string { + let labels = getLabelsForLanes(laneOrLanes); + if (labels != null) { + labels = labels.sort().join(','); + } else { + labels = ''; + } + return `${laneOrLanes}-${labels}`; } function markAndClear(name) { diff --git a/packages/react-reconciler/src/__tests__/SchedulingProfiler-test.internal.js b/packages/react-reconciler/src/__tests__/SchedulingProfiler-test.internal.js index dd3528da50fe1..14f7f0412c9d4 100644 --- a/packages/react-reconciler/src/__tests__/SchedulingProfiler-test.internal.js +++ b/packages/react-reconciler/src/__tests__/SchedulingProfiler-test.internal.js @@ -10,6 +10,7 @@ 'use strict'; +// This test is *.internal so that it can import this shared file. import ReactVersion from 'shared/ReactVersion'; describe('SchedulingProfiler', () => { @@ -17,9 +18,11 @@ describe('SchedulingProfiler', () => { let ReactTestRenderer; let ReactNoop; let Scheduler; + let ReactFiberLane; let clearedMarks; let featureDetectionMarkName = null; + let formatLanes; let marks; function createUserTimingPolyfill() { @@ -76,6 +79,14 @@ describe('SchedulingProfiler', () => { ReactNoop = require('react-noop-renderer'); Scheduler = require('scheduler'); + + const SchedulingProfiler = require('react-reconciler/src/SchedulingProfiler'); + formatLanes = SchedulingProfiler.formatLanes; + + const ReactFeatureFlags = require('shared/ReactFeatureFlags'); + ReactFiberLane = ReactFeatureFlags.enableNewReconciler + ? require('react-reconciler/src/ReactFiberLane.new') + : require('react-reconciler/src/ReactFiberLane.old'); }); afterEach(() => { @@ -85,9 +96,6 @@ describe('SchedulingProfiler', () => { delete global.performance; }); - // This is coupled to implementation - const DEFAULT_LANE = 128; - // @gate !enableSchedulingProfiler it('should not mark if enableSchedulingProfiler is false', () => { ReactTestRenderer.create(
); @@ -105,11 +113,11 @@ describe('SchedulingProfiler', () => { expectMarksToEqual([ `--react-init-${ReactVersion}`, - '--schedule-render-1', - '--render-start-1', + `--schedule-render-${formatLanes(ReactFiberLane.SyncLane)}`, + `--render-start-${formatLanes(ReactFiberLane.SyncLane)}`, '--render-stop', - '--commit-start-1', - '--layout-effects-start-1', + `--commit-start-${formatLanes(ReactFiberLane.SyncLane)}`, + `--layout-effects-start-${formatLanes(ReactFiberLane.SyncLane)}`, '--layout-effects-stop', '--commit-stop', ]); @@ -121,7 +129,7 @@ describe('SchedulingProfiler', () => { expectMarksToEqual([ `--react-init-${ReactVersion}`, - `--schedule-render-${DEFAULT_LANE}`, + `--schedule-render-${formatLanes(ReactFiberLane.DefaultLane)}`, ]); clearPendingMarks(); @@ -129,10 +137,10 @@ describe('SchedulingProfiler', () => { expect(Scheduler).toFlushUntilNextPaint([]); expectMarksToEqual([ - `--render-start-${DEFAULT_LANE}`, + `--render-start-${formatLanes(ReactFiberLane.DefaultLane)}`, '--render-stop', - `--commit-start-${DEFAULT_LANE}`, - `--layout-effects-start-${DEFAULT_LANE}`, + `--commit-start-${formatLanes(ReactFiberLane.DefaultLane)}`, + `--layout-effects-start-${formatLanes(ReactFiberLane.DefaultLane)}`, '--layout-effects-stop', '--commit-stop', ]); @@ -156,8 +164,8 @@ describe('SchedulingProfiler', () => { expectMarksToEqual([ `--react-init-${ReactVersion}`, - `--schedule-render-${DEFAULT_LANE}`, - `--render-start-${DEFAULT_LANE}`, + `--schedule-render-${formatLanes(ReactFiberLane.DefaultLane)}`, + `--render-start-${formatLanes(ReactFiberLane.DefaultLane)}`, '--render-yield', ]); }); @@ -177,12 +185,12 @@ describe('SchedulingProfiler', () => { expectMarksToEqual([ `--react-init-${ReactVersion}`, - '--schedule-render-1', - '--render-start-1', + `--schedule-render-${formatLanes(ReactFiberLane.SyncLane)}`, + `--render-start-${formatLanes(ReactFiberLane.SyncLane)}`, '--suspense-suspend-0-Example', '--render-stop', - '--commit-start-1', - '--layout-effects-start-1', + `--commit-start-${formatLanes(ReactFiberLane.SyncLane)}`, + `--layout-effects-start-${formatLanes(ReactFiberLane.SyncLane)}`, '--layout-effects-stop', '--commit-stop', ]); @@ -208,12 +216,12 @@ describe('SchedulingProfiler', () => { expectMarksToEqual([ `--react-init-${ReactVersion}`, - '--schedule-render-1', - '--render-start-1', + `--schedule-render-${formatLanes(ReactFiberLane.SyncLane)}`, + `--render-start-${formatLanes(ReactFiberLane.SyncLane)}`, '--suspense-suspend-0-Example', '--render-stop', - '--commit-start-1', - '--layout-effects-start-1', + `--commit-start-${formatLanes(ReactFiberLane.SyncLane)}`, + `--layout-effects-start-${formatLanes(ReactFiberLane.SyncLane)}`, '--layout-effects-stop', '--commit-stop', ]); @@ -240,7 +248,7 @@ describe('SchedulingProfiler', () => { expectMarksToEqual([ `--react-init-${ReactVersion}`, - `--schedule-render-${DEFAULT_LANE}`, + `--schedule-render-${formatLanes(ReactFiberLane.DefaultLane)}`, ]); clearPendingMarks(); @@ -248,11 +256,11 @@ describe('SchedulingProfiler', () => { expect(Scheduler).toFlushUntilNextPaint([]); expectMarksToEqual([ - `--render-start-${DEFAULT_LANE}`, + `--render-start-${formatLanes(ReactFiberLane.DefaultLane)}`, '--suspense-suspend-0-Example', '--render-stop', - `--commit-start-${DEFAULT_LANE}`, - `--layout-effects-start-${DEFAULT_LANE}`, + `--commit-start-${formatLanes(ReactFiberLane.DefaultLane)}`, + `--layout-effects-start-${formatLanes(ReactFiberLane.DefaultLane)}`, '--layout-effects-stop', '--commit-stop', ]); @@ -279,7 +287,7 @@ describe('SchedulingProfiler', () => { expectMarksToEqual([ `--react-init-${ReactVersion}`, - `--schedule-render-${DEFAULT_LANE}`, + `--schedule-render-${formatLanes(ReactFiberLane.DefaultLane)}`, ]); clearPendingMarks(); @@ -287,11 +295,11 @@ describe('SchedulingProfiler', () => { expect(Scheduler).toFlushUntilNextPaint([]); expectMarksToEqual([ - `--render-start-${DEFAULT_LANE}`, + `--render-start-${formatLanes(ReactFiberLane.DefaultLane)}`, '--suspense-suspend-0-Example', '--render-stop', - `--commit-start-${DEFAULT_LANE}`, - `--layout-effects-start-${DEFAULT_LANE}`, + `--commit-start-${formatLanes(ReactFiberLane.DefaultLane)}`, + `--layout-effects-start-${formatLanes(ReactFiberLane.DefaultLane)}`, '--layout-effects-stop', '--commit-stop', ]); @@ -318,7 +326,7 @@ describe('SchedulingProfiler', () => { expectMarksToEqual([ `--react-init-${ReactVersion}`, - `--schedule-render-${DEFAULT_LANE}`, + `--schedule-render-${formatLanes(ReactFiberLane.DefaultLane)}`, ]); clearPendingMarks(); @@ -326,15 +334,15 @@ describe('SchedulingProfiler', () => { expect(Scheduler).toFlushUntilNextPaint([]); expectMarksToEqual([ - `--render-start-${DEFAULT_LANE}`, + `--render-start-${formatLanes(ReactFiberLane.DefaultLane)}`, '--render-stop', - `--commit-start-${DEFAULT_LANE}`, - `--layout-effects-start-${DEFAULT_LANE}`, - '--schedule-state-update-1-Example', + `--commit-start-${formatLanes(ReactFiberLane.DefaultLane)}`, + `--layout-effects-start-${formatLanes(ReactFiberLane.DefaultLane)}`, + `--schedule-state-update-${formatLanes(ReactFiberLane.SyncLane)}-Example`, '--layout-effects-stop', - '--render-start-1', + `--render-start-${formatLanes(ReactFiberLane.SyncLane)}`, '--render-stop', - '--commit-start-1', + `--commit-start-${formatLanes(ReactFiberLane.SyncLane)}`, '--commit-stop', '--commit-stop', ]); @@ -355,7 +363,7 @@ describe('SchedulingProfiler', () => { expectMarksToEqual([ `--react-init-${ReactVersion}`, - `--schedule-render-${DEFAULT_LANE}`, + `--schedule-render-${formatLanes(ReactFiberLane.DefaultLane)}`, ]); clearPendingMarks(); @@ -363,15 +371,17 @@ describe('SchedulingProfiler', () => { expect(Scheduler).toFlushUntilNextPaint([]); expectMarksToEqual([ - `--render-start-${DEFAULT_LANE}`, + `--render-start-${formatLanes(ReactFiberLane.DefaultLane)}`, '--render-stop', - `--commit-start-${DEFAULT_LANE}`, - `--layout-effects-start-${DEFAULT_LANE}`, - '--schedule-forced-update-1-Example', + `--commit-start-${formatLanes(ReactFiberLane.DefaultLane)}`, + `--layout-effects-start-${formatLanes(ReactFiberLane.DefaultLane)}`, + `--schedule-forced-update-${formatLanes( + ReactFiberLane.SyncLane, + )}-Example`, '--layout-effects-stop', - '--render-start-1', + `--render-start-${formatLanes(ReactFiberLane.SyncLane)}`, '--render-stop', - '--commit-start-1', + `--commit-start-${formatLanes(ReactFiberLane.SyncLane)}`, '--commit-stop', '--commit-stop', ]); @@ -393,7 +403,7 @@ describe('SchedulingProfiler', () => { expectMarksToEqual([ `--react-init-${ReactVersion}`, - `--schedule-render-${DEFAULT_LANE}`, + `--schedule-render-${formatLanes(ReactFiberLane.DefaultLane)}`, ]); clearPendingMarks(); @@ -402,7 +412,11 @@ describe('SchedulingProfiler', () => { expect(Scheduler).toFlushUntilNextPaint([]); }).toErrorDev('Cannot update during an existing state transition'); - expectMarksToContain(`--schedule-state-update-${DEFAULT_LANE}-Example`); + expectMarksToContain( + `--schedule-state-update-${formatLanes( + ReactFiberLane.DefaultLane, + )}-Example`, + ); }); // @gate enableSchedulingProfiler @@ -421,7 +435,7 @@ describe('SchedulingProfiler', () => { expectMarksToEqual([ `--react-init-${ReactVersion}`, - `--schedule-render-${DEFAULT_LANE}`, + `--schedule-render-${formatLanes(ReactFiberLane.DefaultLane)}`, ]); clearPendingMarks(); @@ -430,7 +444,11 @@ describe('SchedulingProfiler', () => { expect(Scheduler).toFlushUntilNextPaint([]); }).toErrorDev('Cannot update during an existing state transition'); - expectMarksToContain(`--schedule-forced-update-${DEFAULT_LANE}-Example`); + expectMarksToContain( + `--schedule-forced-update-${formatLanes( + ReactFiberLane.DefaultLane, + )}-Example`, + ); }); // @gate enableSchedulingProfiler @@ -447,7 +465,7 @@ describe('SchedulingProfiler', () => { expectMarksToEqual([ `--react-init-${ReactVersion}`, - `--schedule-render-${DEFAULT_LANE}`, + `--schedule-render-${formatLanes(ReactFiberLane.DefaultLane)}`, ]); clearPendingMarks(); @@ -455,15 +473,15 @@ describe('SchedulingProfiler', () => { expect(Scheduler).toFlushUntilNextPaint([]); expectMarksToEqual([ - `--render-start-${DEFAULT_LANE}`, + `--render-start-${formatLanes(ReactFiberLane.DefaultLane)}`, '--render-stop', - `--commit-start-${DEFAULT_LANE}`, - `--layout-effects-start-${DEFAULT_LANE}`, - '--schedule-state-update-1-Example', + `--commit-start-${formatLanes(ReactFiberLane.DefaultLane)}`, + `--layout-effects-start-${formatLanes(ReactFiberLane.DefaultLane)}`, + `--schedule-state-update-${formatLanes(ReactFiberLane.SyncLane)}-Example`, '--layout-effects-stop', - '--render-start-1', + `--render-start-${formatLanes(ReactFiberLane.SyncLane)}`, '--render-stop', - '--commit-start-1', + `--commit-start-${formatLanes(ReactFiberLane.SyncLane)}`, '--commit-stop', '--commit-stop', ]); @@ -487,19 +505,21 @@ describe('SchedulingProfiler', () => { expectMarksToEqual([ `--react-init-${ReactVersion}`, - `--schedule-render-${DEFAULT_LANE}`, - `--render-start-${DEFAULT_LANE}`, + `--schedule-render-${formatLanes(ReactFiberLane.DefaultLane)}`, + `--render-start-${formatLanes(ReactFiberLane.DefaultLane)}`, '--render-stop', - `--commit-start-${DEFAULT_LANE}`, - `--layout-effects-start-${DEFAULT_LANE}`, + `--commit-start-${formatLanes(ReactFiberLane.DefaultLane)}`, + `--layout-effects-start-${formatLanes(ReactFiberLane.DefaultLane)}`, '--layout-effects-stop', '--commit-stop', - `--passive-effects-start-${DEFAULT_LANE}`, - `--schedule-state-update-${DEFAULT_LANE}-Example`, + `--passive-effects-start-${formatLanes(ReactFiberLane.DefaultLane)}`, + `--schedule-state-update-${formatLanes( + ReactFiberLane.DefaultLane, + )}-Example`, '--passive-effects-stop', - `--render-start-${DEFAULT_LANE}`, + `--render-start-${formatLanes(ReactFiberLane.DefaultLane)}`, '--render-stop', - `--commit-start-${DEFAULT_LANE}`, + `--commit-start-${formatLanes(ReactFiberLane.DefaultLane)}`, '--commit-stop', ]); }); @@ -518,6 +538,10 @@ describe('SchedulingProfiler', () => { ReactTestRenderer.create(, {unstable_isConcurrent: true}); }); - expectMarksToContain(`--schedule-state-update-${DEFAULT_LANE}-Example`); + expectMarksToContain( + `--schedule-state-update-${formatLanes( + ReactFiberLane.DefaultLane, + )}-Example`, + ); }); }); diff --git a/packages/react-reconciler/src/__tests__/SchedulingProfilerLabels-test.internal.js b/packages/react-reconciler/src/__tests__/SchedulingProfilerLabels-test.internal.js new file mode 100644 index 0000000000000..d06371940b470 --- /dev/null +++ b/packages/react-reconciler/src/__tests__/SchedulingProfilerLabels-test.internal.js @@ -0,0 +1,179 @@ +/** + * 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. + * + * @emails react-core + */ + +'use strict'; + +// This test schedules work for as many lanes as we can (easily) using public APIs. +// It will hopefully serve as a reminder to update getLabelsForLanes() when we update Lanes. +// It's okay to delete any individual test in this file if the public API changes. +describe('SchedulingProfiler labels', () => { + let React; + let ReactDOM; + let ReactFiberLane; + + let act; + let clearedMarks; + let featureDetectionMarkName = null; + let formatLanes; + let marks; + + function polyfillJSDomUserTiming() { + featureDetectionMarkName = null; + + clearedMarks = []; + marks = []; + + // This is not a true polyfill, but it gives us enough to capture marks. + // Reference: https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API + + // JSDom already implements global.performance and it can't be overridden. + // However it only supports now() and timeOrigin() so we need to "upgrade it" in place. + + if (!global.performance) { + global.performance = {}; + } + + global.performance.clearMarks = function clearMarks(markName) { + clearedMarks.push(markName); + marks = marks.filter(mark => mark !== markName); + }; + + global.performance.mark = function mark(markName, markOptions) { + if (featureDetectionMarkName === null) { + featureDetectionMarkName = markName; + } + marks.push(markName); + if (markOptions != null) { + // This is triggers the feature detection. + markOptions.startTime++; + } + }; + } + + function dispatchAndSetCurrentEvent(element, event) { + try { + window.event = event; + element.dispatchEvent(event); + } finally { + window.event = undefined; + } + } + + beforeEach(() => { + jest.resetModules(); + + polyfillJSDomUserTiming(); + + React = require('react'); + ReactDOM = require('react-dom'); + + const TestUtils = require('react-dom/test-utils'); + act = TestUtils.act; + + const SchedulingProfiler = require('react-reconciler/src/SchedulingProfiler'); + formatLanes = SchedulingProfiler.formatLanes; + + const ReactFeatureFlags = require('shared/ReactFeatureFlags'); + ReactFiberLane = ReactFeatureFlags.enableNewReconciler + ? require('react-reconciler/src/ReactFiberLane.new') + : require('react-reconciler/src/ReactFiberLane.old'); + }); + + afterEach(() => { + // Verify all logged marks also get cleared. + expect(marks).toHaveLength(0); + + delete global.performance; + }); + + // @gate enableSchedulingProfiler + it('regression test SyncLane', () => { + ReactDOM.render(
, document.createElement('div')); + expect(clearedMarks).toContain( + `--schedule-render-${formatLanes(ReactFiberLane.SyncLane)}`, + ); + }); + + // @gate experimental + // @gate enableSchedulingProfiler + it('regression test DefaultLane', () => { + const container = document.createElement('div'); + const root = ReactDOM.createRoot(container); + + act(() => { + root.render(
); + expect(clearedMarks).toContain( + `--schedule-render-${formatLanes(ReactFiberLane.DefaultLane)}`, + ); + }); + }); + + // @gate experimental + // @gate enableSchedulingProfiler + // @gate !enableLegacyFBSupport + it('regression test InputDiscreteLane', () => { + const container = document.createElement('div'); + const root = ReactDOM.createRoot(container); + const targetRef = React.createRef(null); + + function App() { + const [count, setCount] = React.useState(0); + const handleClick = () => { + setCount(count + 1); + }; + return