@paulirish/trace_engine 0.0.10 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/analyze-trace.mjs +1 -1
- package/core/platform/DevToolsPath.d.ts +4 -13
- package/core/platform/DevToolsPath.js +7 -4
- package/core/platform/DevToolsPath.js.map +1 -7
- package/core/platform/MimeType.d.ts +27 -0
- package/core/platform/MimeType.js +119 -86
- package/core/platform/MimeType.js.map +1 -7
- package/core/platform/Timing.d.ts +7 -0
- package/core/platform/Timing.js +7 -4
- package/core/platform/Timing.js.map +1 -7
- package/core/platform/UIString.d.ts +2 -5
- package/core/platform/UIString.js +5 -2
- package/core/platform/UIString.js.map +1 -7
- package/core/platform/UserVisibleError.js +19 -10
- package/core/platform/UserVisibleError.js.map +1 -7
- package/core/platform/array-utilities.d.ts +48 -10
- package/core/platform/array-utilities.js +160 -124
- package/core/platform/array-utilities.js.map +1 -7
- package/core/platform/brand.d.ts +14 -0
- package/core/platform/brand.js +5 -1
- package/core/platform/brand.js.map +1 -7
- package/core/platform/date-utilities.js +10 -6
- package/core/platform/date-utilities.js.map +1 -7
- package/core/platform/dom-utilities.d.ts +3 -1
- package/core/platform/dom-utilities.js +94 -83
- package/core/platform/dom-utilities.js.map +1 -7
- package/core/platform/keyboard-utilities.d.ts +2 -0
- package/core/platform/keyboard-utilities.js +15 -24
- package/core/platform/keyboard-utilities.js.map +1 -7
- package/core/platform/map-utilities.d.ts +4 -0
- package/core/platform/map-utilities.js +66 -60
- package/core/platform/map-utilities.js.map +1 -7
- package/core/platform/number-utilities.js +66 -55
- package/core/platform/number-utilities.js.map +1 -7
- package/core/platform/platform.d.ts +5 -1
- package/core/platform/platform.js +54 -37
- package/core/platform/platform.js.map +1 -7
- package/core/platform/promise-utilities.d.ts +10 -0
- package/core/platform/promise-utilities.js +16 -8
- package/core/platform/promise-utilities.js.map +1 -7
- package/core/platform/set-utilities.js +20 -17
- package/core/platform/set-utilities.js.map +1 -7
- package/core/platform/string-utilities.d.ts +32 -1
- package/core/platform/string-utilities.js +453 -379
- package/core/platform/string-utilities.js.map +1 -7
- package/core/platform/typescript-utilities.d.ts +5 -5
- package/core/platform/typescript-utilities.js +19 -7
- package/core/platform/typescript-utilities.js.map +1 -7
- package/generated/protocol.d.ts +2081 -347
- package/generated/protocol.js +5 -2230
- package/models/cpu_profile/CPUProfileDataModel.d.ts +77 -0
- package/models/cpu_profile/CPUProfileDataModel.js +492 -359
- package/models/cpu_profile/CPUProfileDataModel.js.map +1 -7
- package/models/cpu_profile/ProfileTreeModel.d.ts +29 -0
- package/models/cpu_profile/ProfileTreeModel.js +87 -82
- package/models/cpu_profile/ProfileTreeModel.js.map +1 -7
- package/models/cpu_profile/cpu_profile.d.ts +3 -0
- package/models/cpu_profile/cpu_profile.js +7 -7
- package/models/cpu_profile/cpu_profile.js.map +1 -7
- package/models/trace/EntriesFilter.d.ts +55 -0
- package/models/trace/EntriesFilter.js +227 -166
- package/models/trace/EntriesFilter.js.map +1 -7
- package/models/trace/LegacyTracingModel.js.map +1 -7
- package/models/trace/ModelImpl.d.ts +110 -0
- package/models/trace/ModelImpl.js +161 -102
- package/models/trace/ModelImpl.js.map +1 -7
- package/models/trace/Processor.d.ts +36 -0
- package/models/trace/Processor.js +197 -163
- package/models/trace/Processor.js.map +1 -7
- package/models/trace/TracingManager.js.map +1 -7
- package/models/trace/extras/FetchNodes.d.ts +46 -0
- package/models/trace/extras/FetchNodes.js +132 -91
- package/models/trace/extras/FetchNodes.js.map +1 -7
- package/models/trace/extras/FilmStrip.d.ts +19 -0
- package/models/trace/extras/FilmStrip.js +38 -31
- package/models/trace/extras/FilmStrip.js.map +1 -7
- package/models/trace/extras/MainThreadActivity.d.ts +2 -0
- package/models/trace/extras/MainThreadActivity.js +72 -56
- package/models/trace/extras/MainThreadActivity.js.map +1 -7
- package/models/trace/extras/Metadata.d.ts +2 -0
- package/models/trace/extras/Metadata.js +42 -26
- package/models/trace/extras/Metadata.js.map +1 -7
- package/models/trace/extras/extras.js.map +1 -7
- package/models/trace/handlers/AnimationHandler.d.ts +8 -0
- package/models/trace/handlers/AnimationHandler.js +22 -20
- package/models/trace/handlers/AnimationHandler.js.map +1 -7
- package/models/trace/handlers/AuctionWorkletsHandler.d.ts +8 -0
- package/models/trace/handlers/AuctionWorkletsHandler.js +143 -89
- package/models/trace/handlers/AuctionWorkletsHandler.js.map +1 -7
- package/models/trace/handlers/FramesHandler.d.ts +76 -0
- package/models/trace/handlers/FramesHandler.js +424 -355
- package/models/trace/handlers/FramesHandler.js.map +1 -7
- package/models/trace/handlers/GPUHandler.d.ts +11 -0
- package/models/trace/handlers/GPUHandler.js +41 -37
- package/models/trace/handlers/GPUHandler.js.map +1 -7
- package/models/trace/handlers/InitiatorsHandler.d.ts +10 -0
- package/models/trace/handlers/InitiatorsHandler.js +164 -113
- package/models/trace/handlers/InitiatorsHandler.js.map +1 -7
- package/models/trace/handlers/InvalidationsHandler.d.ts +10 -0
- package/models/trace/handlers/InvalidationsHandler.js +101 -79
- package/models/trace/handlers/InvalidationsHandler.js.map +1 -7
- package/models/trace/handlers/LargestImagePaintHandler.d.ts +5 -0
- package/models/trace/handlers/LargestImagePaintHandler.js +32 -12
- package/models/trace/handlers/LargestImagePaintHandler.js.map +1 -7
- package/models/trace/handlers/LargestTextPaintHandler.d.ts +5 -0
- package/models/trace/handlers/LargestTextPaintHandler.js +20 -12
- package/models/trace/handlers/LargestTextPaintHandler.js.map +1 -7
- package/models/trace/handlers/LayerTreeHandler.d.ts +13 -0
- package/models/trace/handlers/LayerTreeHandler.js +96 -70
- package/models/trace/handlers/LayerTreeHandler.js.map +1 -7
- package/models/trace/handlers/LayoutShiftsHandler.d.ts +44 -0
- package/models/trace/handlers/LayoutShiftsHandler.js +304 -227
- package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -7
- package/models/trace/handlers/MemoryHandler.d.ts +7 -0
- package/models/trace/handlers/MemoryHandler.js +14 -11
- package/models/trace/handlers/MemoryHandler.js.map +1 -7
- package/models/trace/handlers/MetaHandler.d.ts +37 -0
- package/models/trace/handlers/MetaHandler.js +314 -226
- package/models/trace/handlers/MetaHandler.js.map +1 -7
- package/models/trace/handlers/ModelHandlers.d.ts +21 -0
- package/models/trace/handlers/ModelHandlers.js +25 -22
- package/models/trace/handlers/ModelHandlers.js.map +1 -7
- package/models/trace/handlers/NetworkRequestsHandler.d.ts +17 -0
- package/models/trace/handlers/NetworkRequestsHandler.js +342 -218
- package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -7
- package/models/trace/handlers/PageLoadMetricsHandler.d.ts +67 -0
- package/models/trace/handlers/PageLoadMetricsHandler.js +357 -284
- package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -7
- package/models/trace/handlers/RendererHandler.d.ts +101 -0
- package/models/trace/handlers/RendererHandler.js +295 -191
- package/models/trace/handlers/RendererHandler.js.map +1 -7
- package/models/trace/handlers/SamplesHandler.d.ts +46 -0
- package/models/trace/handlers/SamplesHandler.js +195 -158
- package/models/trace/handlers/SamplesHandler.js.map +1 -7
- package/models/trace/handlers/ScreenshotsHandler.d.ts +7 -0
- package/models/trace/handlers/ScreenshotsHandler.js +63 -41
- package/models/trace/handlers/ScreenshotsHandler.js.map +1 -7
- package/models/trace/handlers/Threads.d.ts +33 -0
- package/models/trace/handlers/Threads.js +85 -67
- package/models/trace/handlers/Threads.js.map +1 -7
- package/models/trace/handlers/UserInteractionsHandler.d.ts +57 -0
- package/models/trace/handlers/UserInteractionsHandler.js +240 -141
- package/models/trace/handlers/UserInteractionsHandler.js.map +1 -7
- package/models/trace/handlers/UserTimingsHandler.d.ts +28 -0
- package/models/trace/handlers/UserTimingsHandler.js +91 -80
- package/models/trace/handlers/UserTimingsHandler.js.map +1 -7
- package/models/trace/handlers/WarningsHandler.d.ts +14 -0
- package/models/trace/handlers/WarningsHandler.js +100 -62
- package/models/trace/handlers/WarningsHandler.js.map +1 -7
- package/models/trace/handlers/WorkersHandler.d.ts +11 -0
- package/models/trace/handlers/WorkersHandler.js +40 -38
- package/models/trace/handlers/WorkersHandler.js.map +1 -7
- package/models/trace/handlers/handlers.d.ts +3 -0
- package/models/trace/handlers/handlers.js +7 -4
- package/models/trace/handlers/handlers.js.map +1 -7
- package/models/trace/handlers/types.d.ts +45 -0
- package/models/trace/handlers/types.js +15 -15
- package/models/trace/handlers/types.js.map +1 -7
- package/models/trace/helpers/SamplesIntegrator.d.ts +49 -0
- package/models/trace/helpers/SamplesIntegrator.js +381 -204
- package/models/trace/helpers/SamplesIntegrator.js.map +1 -7
- package/models/trace/helpers/Timing.d.ts +26 -0
- package/models/trace/helpers/Timing.js +131 -110
- package/models/trace/helpers/Timing.js.map +1 -7
- package/models/trace/helpers/Trace.d.ts +37 -0
- package/models/trace/helpers/Trace.js +200 -166
- package/models/trace/helpers/Trace.js.map +1 -7
- package/models/trace/helpers/TreeHelpers.d.ts +90 -0
- package/models/trace/helpers/TreeHelpers.js +203 -100
- package/models/trace/helpers/TreeHelpers.js.map +1 -7
- package/models/trace/helpers/helpers.d.ts +4 -0
- package/models/trace/helpers/helpers.js +8 -5
- package/models/trace/helpers/helpers.js.map +1 -7
- package/models/trace/root-causes/LayoutShift.d.ts +119 -0
- package/models/trace/root-causes/LayoutShift.js +470 -323
- package/models/trace/root-causes/LayoutShift.js.map +1 -7
- package/models/trace/root-causes/RootCauses.d.ts +14 -0
- package/models/trace/root-causes/RootCauses.js +9 -6
- package/models/trace/root-causes/RootCauses.js.map +1 -7
- package/models/trace/root-causes/root-causes.d.ts +1 -0
- package/models/trace/root-causes/root-causes.js +5 -2
- package/models/trace/root-causes/root-causes.js.map +1 -7
- package/models/trace/trace.d.ts +11 -0
- package/models/trace/trace.js +17 -23
- package/models/trace/trace.js.map +1 -7
- package/models/trace/types/Configuration.d.ts +33 -0
- package/models/trace/types/Configuration.js +25 -14
- package/models/trace/types/Configuration.js.map +1 -7
- package/models/trace/types/File.d.ts +23 -0
- package/models/trace/types/File.js +5 -6
- package/models/trace/types/File.js.map +1 -7
- package/models/trace/types/Timing.d.ts +25 -0
- package/models/trace/types/Timing.js +10 -11
- package/models/trace/types/Timing.js.map +1 -7
- package/models/trace/types/TraceEvents.d.ts +1571 -0
- package/models/trace/types/TraceEvents.js +174 -381
- package/models/trace/types/TraceEvents.js.map +1 -7
- package/models/trace/types/types.d.ts +4 -0
- package/models/trace/types/types.js +8 -5
- package/models/trace/types/types.js.map +1 -7
- package/package.json +1 -1
- package/TracingManager.js +0 -0
- package/extras/extras.js +0 -0
- package/trace.mjs +0 -6980
- package/trace.mjs.map +0 -8
|
@@ -1,7 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../../../front_end/models/trace/extras/MainThreadActivity.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nconst IDLE_FUNCTION_CALL_NAMES = new Set([\n '(program)',\n '(idle)',\n '(root)',\n]);\n\nexport function calculateWindow(\n traceBounds: Types.Timing.TraceWindowMicroSeconds,\n mainThreadEntries: readonly Types.TraceEvents.SyntheticTraceEntry[]): Types.Timing.TraceWindowMicroSeconds {\n if (!mainThreadEntries.length) {\n return traceBounds;\n }\n const entriesWithIdleRemoved = mainThreadEntries.filter(entry => {\n if (Types.TraceEvents.isProfileCall(entry) &&\n (IDLE_FUNCTION_CALL_NAMES.has(entry.callFrame.functionName) || !entry.callFrame.functionName)) {\n return false;\n }\n return true;\n });\n\n if (entriesWithIdleRemoved.length === 0) {\n return traceBounds;\n }\n /**\n * Calculates regions of low utilization and returns the index of the event\n * that is the first event that should be included.\n **/\n function findLowUtilizationRegion(startIndex: number, stopIndex: number): number {\n const threshold = 0.1;\n\n let cutIndex = startIndex;\n const entryAtCut = entriesWithIdleRemoved[cutIndex];\n const timings = Helpers.Timing.eventTimingsMicroSeconds(entryAtCut);\n let cutTime = (timings.startTime + timings.endTime) / 2;\n let usedTime = 0;\n const step = Math.sign(stopIndex - startIndex);\n for (let i = startIndex; i !== stopIndex; i += step) {\n const task = entriesWithIdleRemoved[i];\n const taskTimings = Helpers.Timing.eventTimingsMicroSeconds(task);\n const taskTime = (taskTimings.startTime + taskTimings.endTime) / 2;\n const interval = Math.abs(cutTime - taskTime);\n if (usedTime < threshold * interval) {\n cutIndex = i;\n cutTime = taskTime;\n usedTime = 0;\n }\n usedTime += taskTimings.duration;\n }\n return cutIndex;\n }\n const rightIndex = findLowUtilizationRegion(entriesWithIdleRemoved.length - 1, 0);\n const leftIndex = findLowUtilizationRegion(0, rightIndex);\n const leftTimings = Helpers.Timing.eventTimingsMicroSeconds(entriesWithIdleRemoved[leftIndex]);\n const rightTimings = Helpers.Timing.eventTimingsMicroSeconds(entriesWithIdleRemoved[rightIndex]);\n\n let leftTime = leftTimings.startTime;\n let rightTime = rightTimings.endTime;\n const zoomedInSpan = rightTime - leftTime;\n\n if (zoomedInSpan < traceBounds.range * 0.1) {\n // If the area we have chosen to zoom into is less than 10% of the entire\n // span, we bail and show the entire trace. It would not be so useful to\n // the user to zoom in on such a small area; we assume they have\n // purposefully recorded a trace that contains empty periods of time.\n return traceBounds;\n }\n\n // Adjust the left time down by 5%, and the right time up by 5%, so that\n // we give the range we want to zoom a bit of breathing space. At the\n // same time, ensure that we do not stray beyond the bounds of the\n // min/max time of the entire trace.\n leftTime = Types.Timing.MicroSeconds(Math.max(leftTime - 0.05 * zoomedInSpan, traceBounds.min));\n rightTime = Types.Timing.MicroSeconds(Math.min(rightTime + 0.05 * zoomedInSpan, traceBounds.max));\n\n return {\n min: leftTime,\n max: rightTime,\n range: Types.Timing.MicroSeconds(rightTime - leftTime),\n };\n}\n"],
|
|
5
|
-
"mappings": "AAGA;AACA;AAEA,MAAM,2BAA2B,oBAAI,IAAI;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA;AAGK,gCACH,aACA,mBAA2G;AAC7G,MAAI,CAAC,kBAAkB,QAAQ;AAC7B,WAAO;AAAA;AAET,QAAM,yBAAyB,kBAAkB,OAAO,WAAS;AAC/D,QAAI,MAAM,YAAY,cAAc,UAC/B,0BAAyB,IAAI,MAAM,UAAU,iBAAiB,CAAC,MAAM,UAAU,eAAe;AACjG,aAAO;AAAA;AAET,WAAO;AAAA;AAGT,MAAI,uBAAuB,WAAW,GAAG;AACvC,WAAO;AAAA;AAMT,oCAAkC,YAAoB,WAA2B;AAC/E,UAAM,YAAY;AAElB,QAAI,WAAW;AACf,UAAM,aAAa,uBAAuB;AAC1C,UAAM,UAAU,QAAQ,OAAO,yBAAyB;AACxD,QAAI,UAAW,SAAQ,YAAY,QAAQ,WAAW;AACtD,QAAI,WAAW;AACf,UAAM,OAAO,KAAK,KAAK,YAAY;AACnC,aAAS,IAAI,YAAY,MAAM,WAAW,KAAK,MAAM;AACnD,YAAM,OAAO,uBAAuB;AACpC,YAAM,cAAc,QAAQ,OAAO,yBAAyB;AAC5D,YAAM,WAAY,aAAY,YAAY,YAAY,WAAW;AACjE,YAAM,WAAW,KAAK,IAAI,UAAU;AACpC,UAAI,WAAW,YAAY,UAAU;AACnC,mBAAW;AACX,kBAAU;AACV,mBAAW;AAAA;AAEb,kBAAY,YAAY;AAAA;AAE1B,WAAO;AAAA;AAET,QAAM,aAAa,yBAAyB,uBAAuB,SAAS,GAAG;AAC/E,QAAM,YAAY,yBAAyB,GAAG;AAC9C,QAAM,cAAc,QAAQ,OAAO,yBAAyB,uBAAuB;AACnF,QAAM,eAAe,QAAQ,OAAO,yBAAyB,uBAAuB;AAEpF,MAAI,WAAW,YAAY;AAC3B,MAAI,YAAY,aAAa;AAC7B,QAAM,eAAe,YAAY;AAEjC,MAAI,eAAe,YAAY,QAAQ,KAAK;AAK1C,WAAO;AAAA;AAOT,aAAW,MAAM,OAAO,aAAa,KAAK,IAAI,WAAW,OAAO,cAAc,YAAY;AAC1F,cAAY,MAAM,OAAO,aAAa,KAAK,IAAI,YAAY,OAAO,cAAc,YAAY;AAE5F,SAAO;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,OAAO,MAAM,OAAO,aAAa,YAAY;AAAA;AAAA;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
1
|
+
{"version":3,"file":"MainThreadActivity.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/MainThreadActivity.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nconst IDLE_FUNCTION_CALL_NAMES = new Set([\n '(program)',\n '(idle)',\n '(root)',\n]);\n\nexport function calculateWindow(\n traceBounds: Types.Timing.TraceWindowMicroSeconds,\n mainThreadEntries: readonly Types.TraceEvents.SyntheticTraceEntry[]): Types.Timing.TraceWindowMicroSeconds {\n if (!mainThreadEntries.length) {\n return traceBounds;\n }\n const entriesWithIdleRemoved = mainThreadEntries.filter(entry => {\n if (Types.TraceEvents.isProfileCall(entry) &&\n (IDLE_FUNCTION_CALL_NAMES.has(entry.callFrame.functionName) || !entry.callFrame.functionName)) {\n return false;\n }\n return true;\n });\n\n if (entriesWithIdleRemoved.length === 0) {\n return traceBounds;\n }\n /**\n * Calculates regions of low utilization and returns the index of the event\n * that is the first event that should be included.\n **/\n function findLowUtilizationRegion(startIndex: number, stopIndex: number): number {\n const threshold = 0.1;\n\n let cutIndex = startIndex;\n const entryAtCut = entriesWithIdleRemoved[cutIndex];\n const timings = Helpers.Timing.eventTimingsMicroSeconds(entryAtCut);\n let cutTime = (timings.startTime + timings.endTime) / 2;\n let usedTime = 0;\n const step = Math.sign(stopIndex - startIndex);\n for (let i = startIndex; i !== stopIndex; i += step) {\n const task = entriesWithIdleRemoved[i];\n const taskTimings = Helpers.Timing.eventTimingsMicroSeconds(task);\n const taskTime = (taskTimings.startTime + taskTimings.endTime) / 2;\n const interval = Math.abs(cutTime - taskTime);\n if (usedTime < threshold * interval) {\n cutIndex = i;\n cutTime = taskTime;\n usedTime = 0;\n }\n usedTime += taskTimings.duration;\n }\n return cutIndex;\n }\n const rightIndex = findLowUtilizationRegion(entriesWithIdleRemoved.length - 1, 0);\n const leftIndex = findLowUtilizationRegion(0, rightIndex);\n const leftTimings = Helpers.Timing.eventTimingsMicroSeconds(entriesWithIdleRemoved[leftIndex]);\n const rightTimings = Helpers.Timing.eventTimingsMicroSeconds(entriesWithIdleRemoved[rightIndex]);\n\n let leftTime = leftTimings.startTime;\n let rightTime = rightTimings.endTime;\n const zoomedInSpan = rightTime - leftTime;\n\n if (zoomedInSpan < traceBounds.range * 0.1) {\n // If the area we have chosen to zoom into is less than 10% of the entire\n // span, we bail and show the entire trace. It would not be so useful to\n // the user to zoom in on such a small area; we assume they have\n // purposefully recorded a trace that contains empty periods of time.\n return traceBounds;\n }\n\n // Adjust the left time down by 5%, and the right time up by 5%, so that\n // we give the range we want to zoom a bit of breathing space. At the\n // same time, ensure that we do not stray beyond the bounds of the\n // min/max time of the entire trace.\n leftTime = Types.Timing.MicroSeconds(Math.max(leftTime - 0.05 * zoomedInSpan, traceBounds.min));\n rightTime = Types.Timing.MicroSeconds(Math.min(rightTime + 0.05 * zoomedInSpan, traceBounds.max));\n\n return {\n min: leftTime,\n max: rightTime,\n range: Types.Timing.MicroSeconds(rightTime - leftTime),\n };\n}\n"]}
|
|
@@ -1,28 +1,44 @@
|
|
|
1
|
-
|
|
1
|
+
// Copyright 2023 The Chromium Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
import * as SDK from '../../../core/sdk/sdk.js';
|
|
2
5
|
export async function forNewRecording(recordStartTime) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
6
|
+
try {
|
|
7
|
+
const cpuThrottlingManager = SDK.CPUThrottlingManager.CPUThrottlingManager.instance();
|
|
8
|
+
// If the CPU Throttling manager has yet to have its primary page target
|
|
9
|
+
// set, it will block on the call to get the current hardware concurrency
|
|
10
|
+
// until it does. At this point where the user has recorded a trace, that
|
|
11
|
+
// target should have been set. So if it doesn't have it set, we instead
|
|
12
|
+
// just bail and don't store the hardware concurrency (this is only
|
|
13
|
+
// metadata, not mission critical information).
|
|
14
|
+
// We also race this call against a 1s timeout, because sometimes this call
|
|
15
|
+
// can hang (unsure exactly why) and we do not want to block parsing for
|
|
16
|
+
// too long as a result.
|
|
17
|
+
function getConcurrencyOrTimeout() {
|
|
18
|
+
return Promise.race([
|
|
19
|
+
SDK.CPUThrottlingManager.CPUThrottlingManager.instance().getHardwareConcurrency(),
|
|
20
|
+
new Promise(resolve => {
|
|
21
|
+
setTimeout(() => resolve(undefined), 1_000);
|
|
22
|
+
}),
|
|
23
|
+
]);
|
|
24
|
+
}
|
|
25
|
+
const hardwareConcurrency = cpuThrottlingManager.hasPrimaryPageTargetSet() ? await getConcurrencyOrTimeout() : undefined;
|
|
26
|
+
const cpuThrottling = SDK.CPUThrottlingManager.CPUThrottlingManager.instance().cpuThrottlingRate();
|
|
27
|
+
const networkConditions = SDK.NetworkManager.MultitargetNetworkManager.instance().networkConditions();
|
|
28
|
+
const networkTitle = typeof networkConditions.title === 'function' ? networkConditions.title() : networkConditions.title;
|
|
29
|
+
return {
|
|
30
|
+
source: 'DevTools',
|
|
31
|
+
startTime: recordStartTime ? new Date(recordStartTime).toJSON() : undefined,
|
|
32
|
+
cpuThrottling,
|
|
33
|
+
networkThrottling: networkTitle,
|
|
34
|
+
hardwareConcurrency,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// If anything went wrong, it does not really matter. The impact is that we
|
|
39
|
+
// will not save the metadata when we save the trace to disk, but that is
|
|
40
|
+
// not really important, so just return empty object and move on
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
27
43
|
}
|
|
28
|
-
//# sourceMappingURL=Metadata.js.map
|
|
44
|
+
//# sourceMappingURL=Metadata.js.map
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../../../front_end/models/trace/extras/Metadata.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as SDK from '../../../core/sdk/sdk.js';\nimport type * as Types from '../types/types.js';\n\nexport async function forNewRecording(recordStartTime?: number): Promise<Types.File.MetaData> {\n try {\n const cpuThrottlingManager = SDK.CPUThrottlingManager.CPUThrottlingManager.instance();\n\n // If the CPU Throttling manager has yet to have its primary page target\n // set, it will block on the call to get the current hardware concurrency\n // until it does. At this point where the user has recorded a trace, that\n // target should have been set. So if it doesn't have it set, we instead\n // just bail and don't store the hardware concurrency (this is only\n // metadata, not mission critical information).\n // We also race this call against a 1s timeout, because sometimes this call\n // can hang (unsure exactly why) and we do not want to block parsing for\n // too long as a result.\n function getConcurrencyOrTimeout(): Promise<number|undefined> {\n return Promise.race([\n SDK.CPUThrottlingManager.CPUThrottlingManager.instance().getHardwareConcurrency(),\n new Promise<undefined>(resolve => {\n setTimeout(() => resolve(undefined), 1_000);\n }),\n ]);\n }\n\n const hardwareConcurrency =\n cpuThrottlingManager.hasPrimaryPageTargetSet() ? await getConcurrencyOrTimeout() : undefined;\n const cpuThrottling = SDK.CPUThrottlingManager.CPUThrottlingManager.instance().cpuThrottlingRate();\n const networkConditions = SDK.NetworkManager.MultitargetNetworkManager.instance().networkConditions();\n const networkTitle =\n typeof networkConditions.title === 'function' ? networkConditions.title() : networkConditions.title;\n\n return {\n source: 'DevTools',\n startTime: recordStartTime ? new Date(recordStartTime).toJSON() : undefined, // ISO-8601 timestamp\n cpuThrottling,\n networkThrottling: networkTitle,\n hardwareConcurrency,\n };\n } catch {\n // If anything went wrong, it does not really matter. The impact is that we\n // will not save the metadata when we save the trace to disk, but that is\n // not really important, so just return empty object and move on\n return {};\n }\n}\n"],
|
|
5
|
-
"mappings": "AAIA;AAGA,sCAAsC,iBAAwD;AAC5F,MAAI;AAYF,QAAS,0BAAT,WAA8D;AAC5D,aAAO,QAAQ,KAAK;AAAA,QAClB,IAAI,qBAAqB,qBAAqB,WAAW;AAAA,QACzD,IAAI,QAAmB,aAAW;AAChC,qBAAW,MAAM,QAAQ,SAAY;AAAA;AAAA;AAAA;AAf3C,UAAM,uBAAuB,IAAI,qBAAqB,qBAAqB;AAoB3E,UAAM,sBACF,qBAAqB,4BAA4B,MAAM,4BAA4B;AACvF,UAAM,gBAAgB,IAAI,qBAAqB,qBAAqB,WAAW;AAC/E,UAAM,oBAAoB,IAAI,eAAe,0BAA0B,WAAW;AAClF,UAAM,eACF,OAAO,kBAAkB,UAAU,aAAa,kBAAkB,UAAU,kBAAkB;AAElG,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,WAAW,kBAAkB,IAAI,KAAK,iBAAiB,WAAW;AAAA,MAClE;AAAA,MACA,mBAAmB;AAAA,MACnB;AAAA;AAAA,UAEF;AAIA,WAAO;AAAA;AAAA;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
1
|
+
{"version":3,"file":"Metadata.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/Metadata.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAGhD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,eAAwB;IAC5D,IAAI;QACF,MAAM,oBAAoB,GAAG,GAAG,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,QAAQ,EAAE,CAAC;QAEtF,wEAAwE;QACxE,yEAAyE;QACzE,yEAAyE;QACzE,wEAAwE;QACxE,mEAAmE;QACnE,+CAA+C;QAC/C,2EAA2E;QAC3E,wEAAwE;QACxE,wBAAwB;QACxB,SAAS,uBAAuB;YAC9B,OAAO,OAAO,CAAC,IAAI,CAAC;gBAClB,GAAG,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,QAAQ,EAAE,CAAC,sBAAsB,EAAE;gBACjF,IAAI,OAAO,CAAY,OAAO,CAAC,EAAE;oBAC/B,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC;gBAC9C,CAAC,CAAC;aACH,CAAC,CAAC;QACL,CAAC;QAED,MAAM,mBAAmB,GACrB,oBAAoB,CAAC,uBAAuB,EAAE,CAAC,CAAC,CAAC,MAAM,uBAAuB,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACjG,MAAM,aAAa,GAAG,GAAG,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,QAAQ,EAAE,CAAC,iBAAiB,EAAE,CAAC;QACnG,MAAM,iBAAiB,GAAG,GAAG,CAAC,cAAc,CAAC,yBAAyB,CAAC,QAAQ,EAAE,CAAC,iBAAiB,EAAE,CAAC;QACtG,MAAM,YAAY,GACd,OAAO,iBAAiB,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC;QAExG,OAAO;YACL,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS;YAC3E,aAAa;YACb,iBAAiB,EAAE,YAAY;YAC/B,mBAAmB;SACpB,CAAC;KACH;IAAC,MAAM;QACN,2EAA2E;QAC3E,yEAAyE;QACzE,gEAAgE;QAChE,OAAO,EAAE,CAAC;KACX;AACH,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as SDK from '../../../core/sdk/sdk.js';\nimport type * as Types from '../types/types.js';\n\nexport async function forNewRecording(recordStartTime?: number): Promise<Types.File.MetaData> {\n try {\n const cpuThrottlingManager = SDK.CPUThrottlingManager.CPUThrottlingManager.instance();\n\n // If the CPU Throttling manager has yet to have its primary page target\n // set, it will block on the call to get the current hardware concurrency\n // until it does. At this point where the user has recorded a trace, that\n // target should have been set. So if it doesn't have it set, we instead\n // just bail and don't store the hardware concurrency (this is only\n // metadata, not mission critical information).\n // We also race this call against a 1s timeout, because sometimes this call\n // can hang (unsure exactly why) and we do not want to block parsing for\n // too long as a result.\n function getConcurrencyOrTimeout(): Promise<number|undefined> {\n return Promise.race([\n SDK.CPUThrottlingManager.CPUThrottlingManager.instance().getHardwareConcurrency(),\n new Promise<undefined>(resolve => {\n setTimeout(() => resolve(undefined), 1_000);\n }),\n ]);\n }\n\n const hardwareConcurrency =\n cpuThrottlingManager.hasPrimaryPageTargetSet() ? await getConcurrencyOrTimeout() : undefined;\n const cpuThrottling = SDK.CPUThrottlingManager.CPUThrottlingManager.instance().cpuThrottlingRate();\n const networkConditions = SDK.NetworkManager.MultitargetNetworkManager.instance().networkConditions();\n const networkTitle =\n typeof networkConditions.title === 'function' ? networkConditions.title() : networkConditions.title;\n\n return {\n source: 'DevTools',\n startTime: recordStartTime ? new Date(recordStartTime).toJSON() : undefined, // ISO-8601 timestamp\n cpuThrottling,\n networkThrottling: networkTitle,\n hardwareConcurrency,\n };\n } catch {\n // If anything went wrong, it does not really matter. The impact is that we\n // will not save the metadata when we save the trace to disk, but that is\n // not really important, so just return empty object and move on\n return {};\n }\n}\n"]}
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../../../front_end/models/trace/extras/extras.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nexport * as FetchNodes from './FetchNodes.js';\nexport * as FilmStrip from './FilmStrip.js';\nexport * as MainThreadActivity from './MainThreadActivity.js';\nexport * as Metadata from './Metadata.js';\n"],
|
|
5
|
-
"mappings": "AAIA;AACA;AACA;AACA;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
1
|
+
{"version":3,"file":"extras.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/extras.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,kBAAkB,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nexport * as FetchNodes from './FetchNodes.js';\nexport * as FilmStrip from './FilmStrip.js';\nexport * as MainThreadActivity from './MainThreadActivity.js';\nexport * as Metadata from './Metadata.js';\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as Types from '../types/types.js';
|
|
2
|
+
export interface AnimationData {
|
|
3
|
+
animations: readonly Types.TraceEvents.SyntheticAnimationPair[];
|
|
4
|
+
}
|
|
5
|
+
export declare function reset(): void;
|
|
6
|
+
export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void;
|
|
7
|
+
export declare function finalize(): Promise<void>;
|
|
8
|
+
export declare function data(): AnimationData;
|
|
@@ -1,30 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
// Copyright 2022 The Chromium Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
import * as Helpers from '../helpers/helpers.js';
|
|
5
|
+
import * as Types from '../types/types.js';
|
|
4
6
|
const animations = [];
|
|
5
7
|
const animationsSyntheticEvents = [];
|
|
6
|
-
let handlerState = HandlerState.UNINITIALIZED
|
|
8
|
+
let handlerState = 1 /* HandlerState.UNINITIALIZED */;
|
|
7
9
|
export function reset() {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
animations.length = 0;
|
|
11
|
+
animationsSyntheticEvents.length = 0;
|
|
10
12
|
}
|
|
11
13
|
export function handleEvent(event) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
if (Types.TraceEvents.isTraceEventAnimation(event)) {
|
|
15
|
+
animations.push(event);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
16
18
|
}
|
|
17
19
|
export async function finalize() {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
const syntheticEvents = Helpers.Trace.createMatchedSortedSyntheticEvents(animations);
|
|
21
|
+
animationsSyntheticEvents.push(...syntheticEvents);
|
|
22
|
+
handlerState = 3 /* HandlerState.FINALIZED */;
|
|
21
23
|
}
|
|
22
24
|
export function data() {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
if (handlerState !== 3 /* HandlerState.FINALIZED */) {
|
|
26
|
+
throw new Error('Animation handler is not finalized');
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
animations: Array.from(animationsSyntheticEvents),
|
|
30
|
+
};
|
|
29
31
|
}
|
|
30
|
-
//# sourceMappingURL=AnimationHandler.js.map
|
|
32
|
+
//# sourceMappingURL=AnimationHandler.js.map
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../../../front_end/models/trace/handlers/AnimationHandler.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\nconst animations: Types.TraceEvents.TraceEventAnimation[] = [];\nconst animationsSyntheticEvents: Types.TraceEvents.SyntheticAnimationPair[] = [];\n\nexport interface AnimationData {\n animations: readonly Types.TraceEvents.SyntheticAnimationPair[];\n}\nlet handlerState = HandlerState.UNINITIALIZED;\n\nexport function reset(): void {\n animations.length = 0;\n animationsSyntheticEvents.length = 0;\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventAnimation(event)) {\n animations.push(event);\n return;\n }\n}\n\nexport async function finalize(): Promise<void> {\n const syntheticEvents = Helpers.Trace.createMatchedSortedSyntheticEvents(animations);\n animationsSyntheticEvents.push(...syntheticEvents);\n handlerState = HandlerState.FINALIZED;\n}\n\nexport function data(): AnimationData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('Animation handler is not finalized');\n }\n\n return {\n animations: Array.from(animationsSyntheticEvents),\n };\n}\n"],
|
|
5
|
-
"mappings": "AAIA;AACA;AAEA;AAEA,MAAM,aAAsD;AAC5D,MAAM,4BAAwE;AAK9E,IAAI,eAAe,aAAa;AAEzB,wBAAuB;AAC5B,aAAW,SAAS;AACpB,4BAA0B,SAAS;AAAA;AAG9B,4BAAqB,OAA+C;AACzE,MAAI,MAAM,YAAY,sBAAsB,QAAQ;AAClD,eAAW,KAAK;AAChB;AAAA;AAAA;AAIJ,iCAAgD;AAC9C,QAAM,kBAAkB,QAAQ,MAAM,mCAAmC;AACzE,4BAA0B,KAAK,GAAG;AAClC,iBAAe,aAAa;AAAA;AAGvB,uBAA+B;AACpC,MAAI,iBAAiB,aAAa,WAAW;AAC3C,UAAM,IAAI,MAAM;AAAA;AAGlB,SAAO;AAAA,IACL,YAAY,MAAM,KAAK;AAAA;AAAA;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
1
|
+
{"version":3,"file":"AnimationHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/AnimationHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAI3C,MAAM,UAAU,GAA4C,EAAE,CAAC;AAC/D,MAAM,yBAAyB,GAA+C,EAAE,CAAC;AAKjF,IAAI,YAAY,qCAA6B,CAAC;AAE9C,MAAM,UAAU,KAAK;IACnB,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;IACtB,yBAAyB,CAAC,MAAM,GAAG,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAuC;IACjE,IAAI,KAAK,CAAC,WAAW,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE;QAClD,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,OAAO;KACR;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,UAAU,CAAC,CAAC;IACrF,yBAAyB,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC;IACnD,YAAY,iCAAyB,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,IAAI,YAAY,mCAA2B,EAAE;QAC3C,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;KACvD;IAED,OAAO;QACL,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC;KAClD,CAAC;AACJ,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\nconst animations: Types.TraceEvents.TraceEventAnimation[] = [];\nconst animationsSyntheticEvents: Types.TraceEvents.SyntheticAnimationPair[] = [];\n\nexport interface AnimationData {\n animations: readonly Types.TraceEvents.SyntheticAnimationPair[];\n}\nlet handlerState = HandlerState.UNINITIALIZED;\n\nexport function reset(): void {\n animations.length = 0;\n animationsSyntheticEvents.length = 0;\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventAnimation(event)) {\n animations.push(event);\n return;\n }\n}\n\nexport async function finalize(): Promise<void> {\n const syntheticEvents = Helpers.Trace.createMatchedSortedSyntheticEvents(animations);\n animationsSyntheticEvents.push(...syntheticEvents);\n handlerState = HandlerState.FINALIZED;\n}\n\nexport function data(): AnimationData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('Animation handler is not finalized');\n }\n\n return {\n animations: Array.from(animationsSyntheticEvents),\n };\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as Types from '../types/types.js';
|
|
2
|
+
export declare function reset(): void;
|
|
3
|
+
export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void;
|
|
4
|
+
export declare function finalize(): Promise<void>;
|
|
5
|
+
export interface AuctionWorkletsData {
|
|
6
|
+
worklets: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.SyntheticAuctionWorkletEvent>;
|
|
7
|
+
}
|
|
8
|
+
export declare function data(): AuctionWorkletsData;
|
|
@@ -1,106 +1,160 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
// Copyright 2023 The Chromium Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
import * as Types from '../types/types.js';
|
|
5
|
+
/**
|
|
6
|
+
* There are two metadata events that we care about.
|
|
7
|
+
* => AuctionWorkletRunningInProcess tells us which process the Auction Worklet
|
|
8
|
+
* has taken to run in.
|
|
9
|
+
* => AuctionWorkletDoneWithProcess tells us when the worklet is done with that
|
|
10
|
+
* process. This is less useful - but in the future we might want to surface
|
|
11
|
+
* this information so we still parse and return the event.
|
|
12
|
+
*
|
|
13
|
+
* It is important to note that the top level PID on these events is NOT the
|
|
14
|
+
* PID that the worklet is running on; instead we have to look at its
|
|
15
|
+
* args.data.pid property, which is the PID of the process that it is running
|
|
16
|
+
* on.
|
|
17
|
+
*
|
|
18
|
+
* For any given RunningInProcess event, we would typically expect to see a
|
|
19
|
+
* DoneWithProcess event, however this is not guaranteed, especially as users
|
|
20
|
+
* can record any chunk of time in DevTools.
|
|
21
|
+
*
|
|
22
|
+
* Similarly, it is also possible to see a DoneWithProcess event without a
|
|
23
|
+
* RunningInProcess event, if the user started recording after the auction
|
|
24
|
+
* worklets started. Therefore we are happy to create
|
|
25
|
+
* SyntheticAuctionWorkletEvents as long as we see just one of these events.
|
|
26
|
+
*
|
|
27
|
+
* If we do get two events and need to pair them, we can use the
|
|
28
|
+
* args.data.target property, which is a string ID shared by both
|
|
29
|
+
* events.
|
|
30
|
+
*/
|
|
31
|
+
const runningInProcessEvents = new Map();
|
|
32
|
+
const doneWithProcessEvents = new Map();
|
|
33
|
+
// Keyed by the PID defined in `args.data.pid` on AuctionWorklet trace events..
|
|
34
|
+
const createdSyntheticEvents = new Map();
|
|
35
|
+
// Each AuctonWorklet takes over a process and has 2 threads (that we care
|
|
36
|
+
// about and want to show as tracks):
|
|
37
|
+
// 1. A CrUtilityMain thread which is known as the "control process".
|
|
38
|
+
// 2. A AuctionV8HelperThread which is the actual auction worklet and will be
|
|
39
|
+
// either a "Seller" or a "Bidder"
|
|
40
|
+
// To detect these we look for the metadata thread_name events. We key these by
|
|
41
|
+
// PID so that we can easily look them up later without having to loop through.
|
|
42
|
+
const utilityThreads = new Map();
|
|
43
|
+
const v8HelperThreads = new Map();
|
|
7
44
|
export function reset() {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
45
|
+
runningInProcessEvents.clear();
|
|
46
|
+
doneWithProcessEvents.clear();
|
|
47
|
+
createdSyntheticEvents.clear();
|
|
48
|
+
utilityThreads.clear();
|
|
49
|
+
v8HelperThreads.clear();
|
|
13
50
|
}
|
|
14
51
|
export function handleEvent(event) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
if (Types.TraceEvents.isTraceEventAuctionWorkletDoneWithProcess(event)) {
|
|
20
|
-
doneWithProcessEvents.set(event.args.data.pid, event);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
if (Types.TraceEvents.isThreadName(event)) {
|
|
24
|
-
if (event.args.name === "auction_worklet.CrUtilityMain") {
|
|
25
|
-
utilityThreads.set(event.pid, event);
|
|
26
|
-
return;
|
|
52
|
+
if (Types.TraceEvents.isTraceEventAuctionWorkletRunningInProcess(event)) {
|
|
53
|
+
runningInProcessEvents.set(event.args.data.pid, event);
|
|
54
|
+
return;
|
|
27
55
|
}
|
|
28
|
-
if (
|
|
29
|
-
|
|
56
|
+
if (Types.TraceEvents.isTraceEventAuctionWorkletDoneWithProcess(event)) {
|
|
57
|
+
doneWithProcessEvents.set(event.args.data.pid, event);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (Types.TraceEvents.isThreadName(event)) {
|
|
61
|
+
if (event.args.name === 'auction_worklet.CrUtilityMain') {
|
|
62
|
+
utilityThreads.set(event.pid, event);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (event.args.name === 'AuctionV8HelperThread') {
|
|
66
|
+
v8HelperThreads.set(event.pid, event);
|
|
67
|
+
}
|
|
30
68
|
}
|
|
31
|
-
}
|
|
32
69
|
}
|
|
33
70
|
function workletType(input) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
71
|
+
switch (input) {
|
|
72
|
+
case 'seller':
|
|
73
|
+
return "seller" /* Types.TraceEvents.AuctionWorkletType.SELLER */;
|
|
74
|
+
case 'bidder':
|
|
75
|
+
return "bidder" /* Types.TraceEvents.AuctionWorkletType.BIDDER */;
|
|
76
|
+
default:
|
|
77
|
+
return "unknown" /* Types.TraceEvents.AuctionWorkletType.UNKNOWN */;
|
|
78
|
+
}
|
|
42
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* We cannot make the full event without knowing the type of event, but we can
|
|
82
|
+
* create everything other than the `args` field, as those are identical
|
|
83
|
+
* regardless of the type of event.
|
|
84
|
+
*/
|
|
43
85
|
function makeSyntheticEventBase(event) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
86
|
+
return {
|
|
87
|
+
name: 'SyntheticAuctionWorkletEvent',
|
|
88
|
+
s: "t" /* Types.TraceEvents.TraceEventScope.THREAD */,
|
|
89
|
+
cat: event.cat,
|
|
90
|
+
tid: event.tid,
|
|
91
|
+
ts: event.ts,
|
|
92
|
+
ph: "I" /* Types.TraceEvents.Phase.INSTANT */,
|
|
93
|
+
pid: event.args.data.pid,
|
|
94
|
+
host: event.args.data.host,
|
|
95
|
+
target: event.args.data.target,
|
|
96
|
+
type: workletType(event.args.data.type),
|
|
97
|
+
};
|
|
56
98
|
}
|
|
57
99
|
export async function finalize() {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (runningEvent) {
|
|
67
|
-
syntheticEvent = {
|
|
68
|
-
...makeSyntheticEventBase(runningEvent),
|
|
69
|
-
args: {
|
|
70
|
-
data: {
|
|
71
|
-
runningInProcessEvent: runningEvent,
|
|
72
|
-
utilityThread: utilityThreadNameEvent,
|
|
73
|
-
v8HelperThread: v8HelperEvent
|
|
74
|
-
}
|
|
100
|
+
// Loop through the utility threads we found to create the worklet events. We
|
|
101
|
+
// expect each worklet to have a utility thread, so we can use them as the
|
|
102
|
+
// root of our list of worklets.
|
|
103
|
+
for (const [pid, utilityThreadNameEvent] of utilityThreads) {
|
|
104
|
+
const v8HelperEvent = v8HelperThreads.get(pid);
|
|
105
|
+
if (!v8HelperEvent) {
|
|
106
|
+
// Bad trace data - AuctionWorklets are expected to always have both threads.
|
|
107
|
+
continue;
|
|
75
108
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
109
|
+
const runningEvent = runningInProcessEvents.get(pid);
|
|
110
|
+
const doneWithEvent = doneWithProcessEvents.get(pid);
|
|
111
|
+
// We can create a worklet from either the runningEvent or doneWithEvent -
|
|
112
|
+
// we do not need both. We cannot express that to TypeScript with an early
|
|
113
|
+
// return here, so instead we set the event initially to null, and then
|
|
114
|
+
// create it from either the running event or the doneWith event. If it is
|
|
115
|
+
// still null after this, that means neither event was found, and we drop
|
|
116
|
+
// the worklet as we do not have enough information to create the synthetic
|
|
117
|
+
// event.
|
|
118
|
+
let syntheticEvent = null;
|
|
119
|
+
if (runningEvent) {
|
|
120
|
+
syntheticEvent = {
|
|
121
|
+
...makeSyntheticEventBase(runningEvent),
|
|
122
|
+
args: {
|
|
123
|
+
data: {
|
|
124
|
+
runningInProcessEvent: runningEvent,
|
|
125
|
+
utilityThread: utilityThreadNameEvent,
|
|
126
|
+
v8HelperThread: v8HelperEvent,
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
if (doneWithEvent) {
|
|
131
|
+
syntheticEvent.args.data.doneWithProcessEvent = doneWithEvent;
|
|
132
|
+
}
|
|
89
133
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
134
|
+
else if (doneWithEvent) {
|
|
135
|
+
syntheticEvent = {
|
|
136
|
+
...makeSyntheticEventBase(doneWithEvent),
|
|
137
|
+
args: {
|
|
138
|
+
data: {
|
|
139
|
+
doneWithProcessEvent: doneWithEvent,
|
|
140
|
+
utilityThread: utilityThreadNameEvent,
|
|
141
|
+
v8HelperThread: v8HelperEvent,
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
if (runningEvent) {
|
|
146
|
+
syntheticEvent.args.data.runningInProcessEvent = runningEvent;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (syntheticEvent === null) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
createdSyntheticEvents.set(pid, syntheticEvent);
|
|
97
153
|
}
|
|
98
|
-
createdSyntheticEvents.set(pid, syntheticEvent);
|
|
99
|
-
}
|
|
100
154
|
}
|
|
101
155
|
export function data() {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
156
|
+
return {
|
|
157
|
+
worklets: new Map(createdSyntheticEvents),
|
|
158
|
+
};
|
|
105
159
|
}
|
|
106
|
-
//# sourceMappingURL=AuctionWorkletsHandler.js.map
|
|
160
|
+
//# sourceMappingURL=AuctionWorkletsHandler.js.map
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../../../front_end/models/trace/handlers/AuctionWorkletsHandler.ts"],
|
|
4
|
-
"sourcesContent": ["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\n/**\n * There are two metadata events that we care about.\n * => AuctionWorkletRunningInProcess tells us which process the Auction Worklet\n * has taken to run in.\n * => AuctionWorkletDoneWithProcess tells us when the worklet is done with that\n * process. This is less useful - but in the future we might want to surface\n * this information so we still parse and return the event.\n *\n * It is important to note that the top level PID on these events is NOT the\n * PID that the worklet is running on; instead we have to look at its\n * args.data.pid property, which is the PID of the process that it is running\n * on.\n *\n * For any given RunningInProcess event, we would typically expect to see a\n * DoneWithProcess event, however this is not guaranteed, especially as users\n * can record any chunk of time in DevTools.\n *\n * Similarly, it is also possible to see a DoneWithProcess event without a\n * RunningInProcess event, if the user started recording after the auction\n * worklets started. Therefore we are happy to create\n * SyntheticAuctionWorkletEvents as long as we see just one of these events.\n *\n * If we do get two events and need to pair them, we can use the\n * args.data.target property, which is a string ID shared by both\n * events.\n */\nconst runningInProcessEvents:\n Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventAuctionWorkletRunningInProcess> = new Map();\nconst doneWithProcessEvents:\n Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventAuctionWorkletDoneWithProcess> = new Map();\n\n// Keyed by the PID defined in `args.data.pid` on AuctionWorklet trace events..\nconst createdSyntheticEvents: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.SyntheticAuctionWorkletEvent> =\n new Map();\n\n// Each AuctonWorklet takes over a process and has 2 threads (that we care\n// about and want to show as tracks):\n// 1. A CrUtilityMain thread which is known as the \"control process\".\n// 2. A AuctionV8HelperThread which is the actual auction worklet and will be\n// either a \"Seller\" or a \"Bidder\"\n// To detect these we look for the metadata thread_name events. We key these by\n// PID so that we can easily look them up later without having to loop through.\nconst utilityThreads: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventThreadName> = new Map();\nconst v8HelperThreads: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventThreadName> = new Map();\n\nexport function reset(): void {\n runningInProcessEvents.clear();\n doneWithProcessEvents.clear();\n createdSyntheticEvents.clear();\n utilityThreads.clear();\n v8HelperThreads.clear();\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventAuctionWorkletRunningInProcess(event)) {\n runningInProcessEvents.set(event.args.data.pid, event);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventAuctionWorkletDoneWithProcess(event)) {\n doneWithProcessEvents.set(event.args.data.pid, event);\n return;\n }\n\n if (Types.TraceEvents.isThreadName(event)) {\n if (event.args.name === 'auction_worklet.CrUtilityMain') {\n utilityThreads.set(event.pid, event);\n return;\n }\n if (event.args.name === 'AuctionV8HelperThread') {\n v8HelperThreads.set(event.pid, event);\n }\n }\n}\n\nfunction workletType(input: string): Types.TraceEvents.AuctionWorkletType {\n switch (input) {\n case 'seller':\n return Types.TraceEvents.AuctionWorkletType.SELLER;\n case 'bidder':\n return Types.TraceEvents.AuctionWorkletType.BIDDER;\n default:\n return Types.TraceEvents.AuctionWorkletType.UNKNOWN;\n }\n}\n\n/**\n * We cannot make the full event without knowing the type of event, but we can\n * create everything other than the `args` field, as those are identical\n * regardless of the type of event.\n */\nfunction makeSyntheticEventBase(event: Types.TraceEvents.TraceEventAuctionWorkletDoneWithProcess|\n Types.TraceEvents.TraceEventAuctionWorkletRunningInProcess):\n Omit<Types.TraceEvents.SyntheticAuctionWorkletEvent, 'args'> {\n return {\n name: 'SyntheticAuctionWorkletEvent',\n s: Types.TraceEvents.TraceEventScope.THREAD,\n cat: event.cat,\n tid: event.tid,\n ts: event.ts,\n ph: Types.TraceEvents.Phase.INSTANT,\n pid: event.args.data.pid,\n host: event.args.data.host,\n target: event.args.data.target,\n type: workletType(event.args.data.type),\n };\n}\n\nexport async function finalize(): Promise<void> {\n // Loop through the utility threads we found to create the worklet events. We\n // expect each worklet to have a utility thread, so we can use them as the\n // root of our list of worklets.\n for (const [pid, utilityThreadNameEvent] of utilityThreads) {\n const v8HelperEvent = v8HelperThreads.get(pid);\n if (!v8HelperEvent) {\n // Bad trace data - AuctionWorklets are expected to always have both threads.\n continue;\n }\n\n const runningEvent = runningInProcessEvents.get(pid);\n const doneWithEvent = doneWithProcessEvents.get(pid);\n\n // We can create a worklet from either the runningEvent or doneWithEvent -\n // we do not need both. We cannot express that to TypeScript with an early\n // return here, so instead we set the event initially to null, and then\n // create it from either the running event or the doneWith event. If it is\n // still null after this, that means neither event was found, and we drop\n // the worklet as we do not have enough information to create the synthetic\n // event.\n\n let syntheticEvent: Types.TraceEvents.SyntheticAuctionWorkletEvent|null = null;\n\n if (runningEvent) {\n syntheticEvent = {\n ...makeSyntheticEventBase(runningEvent),\n args: {\n data: {\n runningInProcessEvent: runningEvent,\n utilityThread: utilityThreadNameEvent,\n v8HelperThread: v8HelperEvent,\n },\n },\n };\n if (doneWithEvent) {\n syntheticEvent.args.data.doneWithProcessEvent = doneWithEvent;\n }\n } else if (doneWithEvent) {\n syntheticEvent = {\n ...makeSyntheticEventBase(doneWithEvent),\n args: {\n data: {\n doneWithProcessEvent: doneWithEvent,\n utilityThread: utilityThreadNameEvent,\n v8HelperThread: v8HelperEvent,\n },\n },\n };\n if (runningEvent) {\n syntheticEvent.args.data.runningInProcessEvent = runningEvent;\n }\n }\n if (syntheticEvent === null) {\n continue;\n }\n createdSyntheticEvents.set(pid, syntheticEvent);\n }\n}\n\nexport interface AuctionWorkletsData {\n worklets: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.SyntheticAuctionWorkletEvent>;\n}\n\nexport function data(): AuctionWorkletsData {\n return {\n worklets: new Map(createdSyntheticEvents),\n };\n}\n"],
|
|
5
|
-
"mappings": "AAIA;AA4BA,MAAM,yBAC6F,oBAAI;AACvG,MAAM,wBAC4F,oBAAI;AAGtG,MAAM,yBACF,oBAAI;AASR,MAAM,iBAA2F,oBAAI;AACrG,MAAM,kBAA4F,oBAAI;AAE/F,wBAAuB;AAC5B,yBAAuB;AACvB,wBAAsB;AACtB,yBAAuB;AACvB,iBAAe;AACf,kBAAgB;AAAA;AAGX,4BAAqB,OAA+C;AACzE,MAAI,MAAM,YAAY,2CAA2C,QAAQ;AACvE,2BAAuB,IAAI,MAAM,KAAK,KAAK,KAAK;AAChD;AAAA;AAGF,MAAI,MAAM,YAAY,0CAA0C,QAAQ;AACtE,0BAAsB,IAAI,MAAM,KAAK,KAAK,KAAK;AAC/C;AAAA;AAGF,MAAI,MAAM,YAAY,aAAa,QAAQ;AACzC,QAAI,MAAM,KAAK,SAAS,iCAAiC;AACvD,qBAAe,IAAI,MAAM,KAAK;AAC9B;AAAA;AAEF,QAAI,MAAM,KAAK,SAAS,yBAAyB;AAC/C,sBAAgB,IAAI,MAAM,KAAK;AAAA;AAAA;AAAA;AAKrC,qBAAqB,OAAqD;AACxE,UAAQ;AAAA,SACD;AACH,aAAO,MAAM,YAAY,mBAAmB;AAAA,SACzC;AACH,aAAO,MAAM,YAAY,mBAAmB;AAAA;AAE5C,aAAO,MAAM,YAAY,mBAAmB;AAAA;AAAA;AASlD,gCAAgC,OAEiC;AAC/D,SAAO;AAAA,IACL,MAAM;AAAA,IACN,GAAG,MAAM,YAAY,gBAAgB;AAAA,IACrC,KAAK,MAAM;AAAA,IACX,KAAK,MAAM;AAAA,IACX,IAAI,MAAM;AAAA,IACV,IAAI,MAAM,YAAY,MAAM;AAAA,IAC5B,KAAK,MAAM,KAAK,KAAK;AAAA,IACrB,MAAM,MAAM,KAAK,KAAK;AAAA,IACtB,QAAQ,MAAM,KAAK,KAAK;AAAA,IACxB,MAAM,YAAY,MAAM,KAAK,KAAK;AAAA;AAAA;AAItC,iCAAgD;AAI9C,aAAW,CAAC,KAAK,2BAA2B,gBAAgB;AAC1D,UAAM,gBAAgB,gBAAgB,IAAI;AAC1C,QAAI,CAAC,eAAe;AAElB;AAAA;AAGF,UAAM,eAAe,uBAAuB,IAAI;AAChD,UAAM,gBAAgB,sBAAsB,IAAI;AAUhD,QAAI,iBAAsE;AAE1E,QAAI,cAAc;AAChB,uBAAiB;AAAA,WACZ,uBAAuB;AAAA,QAC1B,MAAM;AAAA,UACJ,MAAM;AAAA,YACJ,uBAAuB;AAAA,YACvB,eAAe;AAAA,YACf,gBAAgB;AAAA;AAAA;AAAA;AAItB,UAAI,eAAe;AACjB,uBAAe,KAAK,KAAK,uBAAuB;AAAA;AAAA,eAEzC,eAAe;AACxB,uBAAiB;AAAA,WACZ,uBAAuB;AAAA,QAC1B,MAAM;AAAA,UACJ,MAAM;AAAA,YACJ,sBAAsB;AAAA,YACtB,eAAe;AAAA,YACf,gBAAgB;AAAA;AAAA;AAAA;AAItB,UAAI,cAAc;AAChB,uBAAe,KAAK,KAAK,wBAAwB;AAAA;AAAA;AAGrD,QAAI,mBAAmB,MAAM;AAC3B;AAAA;AAEF,2BAAuB,IAAI,KAAK;AAAA;AAAA;AAQ7B,uBAAqC;AAC1C,SAAO;AAAA,IACL,UAAU,IAAI,IAAI;AAAA;AAAA;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
1
|
+
{"version":3,"file":"AuctionWorkletsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/AuctionWorkletsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\n/**\n * There are two metadata events that we care about.\n * => AuctionWorkletRunningInProcess tells us which process the Auction Worklet\n * has taken to run in.\n * => AuctionWorkletDoneWithProcess tells us when the worklet is done with that\n * process. This is less useful - but in the future we might want to surface\n * this information so we still parse and return the event.\n *\n * It is important to note that the top level PID on these events is NOT the\n * PID that the worklet is running on; instead we have to look at its\n * args.data.pid property, which is the PID of the process that it is running\n * on.\n *\n * For any given RunningInProcess event, we would typically expect to see a\n * DoneWithProcess event, however this is not guaranteed, especially as users\n * can record any chunk of time in DevTools.\n *\n * Similarly, it is also possible to see a DoneWithProcess event without a\n * RunningInProcess event, if the user started recording after the auction\n * worklets started. Therefore we are happy to create\n * SyntheticAuctionWorkletEvents as long as we see just one of these events.\n *\n * If we do get two events and need to pair them, we can use the\n * args.data.target property, which is a string ID shared by both\n * events.\n */\nconst runningInProcessEvents:\n Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventAuctionWorkletRunningInProcess> = new Map();\nconst doneWithProcessEvents:\n Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventAuctionWorkletDoneWithProcess> = new Map();\n\n// Keyed by the PID defined in `args.data.pid` on AuctionWorklet trace events..\nconst createdSyntheticEvents: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.SyntheticAuctionWorkletEvent> =\n new Map();\n\n// Each AuctonWorklet takes over a process and has 2 threads (that we care\n// about and want to show as tracks):\n// 1. A CrUtilityMain thread which is known as the \"control process\".\n// 2. A AuctionV8HelperThread which is the actual auction worklet and will be\n// either a \"Seller\" or a \"Bidder\"\n// To detect these we look for the metadata thread_name events. We key these by\n// PID so that we can easily look them up later without having to loop through.\nconst utilityThreads: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventThreadName> = new Map();\nconst v8HelperThreads: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventThreadName> = new Map();\n\nexport function reset(): void {\n runningInProcessEvents.clear();\n doneWithProcessEvents.clear();\n createdSyntheticEvents.clear();\n utilityThreads.clear();\n v8HelperThreads.clear();\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventAuctionWorkletRunningInProcess(event)) {\n runningInProcessEvents.set(event.args.data.pid, event);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventAuctionWorkletDoneWithProcess(event)) {\n doneWithProcessEvents.set(event.args.data.pid, event);\n return;\n }\n\n if (Types.TraceEvents.isThreadName(event)) {\n if (event.args.name === 'auction_worklet.CrUtilityMain') {\n utilityThreads.set(event.pid, event);\n return;\n }\n if (event.args.name === 'AuctionV8HelperThread') {\n v8HelperThreads.set(event.pid, event);\n }\n }\n}\n\nfunction workletType(input: string): Types.TraceEvents.AuctionWorkletType {\n switch (input) {\n case 'seller':\n return Types.TraceEvents.AuctionWorkletType.SELLER;\n case 'bidder':\n return Types.TraceEvents.AuctionWorkletType.BIDDER;\n default:\n return Types.TraceEvents.AuctionWorkletType.UNKNOWN;\n }\n}\n\n/**\n * We cannot make the full event without knowing the type of event, but we can\n * create everything other than the `args` field, as those are identical\n * regardless of the type of event.\n */\nfunction makeSyntheticEventBase(event: Types.TraceEvents.TraceEventAuctionWorkletDoneWithProcess|\n Types.TraceEvents.TraceEventAuctionWorkletRunningInProcess):\n Omit<Types.TraceEvents.SyntheticAuctionWorkletEvent, 'args'> {\n return {\n name: 'SyntheticAuctionWorkletEvent',\n s: Types.TraceEvents.TraceEventScope.THREAD,\n cat: event.cat,\n tid: event.tid,\n ts: event.ts,\n ph: Types.TraceEvents.Phase.INSTANT,\n pid: event.args.data.pid,\n host: event.args.data.host,\n target: event.args.data.target,\n type: workletType(event.args.data.type),\n };\n}\n\nexport async function finalize(): Promise<void> {\n // Loop through the utility threads we found to create the worklet events. We\n // expect each worklet to have a utility thread, so we can use them as the\n // root of our list of worklets.\n for (const [pid, utilityThreadNameEvent] of utilityThreads) {\n const v8HelperEvent = v8HelperThreads.get(pid);\n if (!v8HelperEvent) {\n // Bad trace data - AuctionWorklets are expected to always have both threads.\n continue;\n }\n\n const runningEvent = runningInProcessEvents.get(pid);\n const doneWithEvent = doneWithProcessEvents.get(pid);\n\n // We can create a worklet from either the runningEvent or doneWithEvent -\n // we do not need both. We cannot express that to TypeScript with an early\n // return here, so instead we set the event initially to null, and then\n // create it from either the running event or the doneWith event. If it is\n // still null after this, that means neither event was found, and we drop\n // the worklet as we do not have enough information to create the synthetic\n // event.\n\n let syntheticEvent: Types.TraceEvents.SyntheticAuctionWorkletEvent|null = null;\n\n if (runningEvent) {\n syntheticEvent = {\n ...makeSyntheticEventBase(runningEvent),\n args: {\n data: {\n runningInProcessEvent: runningEvent,\n utilityThread: utilityThreadNameEvent,\n v8HelperThread: v8HelperEvent,\n },\n },\n };\n if (doneWithEvent) {\n syntheticEvent.args.data.doneWithProcessEvent = doneWithEvent;\n }\n } else if (doneWithEvent) {\n syntheticEvent = {\n ...makeSyntheticEventBase(doneWithEvent),\n args: {\n data: {\n doneWithProcessEvent: doneWithEvent,\n utilityThread: utilityThreadNameEvent,\n v8HelperThread: v8HelperEvent,\n },\n },\n };\n if (runningEvent) {\n syntheticEvent.args.data.runningInProcessEvent = runningEvent;\n }\n }\n if (syntheticEvent === null) {\n continue;\n }\n createdSyntheticEvents.set(pid, syntheticEvent);\n }\n}\n\nexport interface AuctionWorkletsData {\n worklets: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.SyntheticAuctionWorkletEvent>;\n}\n\nexport function data(): AuctionWorkletsData {\n return {\n worklets: new Map(createdSyntheticEvents),\n };\n}\n"]}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import * as Types from '../types/types.js';
|
|
2
|
+
import { type AuctionWorkletsData } from './AuctionWorkletsHandler.js';
|
|
3
|
+
import { type LayerTreeData } from './LayerTreeHandler.js';
|
|
4
|
+
import { type MetaHandlerData } from './MetaHandler.js';
|
|
5
|
+
import { type RendererHandlerData } from './RendererHandler.js';
|
|
6
|
+
import { type TraceEventHandlerName } from './types.js';
|
|
7
|
+
export declare function reset(): void;
|
|
8
|
+
export declare function initialize(): void;
|
|
9
|
+
export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void;
|
|
10
|
+
export declare function finalize(): Promise<void>;
|
|
11
|
+
export interface FramesData {
|
|
12
|
+
frames: readonly TimelineFrame[];
|
|
13
|
+
framesById: Readonly<Record<number, TimelineFrame | undefined>>;
|
|
14
|
+
}
|
|
15
|
+
export declare function data(): FramesData;
|
|
16
|
+
export declare function deps(): TraceEventHandlerName[];
|
|
17
|
+
export declare class TimelineFrameModel {
|
|
18
|
+
#private;
|
|
19
|
+
constructor(allEvents: readonly Types.TraceEvents.TraceEventData[], rendererData: RendererHandlerData, auctionWorkletsData: AuctionWorkletsData, metaData: MetaHandlerData, layerTreeData: LayerTreeData);
|
|
20
|
+
framesById(): Readonly<Record<number, TimelineFrame | undefined>>;
|
|
21
|
+
frames(): TimelineFrame[];
|
|
22
|
+
}
|
|
23
|
+
export interface FrameLayerTreeData {
|
|
24
|
+
entry: Types.TraceEvents.TraceEventLayerTreeHostImplSnapshot;
|
|
25
|
+
paints: LayerPaintEvent[];
|
|
26
|
+
}
|
|
27
|
+
export declare class TimelineFrame {
|
|
28
|
+
startTime: Types.Timing.MicroSeconds;
|
|
29
|
+
startTimeOffset: Types.Timing.MicroSeconds;
|
|
30
|
+
endTime: Types.Timing.MicroSeconds;
|
|
31
|
+
duration: Types.Timing.MicroSeconds;
|
|
32
|
+
idle: boolean;
|
|
33
|
+
dropped: boolean;
|
|
34
|
+
isPartial: boolean;
|
|
35
|
+
layerTree: FrameLayerTreeData | null;
|
|
36
|
+
paints: LayerPaintEvent[];
|
|
37
|
+
mainFrameId: number | undefined;
|
|
38
|
+
readonly seqId: number;
|
|
39
|
+
constructor(seqId: number, startTime: Types.Timing.MicroSeconds, startTimeOffset: Types.Timing.MicroSeconds);
|
|
40
|
+
setEndTime(endTime: Types.Timing.MicroSeconds): void;
|
|
41
|
+
setLayerTree(layerTree: FrameLayerTreeData | null): void;
|
|
42
|
+
}
|
|
43
|
+
export interface LayerPaintEventPicture {
|
|
44
|
+
rect: Array<number>;
|
|
45
|
+
serializedPicture: string;
|
|
46
|
+
}
|
|
47
|
+
export declare class LayerPaintEvent {
|
|
48
|
+
#private;
|
|
49
|
+
constructor(event: Types.TraceEvents.TraceEventPaint, snapshot: Types.TraceEvents.TraceEventDisplayItemListSnapshot);
|
|
50
|
+
layerId(): number;
|
|
51
|
+
event(): Types.TraceEvents.TraceEventPaint;
|
|
52
|
+
picture(): LayerPaintEventPicture | null;
|
|
53
|
+
}
|
|
54
|
+
export declare class PendingFrame {
|
|
55
|
+
paints: LayerPaintEvent[];
|
|
56
|
+
mainFrameId: number | undefined;
|
|
57
|
+
triggerTime: number;
|
|
58
|
+
constructor(triggerTime: number);
|
|
59
|
+
}
|
|
60
|
+
declare class BeginFrameInfo {
|
|
61
|
+
seqId: number;
|
|
62
|
+
startTime: Types.Timing.MicroSeconds;
|
|
63
|
+
isDropped: boolean;
|
|
64
|
+
isPartial: boolean;
|
|
65
|
+
constructor(seqId: number, startTime: Types.Timing.MicroSeconds, isDropped: boolean, isPartial: boolean);
|
|
66
|
+
}
|
|
67
|
+
export declare class TimelineFrameBeginFrameQueue {
|
|
68
|
+
private queueFrames;
|
|
69
|
+
private mapFrames;
|
|
70
|
+
addFrameIfNotExists(seqId: number, startTime: Types.Timing.MicroSeconds, isDropped: boolean, isPartial: boolean): void;
|
|
71
|
+
setDropped(seqId: number, isDropped: boolean): void;
|
|
72
|
+
setPartial(seqId: number, isPartial: boolean): void;
|
|
73
|
+
processPendingBeginFramesOnDrawFrame(seqId: number): BeginFrameInfo[];
|
|
74
|
+
}
|
|
75
|
+
export declare function framesWithinWindow(frames: readonly TimelineFrame[], startTime: Types.Timing.MicroSeconds, endTime: Types.Timing.MicroSeconds): TimelineFrame[];
|
|
76
|
+
export {};
|