| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @implements {SDK.TargetManager.Observer} | 6 * @implements {SDK.SDKModelObserver<!SDK.CPUProfilerModel>} |
| 7 * @implements {SDK.TracingManagerClient} | 7 * @implements {SDK.TracingManagerClient} |
| 8 * @unrestricted | 8 * @unrestricted |
| 9 */ | 9 */ |
| 10 Timeline.TimelineController = class { | 10 Timeline.TimelineController = class { |
| 11 /** | 11 /** |
| 12 * @param {!SDK.Target} target | 12 * @param {!SDK.Target} target |
| 13 * @param {!Timeline.PerformanceModel} performanceModel | 13 * @param {!Timeline.PerformanceModel} performanceModel |
| 14 * @param {!Timeline.TimelineController.Client} client | 14 * @param {!Timeline.TimelineController.Client} client |
| 15 */ | 15 */ |
| 16 constructor(target, performanceModel, client) { | 16 constructor(target, performanceModel, client) { |
| 17 this._target = target; | 17 this._target = target; |
| 18 this._performanceModel = performanceModel; | 18 this._performanceModel = performanceModel; |
| 19 this._client = client; | 19 this._client = client; |
| 20 | 20 |
| 21 this._tracingModelBackingStorage = new Bindings.TempFileBackingStorage('trac
ing'); | 21 this._tracingModelBackingStorage = new Bindings.TempFileBackingStorage('trac
ing'); |
| 22 this._tracingModel = new SDK.TracingModel(this._tracingModelBackingStorage); | 22 this._tracingModel = new SDK.TracingModel(this._tracingModelBackingStorage); |
| 23 | 23 |
| 24 this._performanceModel.setMainTarget(target); | 24 this._performanceModel.setMainTarget(target); |
| 25 | 25 |
| 26 /** @type {!Array<!SDK.Target>} */ | |
| 27 this._targets = []; | |
| 28 /** @type {!Array<!Timeline.ExtensionTracingSession>} */ | 26 /** @type {!Array<!Timeline.ExtensionTracingSession>} */ |
| 29 this._extensionSessions = []; | 27 this._extensionSessions = []; |
| 30 SDK.targetManager.observeTargets(this); | 28 SDK.targetManager.observeModels(SDK.CPUProfilerModel, this); |
| 31 } | 29 } |
| 32 | 30 |
| 33 /** | 31 /** |
| 34 * @param {!Timeline.TimelineController.RecordingOptions} options | 32 * @param {!Timeline.TimelineController.RecordingOptions} options |
| 35 * @param {!Array<!Extensions.ExtensionTraceProvider>} providers | 33 * @param {!Array<!Extensions.ExtensionTraceProvider>} providers |
| 36 * @return {!Promise} | 34 * @return {!Promise} |
| 37 */ | 35 */ |
| 38 startRecording(options, providers) { | 36 startRecording(options, providers) { |
| 39 this._extensionTraceProviders = Extensions.extensionServer.traceProviders().
slice(); | 37 this._extensionTraceProviders = Extensions.extensionServer.traceProviders().
slice(); |
| 40 | 38 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 providers.map(provider => new Timeline.ExtensionTracingSession(provider,
this._performanceModel)); | 72 providers.map(provider => new Timeline.ExtensionTracingSession(provider,
this._performanceModel)); |
| 75 this._extensionSessions.forEach(session => session.start()); | 73 this._extensionSessions.forEach(session => session.start()); |
| 76 var startPromise = this._startRecordingWithCategories(categoriesArray.join('
,'), options.enableJSSampling); | 74 var startPromise = this._startRecordingWithCategories(categoriesArray.join('
,'), options.enableJSSampling); |
| 77 this._performanceModel.setRecordStartTime(Date.now()); | 75 this._performanceModel.setRecordStartTime(Date.now()); |
| 78 return startPromise; | 76 return startPromise; |
| 79 } | 77 } |
| 80 | 78 |
| 81 stopRecording() { | 79 stopRecording() { |
| 82 var tracingStoppedPromises = []; | 80 var tracingStoppedPromises = []; |
| 83 tracingStoppedPromises.push(new Promise(resolve => this._tracingCompleteCall
back = resolve)); | 81 tracingStoppedPromises.push(new Promise(resolve => this._tracingCompleteCall
back = resolve)); |
| 84 tracingStoppedPromises.push(this._stopProfilingOnAllTargets()); | 82 tracingStoppedPromises.push(this._stopProfilingOnAllModels()); |
| 85 this._target.tracingManager.stop(); | 83 this._target.tracingManager.stop(); |
| 86 tracingStoppedPromises.push(SDK.targetManager.resumeAllTargets()); | 84 tracingStoppedPromises.push(SDK.targetManager.resumeAllTargets()); |
| 87 | 85 |
| 88 this._client.loadingStarted(); | 86 this._client.loadingStarted(); |
| 89 | 87 |
| 90 var extensionCompletionPromises = this._extensionSessions.map(session => ses
sion.stop()); | 88 var extensionCompletionPromises = this._extensionSessions.map(session => ses
sion.stop()); |
| 91 if (extensionCompletionPromises.length) { | 89 if (extensionCompletionPromises.length) { |
| 92 var timerId; | 90 var timerId; |
| 93 var timeoutPromise = new Promise(fulfill => timerId = setTimeout(fulfill,
5000)); | 91 var timeoutPromise = new Promise(fulfill => timerId = setTimeout(fulfill,
5000)); |
| 94 tracingStoppedPromises.push( | 92 tracingStoppedPromises.push( |
| 95 Promise.race([Promise.all(extensionCompletionPromises).then(() => clea
rTimeout(timerId)), timeoutPromise])); | 93 Promise.race([Promise.all(extensionCompletionPromises).then(() => clea
rTimeout(timerId)), timeoutPromise])); |
| 96 } | 94 } |
| 97 Promise.all(tracingStoppedPromises).then(() => this._allSourcesFinished()); | 95 Promise.all(tracingStoppedPromises).then(() => this._allSourcesFinished()); |
| 98 } | 96 } |
| 99 | 97 |
| 100 /** | 98 /** |
| 101 * @override | 99 * @override |
| 102 * @param {!SDK.Target} target | 100 * @param {!SDK.CPUProfilerModel} cpuProfilerModel |
| 103 */ | 101 */ |
| 104 targetAdded(target) { | 102 modelAdded(cpuProfilerModel) { |
| 105 this._targets.push(target); | |
| 106 if (this._profiling) | 103 if (this._profiling) |
| 107 this._startProfilingOnTarget(target); | 104 cpuProfilerModel.startRecording(); |
| 108 } | 105 } |
| 109 | 106 |
| 110 /** | 107 /** |
| 111 * @override | 108 * @override |
| 112 * @param {!SDK.Target} target | 109 * @param {!SDK.CPUProfilerModel} cpuProfilerModel |
| 113 */ | 110 */ |
| 114 targetRemoved(target) { | 111 modelRemoved(cpuProfilerModel) { |
| 115 this._targets.remove(target, true); | |
| 116 // FIXME: We'd like to stop profiling on the target and retrieve a profile | 112 // FIXME: We'd like to stop profiling on the target and retrieve a profile |
| 117 // but it's too late. Backend connection is closed. | 113 // but it's too late. Backend connection is closed. |
| 118 } | 114 } |
| 119 | 115 |
| 120 /** | 116 /** |
| 121 * @param {!SDK.Target} target | |
| 122 * @return {!Promise} | 117 * @return {!Promise} |
| 123 */ | 118 */ |
| 124 _startProfilingOnTarget(target) { | 119 _startProfilingOnAllModels() { |
| 125 return target.hasJSCapability() ? target.profilerAgent().start() : Promise.r
esolve(); | |
| 126 } | |
| 127 | |
| 128 /** | |
| 129 * @return {!Promise} | |
| 130 */ | |
| 131 _startProfilingOnAllTargets() { | |
| 132 var intervalUs = Common.moduleSetting('highResolutionCpuProfiling').get() ?
100 : 1000; | |
| 133 this._target.profilerAgent().setSamplingInterval(intervalUs); | |
| 134 this._profiling = true; | 120 this._profiling = true; |
| 135 return Promise.all(this._targets.map(this._startProfilingOnTarget)); | 121 var models = SDK.targetManager.models(SDK.CPUProfilerModel); |
| 136 } | 122 return Promise.all(models.map(model => model.startRecording())); |
| 137 | |
| 138 /** | |
| 139 * @param {!SDK.Target} target | |
| 140 * @return {!Promise} | |
| 141 */ | |
| 142 _stopProfilingOnTarget(target) { | |
| 143 return target.hasJSCapability() ? target.profilerAgent().stop(this._addCpuPr
ofile.bind(this, target.id())) : | |
| 144 Promise.resolve(); | |
| 145 } | 123 } |
| 146 | 124 |
| 147 /** | 125 /** |
| 148 * @param {string} targetId | 126 * @param {string} targetId |
| 149 * @param {?Protocol.Error} error | |
| 150 * @param {?Protocol.Profiler.Profile} cpuProfile | 127 * @param {?Protocol.Profiler.Profile} cpuProfile |
| 151 */ | 128 */ |
| 152 _addCpuProfile(targetId, error, cpuProfile) { | 129 _addCpuProfile(targetId, cpuProfile) { |
| 153 if (!cpuProfile) { | 130 if (!cpuProfile) { |
| 154 Common.console.warn(Common.UIString('CPU profile for a target is not avail
able. %s', error || '')); | 131 Common.console.warn(Common.UIString('CPU profile for a target is not avail
able.')); |
| 155 return; | 132 return; |
| 156 } | 133 } |
| 157 if (!this._cpuProfiles) | 134 if (!this._cpuProfiles) |
| 158 this._cpuProfiles = new Map(); | 135 this._cpuProfiles = new Map(); |
| 159 this._cpuProfiles.set(targetId, cpuProfile); | 136 this._cpuProfiles.set(targetId, cpuProfile); |
| 160 } | 137 } |
| 161 | 138 |
| 162 /** | 139 /** |
| 163 * @return {!Promise} | 140 * @return {!Promise} |
| 164 */ | 141 */ |
| 165 _stopProfilingOnAllTargets() { | 142 _stopProfilingOnAllModels() { |
| 166 var targets = this._profiling ? this._targets : []; | 143 var models = this._profiling ? SDK.targetManager.models(SDK.CPUProfilerModel
) : []; |
| 167 this._profiling = false; | 144 this._profiling = false; |
| 168 return Promise.all(targets.map(this._stopProfilingOnTarget, this)); | 145 var promises = []; |
| 146 for (var model of models) { |
| 147 var targetId = model.target().id(); |
| 148 var modelPromise = model.stopRecording().then(this._addCpuProfile.bind(thi
s, targetId)); |
| 149 promises.push(modelPromise); |
| 150 } |
| 151 return Promise.all(promises); |
| 169 } | 152 } |
| 170 | 153 |
| 171 /** | 154 /** |
| 172 * @param {string} categories | 155 * @param {string} categories |
| 173 * @param {boolean=} enableJSSampling | 156 * @param {boolean=} enableJSSampling |
| 174 * @return {!Promise} | 157 * @return {!Promise} |
| 175 */ | 158 */ |
| 176 _startRecordingWithCategories(categories, enableJSSampling) { | 159 _startRecordingWithCategories(categories, enableJSSampling) { |
| 177 SDK.targetManager.suspendAllTargets(); | 160 SDK.targetManager.suspendAllTargets(); |
| 178 var profilingStartedPromise = enableJSSampling && !Runtime.experiments.isEna
bled('timelineTracingJSProfile') ? | 161 var profilingStartedPromise = enableJSSampling && !Runtime.experiments.isEna
bled('timelineTracingJSProfile') ? |
| 179 this._startProfilingOnAllTargets() : | 162 this._startProfilingOnAllModels() : |
| 180 Promise.resolve(); | 163 Promise.resolve(); |
| 181 var samplingFrequencyHz = Common.moduleSetting('highResolutionCpuProfiling')
.get() ? 10000 : 1000; | 164 var samplingFrequencyHz = Common.moduleSetting('highResolutionCpuProfiling')
.get() ? 10000 : 1000; |
| 182 var options = 'sampling-frequency=' + samplingFrequencyHz; | 165 var options = 'sampling-frequency=' + samplingFrequencyHz; |
| 183 var tracingManager = this._target.tracingManager; | 166 var tracingManager = this._target.tracingManager; |
| 184 return profilingStartedPromise.then(() => tracingManager.start(this, categor
ies, options)); | 167 return profilingStartedPromise.then(() => tracingManager.start(this, categor
ies, options)); |
| 185 } | 168 } |
| 186 | 169 |
| 187 /** | 170 /** |
| 188 * @param {!Array.<!SDK.TracingManager.EventPayload>} events | 171 * @param {!Array.<!SDK.TracingManager.EventPayload>} events |
| 189 * @override | 172 * @override |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 }; | 273 }; |
| 291 | 274 |
| 292 /** | 275 /** |
| 293 * @typedef {!{ | 276 * @typedef {!{ |
| 294 * enableJSSampling: (boolean|undefined), | 277 * enableJSSampling: (boolean|undefined), |
| 295 * capturePictures: (boolean|undefined), | 278 * capturePictures: (boolean|undefined), |
| 296 * captureFilmStrip: (boolean|undefined) | 279 * captureFilmStrip: (boolean|undefined) |
| 297 * }} | 280 * }} |
| 298 */ | 281 */ |
| 299 Timeline.TimelineController.RecordingOptions; | 282 Timeline.TimelineController.RecordingOptions; |
| OLD | NEW |