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 |