blob: 2c3ef2b717832bb5c90ad640924e9fa73f9ff543 [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371/*
2 * Copyright (C) 2014 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
Tim van der Lippe83f02be2020-01-23 11:11:408 * * Redistributions of source code must retain the above copyright
Blink Reformat4c46d092018-04-07 15:32:379 * notice, this list of conditions and the following disclaimer.
Tim van der Lippe83f02be2020-01-23 11:11:4010 * * Redistributions in binary form must reproduce the above
Blink Reformat4c46d092018-04-07 15:32:3711 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
Tim van der Lippe83f02be2020-01-23 11:11:4014 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
Blink Reformat4c46d092018-04-07 15:32:3717 *
Tim van der Lippe83f02be2020-01-23 11:11:4018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Blink Reformat4c46d092018-04-07 15:32:3719 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Tim van der Lippe83f02be2020-01-23 11:11:4021 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Blink Reformat4c46d092018-04-07 15:32:3723 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
Tim van der Lipped41d8632020-01-23 15:15:1231import * as Common from '../common/common.js';
32
Tim van der Lippe9293af72020-01-17 10:50:3733import {DebuggerModel, Location} from './DebuggerModel.js';
34import {RuntimeModel} from './RuntimeModel.js'; // eslint-disable-line no-unused-vars
35import {Capability, SDKModel, Target} from './SDKModel.js'; // eslint-disable-line no-unused-vars
36
Blink Reformat4c46d092018-04-07 15:32:3737/**
38 * @implements {Protocol.ProfilerDispatcher}
39 */
Tim van der Lippe9293af72020-01-17 10:50:3740export class CPUProfilerModel extends SDKModel {
Blink Reformat4c46d092018-04-07 15:32:3741 /**
Tim van der Lippe9293af72020-01-17 10:50:3742 * @param {!Target} target
Blink Reformat4c46d092018-04-07 15:32:3743 */
44 constructor(target) {
45 super(target);
46 this._isRecording = false;
47 this._nextAnonymousConsoleProfileNumber = 1;
48 this._anonymousConsoleProfileIdToTitle = new Map();
49 this._profilerAgent = target.profilerAgent();
Sigurd Schneider759ef972020-01-28 09:46:0650 /** @type {?function(number, string, !Array<!Protocol.Profiler.ScriptCoverage>)} */
51 this._preciseCoverageDeltaUpdateCallback = null;
Blink Reformat4c46d092018-04-07 15:32:3752 target.registerProfilerDispatcher(this);
53 this._profilerAgent.enable();
Tim van der Lippe9293af72020-01-17 10:50:3754 this._debuggerModel = /** @type {!DebuggerModel} */ (target.model(DebuggerModel));
Blink Reformat4c46d092018-04-07 15:32:3755 }
56
57 /**
Tim van der Lippe9293af72020-01-17 10:50:3758 * @return {!RuntimeModel}
Blink Reformat4c46d092018-04-07 15:32:3759 */
60 runtimeModel() {
61 return this._debuggerModel.runtimeModel();
62 }
63
64 /**
Tim van der Lippe9293af72020-01-17 10:50:3765 * @return {!DebuggerModel}
Blink Reformat4c46d092018-04-07 15:32:3766 */
67 debuggerModel() {
68 return this._debuggerModel;
69 }
70
71 /**
72 * @override
73 * @param {string} id
74 * @param {!Protocol.Debugger.Location} scriptLocation
75 * @param {string=} title
76 */
77 consoleProfileStarted(id, scriptLocation, title) {
78 if (!title) {
Tim van der Lipped41d8632020-01-23 15:15:1279 title = Common.UIString.UIString('Profile %d', this._nextAnonymousConsoleProfileNumber++);
Blink Reformat4c46d092018-04-07 15:32:3780 this._anonymousConsoleProfileIdToTitle.set(id, title);
81 }
Tim van der Lippe9b7d21d2019-10-07 18:48:0782 this._dispatchProfileEvent(Events.ConsoleProfileStarted, id, scriptLocation, title);
Blink Reformat4c46d092018-04-07 15:32:3783 }
84
85 /**
86 * @override
87 * @param {string} id
88 * @param {!Protocol.Debugger.Location} scriptLocation
89 * @param {!Protocol.Profiler.Profile} cpuProfile
90 * @param {string=} title
91 */
92 consoleProfileFinished(id, scriptLocation, cpuProfile, title) {
93 if (!title) {
94 title = this._anonymousConsoleProfileIdToTitle.get(id);
95 this._anonymousConsoleProfileIdToTitle.delete(id);
96 }
97 // Make sure ProfilesPanel is initialized and CPUProfileType is created.
98 self.runtime.loadModulePromise('profiler').then(() => {
Tim van der Lippe9b7d21d2019-10-07 18:48:0799 this._dispatchProfileEvent(Events.ConsoleProfileFinished, id, scriptLocation, title, cpuProfile);
Blink Reformat4c46d092018-04-07 15:32:37100 });
101 }
102
103 /**
104 * @param {symbol} eventName
105 * @param {string} id
106 * @param {!Protocol.Debugger.Location} scriptLocation
107 * @param {string=} title
108 * @param {!Protocol.Profiler.Profile=} cpuProfile
109 */
110 _dispatchProfileEvent(eventName, id, scriptLocation, title, cpuProfile) {
Tim van der Lippe9293af72020-01-17 10:50:37111 const debuggerLocation = Location.fromPayload(this._debuggerModel, scriptLocation);
Blink Reformat4c46d092018-04-07 15:32:37112 const globalId = this.target().id() + '.' + id;
Tim van der Lippeff5ad472020-02-17 12:35:09113 const data = /** @type {!EventData} */ (
Blink Reformat4c46d092018-04-07 15:32:37114 {id: globalId, scriptLocation: debuggerLocation, cpuProfile: cpuProfile, title: title, cpuProfilerModel: this});
115 this.dispatchEventToListeners(eventName, data);
116 }
117
118 /**
119 * @return {boolean}
120 */
121 isRecordingProfile() {
122 return this._isRecording;
123 }
124
125 /**
126 * @return {!Promise}
127 */
128 startRecording() {
129 this._isRecording = true;
Paul Lewis4b64b3f2020-01-23 11:41:20130 const intervalUs = self.Common.settings.moduleSetting('highResolutionCpuProfiling').get() ? 100 : 1000;
Blink Reformat4c46d092018-04-07 15:32:37131 this._profilerAgent.setSamplingInterval(intervalUs);
132 return this._profilerAgent.start();
133 }
134
135 /**
136 * @return {!Promise<?Protocol.Profiler.Profile>}
137 */
138 stopRecording() {
139 this._isRecording = false;
140 return this._profilerAgent.stop();
141 }
142
143 /**
Sigurd Schneider7a52be22019-10-30 08:56:48144 * @param {boolean} jsCoveragePerBlock - Collect per Block coverage if `true`, per function coverage otherwise.
Sigurd Schneider759ef972020-01-28 09:46:06145 * @param {?function(number, string, !Array<!Protocol.Profiler.ScriptCoverage>)} preciseCoverageDeltaUpdateCallback - Callback for coverage updates initiated from the back-end
Blink Reformat4c46d092018-04-07 15:32:37146 * @return {!Promise}
147 */
Sigurd Schneider759ef972020-01-28 09:46:06148 startPreciseCoverage(jsCoveragePerBlock, preciseCoverageDeltaUpdateCallback) {
Blink Reformat4c46d092018-04-07 15:32:37149 const callCount = false;
Sigurd Schneider759ef972020-01-28 09:46:06150 this._preciseCoverageDeltaUpdateCallback = preciseCoverageDeltaUpdateCallback;
Sigurd Schneiderc83e88a2020-02-13 08:43:11151 const allowUpdatesTriggeredByBackend = true;
152 return this._profilerAgent.startPreciseCoverage(callCount, jsCoveragePerBlock, allowUpdatesTriggeredByBackend);
Blink Reformat4c46d092018-04-07 15:32:37153 }
154
155 /**
Sigurd Schneider13f30b92020-01-22 09:41:27156 * @return {!Promise<{timestamp:number, coverage:!Array<!Protocol.Profiler.ScriptCoverage>}>}
Blink Reformat4c46d092018-04-07 15:32:37157 */
Sigurd Schneider13f30b92020-01-22 09:41:27158 async takePreciseCoverage() {
159 const r = await this._profilerAgent.invoke_takePreciseCoverage({});
160 const timestamp = (r && r.timestamp) || 0;
161 const coverage = (r && r.result) || [];
162 return {timestamp, coverage};
Blink Reformat4c46d092018-04-07 15:32:37163 }
164
165 /**
166 * @return {!Promise}
167 */
168 stopPreciseCoverage() {
Sigurd Schneider759ef972020-01-28 09:46:06169 this._preciseCoverageDeltaUpdateCallback = null;
Blink Reformat4c46d092018-04-07 15:32:37170 return this._profilerAgent.stopPreciseCoverage();
171 }
Sigurd Schneider7ec654f2020-01-20 12:01:35172
173 /**
174 * @suppress {missingOverride}
175 * @param {number} timestampInSeconds
176 * @param {string} occassion
177 * @param {!Array<!Protocol.Profiler.ScriptCoverage>} coverageData
178 */
179 preciseCoverageDeltaUpdate(timestampInSeconds, occassion, coverageData) {
Sigurd Schneider759ef972020-01-28 09:46:06180 if (this._preciseCoverageDeltaUpdateCallback) {
181 this._preciseCoverageDeltaUpdateCallback(timestampInSeconds, occassion, coverageData);
182 }
Sigurd Schneider7ec654f2020-01-20 12:01:35183 }
Tim van der Lippe9b7d21d2019-10-07 18:48:07184}
Blink Reformat4c46d092018-04-07 15:32:37185
186/** @enum {symbol} */
Tim van der Lippe9b7d21d2019-10-07 18:48:07187export const Events = {
Blink Reformat4c46d092018-04-07 15:32:37188 ConsoleProfileStarted: Symbol('ConsoleProfileStarted'),
189 ConsoleProfileFinished: Symbol('ConsoleProfileFinished')
190};
191
Tim van der Lippe9293af72020-01-17 10:50:37192SDKModel.register(CPUProfilerModel, Capability.JS, true);
Tim van der Lippee54f66e2020-02-03 18:20:32193
194/** @typedef {!{id: string, scriptLocation: !DebuggerModel.Location, title: string, cpuProfile: (!Protocol.Profiler.Profile|undefined), cpuProfilerModel: !CPUProfilerModel}} */
195export let EventData;