Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 1 | // Copyright 2016 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 | |
Tim van der Lippe | 01e1c46 | 2021-04-19 15:04:03 | [diff] [blame] | 5 | import * as Common from '../../core/common/common.js'; |
| 6 | import * as i18n from '../../core/i18n/i18n.js'; |
| 7 | import * as Platform from '../../core/platform/platform.js'; |
| 8 | import * as Root from '../../core/root/root.js'; |
| 9 | import * as SDK from '../../core/sdk/sdk.js'; |
Tim van der Lippe | 01e1c46 | 2021-04-19 15:04:03 | [diff] [blame] | 10 | import * as TimelineModel from '../../models/timeline_model/timeline_model.js'; |
Jack Franklin | 0b4f963 | 2023-03-03 15:40:41 | [diff] [blame] | 11 | import * as TraceEngine from '../../models/trace/trace.js'; |
Tim van der Lippe | 229a54f | 2021-05-14 16:59:05 | [diff] [blame] | 12 | import type * as Protocol from '../../generated/protocol.js'; |
Tim van der Lippe | cec9b76 | 2020-02-13 15:31:22 | [diff] [blame] | 13 | |
Paul Lewis | 897ad8b | 2020-01-15 16:49:17 | [diff] [blame] | 14 | import {PerformanceModel} from './PerformanceModel.js'; |
Paul Lewis | 897ad8b | 2020-01-15 16:49:17 | [diff] [blame] | 15 | |
Simon Zünd | 697fb0b | 2021-03-01 10:12:42 | [diff] [blame] | 16 | const UIStrings = { |
Vidal Guillermo Diazleal Ortega | 87060e4 | 2021-02-11 21:32:34 | [diff] [blame] | 17 | /** |
Simon Zünd | 648d6cf | 2021-04-20 06:30:57 | [diff] [blame] | 18 | * @description Text in Timeline Controller of the Performance panel. |
| 19 | * A "CPU profile" is a recorded performance measurement how a specific target behaves. |
| 20 | * "Target" in this context can mean a web page, service or normal worker. |
| 21 | * "Not available" is used as there are multiple things that can go wrong, but we do not |
| 22 | * know what exactly, just that the CPU profile was not correctly recorded. |
| 23 | */ |
Vidal Guillermo Diazleal Ortega | 87060e4 | 2021-02-11 21:32:34 | [diff] [blame] | 24 | cpuProfileForATargetIsNot: 'CPU profile for a target is not available.', |
Sigurd Schneider | ab1f2b5 | 2021-04-06 08:31:04 | [diff] [blame] | 25 | /** |
Sigurd Schneider | fdc7e13 | 2021-05-07 06:33:45 | [diff] [blame] | 26 | *@description Text in Timeline Controller of the Performance panel indicating that the Performance Panel cannot |
| 27 | * record a performance trace because the type of target (where possible types are page, service worker and shared |
| 28 | * worker) doesn't support it. |
| 29 | */ |
| 30 | tracingNotSupported: 'Performance trace recording not supported for this type of target', |
Vidal Guillermo Diazleal Ortega | 87060e4 | 2021-02-11 21:32:34 | [diff] [blame] | 31 | }; |
Tim van der Lippe | 01e1c46 | 2021-04-19 15:04:03 | [diff] [blame] | 32 | const str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineController.ts', UIStrings); |
Vidal Guillermo Diazleal Ortega | 87060e4 | 2021-02-11 21:32:34 | [diff] [blame] | 33 | const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); |
Sigurd Schneider | b9f6c79 | 2021-05-31 10:57:24 | [diff] [blame] | 34 | export class TimelineController implements SDK.TargetManager.SDKModelObserver<SDK.CPUProfilerModel.CPUProfilerModel>, |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 35 | SDK.TracingManager.TracingManagerClient { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 36 | private readonly target: SDK.Target.Target; |
| 37 | private tracingManager: SDK.TracingManager.TracingManager|null; |
| 38 | private performanceModel: PerformanceModel; |
| 39 | private readonly client: Client; |
| 40 | private readonly tracingModel: SDK.TracingModel.TracingModel; |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 41 | // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration |
| 42 | // eslint-disable-next-line @typescript-eslint/no-explicit-any |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 43 | private tracingCompleteCallback?: ((value: any) => void)|null; |
| 44 | private profiling?: boolean; |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 45 | // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration |
| 46 | // eslint-disable-next-line @typescript-eslint/no-explicit-any |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 47 | private cpuProfiles?: Map<any, any>|null; |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 48 | |
Sigurd Schneider | 79e812e | 2021-06-04 06:48:23 | [diff] [blame] | 49 | constructor(target: SDK.Target.Target, client: Client) { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 50 | this.target = target; |
| 51 | this.tracingManager = target.model(SDK.TracingManager.TracingManager); |
| 52 | this.performanceModel = new PerformanceModel(); |
| 53 | this.performanceModel.setMainTarget(target); |
| 54 | this.client = client; |
Jack Franklin | 45522ff | 2023-06-01 13:19:51 | [diff] [blame^] | 55 | this.tracingModel = new SDK.TracingModel.TracingModel(); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 56 | |
Sigurd Schneider | b9f6c79 | 2021-05-31 10:57:24 | [diff] [blame] | 57 | SDK.TargetManager.TargetManager.instance().observeModels(SDK.CPUProfilerModel.CPUProfilerModel, this); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 58 | } |
| 59 | |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 60 | dispose(): void { |
Sigurd Schneider | b9f6c79 | 2021-05-31 10:57:24 | [diff] [blame] | 61 | SDK.TargetManager.TargetManager.instance().unobserveModels(SDK.CPUProfilerModel.CPUProfilerModel, this); |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 62 | } |
| 63 | |
Sigurd Schneider | 79e812e | 2021-06-04 06:48:23 | [diff] [blame] | 64 | mainTarget(): SDK.Target.Target { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 65 | return this.target; |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 66 | } |
| 67 | |
Jack Franklin | 0de5e82 | 2023-03-09 12:00:37 | [diff] [blame] | 68 | async startRecording(options: RecordingOptions): Promise<Protocol.ProtocolResponseWithError> { |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 69 | function disabledByDefault(category: string): string { |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 70 | return 'disabled-by-default-' + category; |
| 71 | } |
Victor Porof | c22da12 | 2022-03-02 17:17:57 | [diff] [blame] | 72 | |
| 73 | // The following categories are also used in other tools, but this panel |
| 74 | // offers the possibility of turning them off (see below). |
| 75 | // 'disabled-by-default-devtools.screenshot' |
| 76 | // └ default: on, option: captureFilmStrip |
| 77 | // 'disabled-by-default-devtools.timeline.invalidationTracking' |
| 78 | // └ default: off, experiment: timelineInvalidationTracking |
| 79 | // 'disabled-by-default-v8.cpu_profiler' |
| 80 | // └ default: on, option: enableJSSampling |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 81 | const categoriesArray = [ |
Paul Irish | 0567b73 | 2022-05-02 18:31:12 | [diff] [blame] | 82 | Root.Runtime.experiments.isEnabled('timelineShowAllEvents') ? '*' : '-*', |
Victor Porof | c22da12 | 2022-03-02 17:17:57 | [diff] [blame] | 83 | TimelineModel.TimelineModel.TimelineModelImpl.Category.Console, |
| 84 | TimelineModel.TimelineModel.TimelineModelImpl.Category.UserTiming, |
Jaroslav Sevcik | b3d1dd2 | 2022-02-09 06:57:54 | [diff] [blame] | 85 | 'devtools.timeline', |
| 86 | disabledByDefault('devtools.timeline'), |
| 87 | disabledByDefault('devtools.timeline.frame'), |
Victor Porof | c22da12 | 2022-03-02 17:17:57 | [diff] [blame] | 88 | disabledByDefault('devtools.timeline.stack'), |
Jaroslav Sevcik | b3d1dd2 | 2022-02-09 06:57:54 | [diff] [blame] | 89 | disabledByDefault('v8.compile'), |
Victor Porof | c22da12 | 2022-03-02 17:17:57 | [diff] [blame] | 90 | disabledByDefault('v8.cpu_profiler.hires'), |
Paul Lewis | 9edf751 | 2020-04-01 09:37:21 | [diff] [blame] | 91 | TimelineModel.TimelineModel.TimelineModelImpl.Category.Loading, |
Victor Porof | c22da12 | 2022-03-02 17:17:57 | [diff] [blame] | 92 | disabledByDefault('lighthouse'), |
| 93 | 'v8.execute', |
| 94 | 'v8', |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 95 | ]; |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 96 | |
Simon Zünd | 7b7b35e | 2021-11-25 06:31:24 | [diff] [blame] | 97 | if (Root.Runtime.experiments.isEnabled('timelineV8RuntimeCallStats') && options.enableJSSampling) { |
| 98 | categoriesArray.push(disabledByDefault('v8.runtime_stats_sampling')); |
| 99 | } |
Andrés Olivares | 7cc96e8 | 2023-05-04 15:54:56 | [diff] [blame] | 100 | if (options.enableJSSampling) { |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 101 | categoriesArray.push(disabledByDefault('v8.cpu_profiler')); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 102 | } |
Tim van der Lippe | 99e59b8 | 2019-09-30 20:00:59 | [diff] [blame] | 103 | if (Root.Runtime.experiments.isEnabled('timelineInvalidationTracking')) { |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 104 | categoriesArray.push(disabledByDefault('devtools.timeline.invalidationTracking')); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 105 | } |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 106 | if (options.capturePictures) { |
| 107 | categoriesArray.push( |
| 108 | disabledByDefault('devtools.timeline.layers'), disabledByDefault('devtools.timeline.picture'), |
| 109 | disabledByDefault('blink.graphics_context_annotations')); |
| 110 | } |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 111 | if (options.captureFilmStrip) { |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 112 | categoriesArray.push(disabledByDefault('devtools.screenshot')); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 113 | } |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 114 | |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 115 | this.performanceModel.setRecordStartTime(Date.now()); |
Andrés Olivares | 7cc96e8 | 2023-05-04 15:54:56 | [diff] [blame] | 116 | const response = await this.startRecordingWithCategories(categoriesArray.join(',')); |
Sigurd Schneider | ab1f2b5 | 2021-04-06 08:31:04 | [diff] [blame] | 117 | if (response.getError()) { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 118 | await this.waitForTracingToStop(false); |
Sigurd Schneider | b9f6c79 | 2021-05-31 10:57:24 | [diff] [blame] | 119 | await SDK.TargetManager.TargetManager.instance().resumeAllTargets(); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 120 | } |
Sigurd Schneider | 6eecdaa | 2019-08-20 07:47:10 | [diff] [blame] | 121 | return response; |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 122 | } |
| 123 | |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 124 | async stopRecording(): Promise<PerformanceModel> { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 125 | if (this.tracingManager) { |
| 126 | this.tracingManager.stop(); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 127 | } |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 128 | |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 129 | this.client.loadingStarted(); |
| 130 | await this.waitForTracingToStop(true); |
Andrés Olivares | 435b3eb | 2022-10-17 11:46:39 | [diff] [blame] | 131 | await this.allSourcesFinished(); |
| 132 | return this.performanceModel; |
| 133 | } |
| 134 | |
| 135 | getPerformanceModel(): PerformanceModel { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 136 | return this.performanceModel; |
Sigurd Schneider | 6eecdaa | 2019-08-20 07:47:10 | [diff] [blame] | 137 | } |
| 138 | |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 139 | private async waitForTracingToStop(awaitTracingCompleteCallback: boolean): Promise<void> { |
Sigurd Schneider | 6eecdaa | 2019-08-20 07:47:10 | [diff] [blame] | 140 | const tracingStoppedPromises = []; |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 141 | if (this.tracingManager && awaitTracingCompleteCallback) { |
Patrick Brosset | e65aaac | 2020-06-22 08:04:40 | [diff] [blame] | 142 | tracingStoppedPromises.push(new Promise(resolve => { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 143 | this.tracingCompleteCallback = resolve; |
Patrick Brosset | e65aaac | 2020-06-22 08:04:40 | [diff] [blame] | 144 | })); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 145 | } |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 146 | tracingStoppedPromises.push(this.stopProfilingOnAllModels()); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 147 | |
Alex Rudenko | 1f8ea58 | 2020-11-19 09:16:07 | [diff] [blame] | 148 | await Promise.all(tracingStoppedPromises); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 149 | } |
| 150 | |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 151 | modelAdded(cpuProfilerModel: SDK.CPUProfilerModel.CPUProfilerModel): void { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 152 | if (this.profiling) { |
Tim van der Lippe | 2d9a95c | 2022-01-04 15:18:03 | [diff] [blame] | 153 | void cpuProfilerModel.startRecording(); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 154 | } |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 155 | } |
| 156 | |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 157 | modelRemoved(_cpuProfilerModel: SDK.CPUProfilerModel.CPUProfilerModel): void { |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 158 | // FIXME: We'd like to stop profiling on the target and retrieve a profile |
| 159 | // but it's too late. Backend connection is closed. |
| 160 | } |
| 161 | |
Sigurd Schneider | a64c135 | 2021-08-18 10:49:29 | [diff] [blame] | 162 | private addCpuProfile(targetId: Protocol.Target.TargetID|'main', cpuProfile: Protocol.Profiler.Profile|null): void { |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 163 | if (!cpuProfile) { |
Vidal Guillermo Diazleal Ortega | 87060e4 | 2021-02-11 21:32:34 | [diff] [blame] | 164 | Common.Console.Console.instance().warn(i18nString(UIStrings.cpuProfileForATargetIsNot)); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 165 | return; |
| 166 | } |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 167 | if (!this.cpuProfiles) { |
| 168 | this.cpuProfiles = new Map(); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 169 | } |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 170 | this.cpuProfiles.set(targetId, cpuProfile); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 171 | } |
| 172 | |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 173 | private async stopProfilingOnAllModels(): Promise<void> { |
Paul Lewis | daac106 | 2020-03-05 14:37:10 | [diff] [blame] | 174 | const models = |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 175 | this.profiling ? SDK.TargetManager.TargetManager.instance().models(SDK.CPUProfilerModel.CPUProfilerModel) : []; |
| 176 | this.profiling = false; |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 177 | const promises = []; |
| 178 | for (const model of models) { |
| 179 | const targetId = model.target().id(); |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 180 | const modelPromise = model.stopRecording().then(this.addCpuProfile.bind(this, targetId)); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 181 | promises.push(modelPromise); |
| 182 | } |
Alex Rudenko | 1f8ea58 | 2020-11-19 09:16:07 | [diff] [blame] | 183 | await Promise.all(promises); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 184 | } |
| 185 | |
Andrés Olivares | 7cc96e8 | 2023-05-04 15:54:56 | [diff] [blame] | 186 | private async startRecordingWithCategories(categories: string): Promise<Protocol.ProtocolResponseWithError> { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 187 | if (!this.tracingManager) { |
Sigurd Schneider | ab1f2b5 | 2021-04-06 08:31:04 | [diff] [blame] | 188 | throw new Error(UIStrings.tracingNotSupported); |
| 189 | } |
Sigurd Schneider | 8c2bcfd | 2019-09-04 09:03:29 | [diff] [blame] | 190 | // There might be a significant delay in the beginning of timeline recording |
| 191 | // caused by starting CPU profiler, that needs to traverse JS heap to collect |
| 192 | // all the functions data. |
Sigurd Schneider | b9f6c79 | 2021-05-31 10:57:24 | [diff] [blame] | 193 | await SDK.TargetManager.TargetManager.instance().suspendAllTargets('performance-timeline'); |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 194 | return this.tracingManager.start(this, categories, ''); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 195 | } |
| 196 | |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 197 | traceEventsCollected(events: SDK.TracingManager.EventPayload[]): void { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 198 | this.tracingModel.addEvents(events); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 199 | } |
| 200 | |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 201 | tracingComplete(): void { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 202 | if (!this.tracingCompleteCallback) { |
Alex Rudenko | 1f8ea58 | 2020-11-19 09:16:07 | [diff] [blame] | 203 | return; |
| 204 | } |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 205 | this.tracingCompleteCallback(undefined); |
| 206 | this.tracingCompleteCallback = null; |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 207 | } |
| 208 | |
Andrés Olivares | 435b3eb | 2022-10-17 11:46:39 | [diff] [blame] | 209 | private async allSourcesFinished(): Promise<void> { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 210 | this.client.processingStarted(); |
Andrés Olivares | 435b3eb | 2022-10-17 11:46:39 | [diff] [blame] | 211 | await this.finalizeTrace(); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 212 | } |
| 213 | |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 214 | private async finalizeTrace(): Promise<void> { |
| 215 | this.injectCpuProfileEvents(); |
Sigurd Schneider | b9f6c79 | 2021-05-31 10:57:24 | [diff] [blame] | 216 | await SDK.TargetManager.TargetManager.instance().resumeAllTargets(); |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 217 | this.tracingModel.tracingComplete(); |
Nancy Li | 351e005 | 2023-02-25 00:53:32 | [diff] [blame] | 218 | await this.client.loadingComplete(this.tracingModel, null); |
Andrés Olivares | 435b3eb | 2022-10-17 11:46:39 | [diff] [blame] | 219 | this.client.loadingCompleteForTest(); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 220 | } |
| 221 | |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 222 | private injectCpuProfileEvent(pid: number, tid: number, cpuProfile: Protocol.Profiler.Profile|null): void { |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 223 | if (!cpuProfile) { |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 224 | return; |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 225 | } |
Alex Rudenko | 1f8ea58 | 2020-11-19 09:16:07 | [diff] [blame] | 226 | // TODO(crbug/1011811): This event type is not compatible with the SDK.TracingManager.EventPayload. |
| 227 | // EventPayload requires many properties to be defined but it's not clear if they will have |
| 228 | // any side effects. |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 229 | const cpuProfileEvent = ({ |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 230 | cat: SDK.TracingModel.DevToolsMetadataEventCategory, |
Jack Franklin | 0b4f963 | 2023-03-03 15:40:41 | [diff] [blame] | 231 | ph: TraceEngine.Types.TraceEvents.Phase.INSTANT, |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 232 | ts: this.tracingModel.maximumRecordTime() * 1000, |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 233 | pid: pid, |
| 234 | tid: tid, |
| 235 | name: TimelineModel.TimelineModel.RecordType.CpuProfile, |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 236 | args: {data: {cpuProfile: cpuProfile}}, |
| 237 | // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration |
| 238 | // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 239 | } as any); |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 240 | this.tracingModel.addEvents([cpuProfileEvent]); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 241 | } |
| 242 | |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 243 | private buildTargetToProcessIdMap(): Map<string, number>|null { |
Tim van der Lippe | cec9b76 | 2020-02-13 15:31:22 | [diff] [blame] | 244 | const metadataEventTypes = TimelineModel.TimelineModel.TimelineModelImpl.DevToolsMetadataEvent; |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 245 | const metadataEvents = this.tracingModel.devToolsMetadataEvents(); |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 246 | const browserMetaEvent = metadataEvents.find(e => e.name === metadataEventTypes.TracingStartedInBrowser); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 247 | if (!browserMetaEvent) { |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 248 | return null; |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 249 | } |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 250 | |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 251 | const pseudoPidToFrames = new Platform.MapUtilities.Multimap<string, string>(); |
| 252 | const targetIdToPid = new Map<string, number>(); |
| 253 | // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration |
| 254 | // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 255 | const frames: any[] = browserMetaEvent.args.data.frames; |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 256 | for (const frameInfo of frames) { |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 257 | targetIdToPid.set(frameInfo.frame, frameInfo.processId); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 258 | } |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 259 | for (const event of metadataEvents) { |
| 260 | const data = event.args.data; |
| 261 | switch (event.name) { |
| 262 | case metadataEventTypes.FrameCommittedInBrowser: |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 263 | if (data.processId) { |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 264 | targetIdToPid.set(data.frame, data.processId); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 265 | } else { |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 266 | pseudoPidToFrames.set(data.processPseudoId, data.frame); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 267 | } |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 268 | break; |
| 269 | case metadataEventTypes.ProcessReadyInBrowser: |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 270 | for (const frame of pseudoPidToFrames.get(data.processPseudoId) || []) { |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 271 | targetIdToPid.set(frame, data.processId); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 272 | } |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 273 | break; |
| 274 | } |
| 275 | } |
| 276 | const mainFrame = frames.find(frame => !frame.parent); |
| 277 | const mainRendererProcessId = mainFrame.processId; |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 278 | const mainProcess = this.tracingModel.getProcessById(mainRendererProcessId); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 279 | if (mainProcess) { |
Danil Somsikov | 1125082 | 2023-02-27 15:02:19 | [diff] [blame] | 280 | const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget(); |
Alex Rudenko | 1f8ea58 | 2020-11-19 09:16:07 | [diff] [blame] | 281 | if (target) { |
| 282 | targetIdToPid.set(target.id(), mainProcess.id()); |
| 283 | } |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 284 | } |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 285 | return targetIdToPid; |
| 286 | } |
| 287 | |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 288 | private injectCpuProfileEvents(): void { |
| 289 | if (!this.cpuProfiles) { |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 290 | return; |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 291 | } |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 292 | |
Tim van der Lippe | cec9b76 | 2020-02-13 15:31:22 | [diff] [blame] | 293 | const metadataEventTypes = TimelineModel.TimelineModel.TimelineModelImpl.DevToolsMetadataEvent; |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 294 | const metadataEvents = this.tracingModel.devToolsMetadataEvents(); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 295 | |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 296 | const targetIdToPid = this.buildTargetToProcessIdMap(); |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 297 | if (targetIdToPid) { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 298 | for (const [id, profile] of this.cpuProfiles) { |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 299 | const pid = targetIdToPid.get(id); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 300 | if (!pid) { |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 301 | continue; |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 302 | } |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 303 | const process = this.tracingModel.getProcessById(pid); |
Tim van der Lippe | cec9b76 | 2020-02-13 15:31:22 | [diff] [blame] | 304 | const thread = |
| 305 | process && process.threadByName(TimelineModel.TimelineModel.TimelineModelImpl.RendererMainThreadName); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 306 | if (thread) { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 307 | this.injectCpuProfileEvent(pid, thread.id(), profile); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 308 | } |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 309 | } |
| 310 | } else { |
| 311 | // Legacy backends support. |
Tim van der Lippe | 779b46b | 2021-01-13 13:40:22 | [diff] [blame] | 312 | const filteredEvents = metadataEvents.filter(event => event.name === metadataEventTypes.TracingStartedInPage); |
| 313 | const mainMetaEvent = filteredEvents[filteredEvents.length - 1]; |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 314 | if (mainMetaEvent) { |
| 315 | const pid = mainMetaEvent.thread.process().id(); |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 316 | if (this.tracingManager) { |
| 317 | const mainCpuProfile = this.cpuProfiles.get(this.tracingManager.target().id()); |
| 318 | this.injectCpuProfileEvent(pid, mainMetaEvent.thread.id(), mainCpuProfile); |
Alex Rudenko | 1f8ea58 | 2020-11-19 09:16:07 | [diff] [blame] | 319 | } |
Pavel Feldman | c039591 | 2018-08-03 02:05:00 | [diff] [blame] | 320 | } else { |
| 321 | // Or there was no tracing manager in the main target at all, in this case build the model full |
| 322 | // of cpu profiles. |
Alexei Filippov | 2af968a | 2018-08-17 02:24:36 | [diff] [blame] | 323 | let tid = 0; |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 324 | for (const pair of this.cpuProfiles) { |
Sigurd Schneider | b9f6c79 | 2021-05-31 10:57:24 | [diff] [blame] | 325 | const target = SDK.TargetManager.TargetManager.instance().targetById(pair[0]); |
Alexei Filippov | 2af968a | 2018-08-17 02:24:36 | [diff] [blame] | 326 | const name = target && target.name(); |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 327 | this.tracingModel.addEvents( |
Paul Irish | 3e218b2 | 2023-03-02 03:21:59 | [diff] [blame] | 328 | TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile( |
Tim van der Lippe | cec9b76 | 2020-02-13 15:31:22 | [diff] [blame] | 329 | pair[1], ++tid, /* injectPageEvent */ tid === 1, name)); |
Pavel Feldman | c039591 | 2018-08-03 02:05:00 | [diff] [blame] | 330 | } |
Alexei Filippov | e712dbc | 2018-05-30 22:31:33 | [diff] [blame] | 331 | } |
| 332 | } |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 333 | |
| 334 | const workerMetaEvents = |
| 335 | metadataEvents.filter(event => event.name === metadataEventTypes.TracingSessionIdForWorker); |
| 336 | for (const metaEvent of workerMetaEvents) { |
| 337 | const workerId = metaEvent.args['data']['workerId']; |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 338 | const cpuProfile = this.cpuProfiles.get(workerId); |
| 339 | this.injectCpuProfileEvent(metaEvent.thread.process().id(), metaEvent.args['data']['workerThreadId'], cpuProfile); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 340 | } |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 341 | this.cpuProfiles = null; |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 342 | } |
| 343 | |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 344 | tracingBufferUsage(usage: number): void { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 345 | this.client.recordingProgress(usage); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 346 | } |
| 347 | |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 348 | eventsRetrievalProgress(progress: number): void { |
Jan Scheffler | f986791 | 2021-08-12 13:25:03 | [diff] [blame] | 349 | this.client.loadingProgress(progress); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 350 | } |
Tim van der Lippe | 0176f6c | 2020-01-08 11:07:01 | [diff] [blame] | 351 | } |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 352 | |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 353 | export interface Client { |
| 354 | recordingProgress(usage: number): void; |
| 355 | loadingStarted(): void; |
| 356 | processingStarted(): void; |
| 357 | loadingProgress(progress?: number): void; |
Nancy Li | 351e005 | 2023-02-25 00:53:32 | [diff] [blame] | 358 | loadingComplete( |
| 359 | tracingModel: SDK.TracingModel.TracingModel|null, |
Jack Franklin | 45522ff | 2023-06-01 13:19:51 | [diff] [blame^] | 360 | exclusiveFilter: TimelineModel.TimelineModelFilter.TimelineModelFilter|null): Promise<void>; |
Andrés Olivares | 435b3eb | 2022-10-17 11:46:39 | [diff] [blame] | 361 | loadingCompleteForTest(): void; |
Tim van der Lippe | 0176f6c | 2020-01-08 11:07:01 | [diff] [blame] | 362 | } |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 363 | export interface RecordingOptions { |
| 364 | enableJSSampling?: boolean; |
| 365 | capturePictures?: boolean; |
| 366 | captureFilmStrip?: boolean; |
Jan Scheffler | 0d88c01 | 2021-04-05 18:45:53 | [diff] [blame] | 367 | } |