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 */ | 34 */ |
37 startRecording(options, providers) { | 35 startRecording(options, providers) { |
38 this._extensionTraceProviders = Extensions.extensionServer.traceProviders().
slice(); | 36 this._extensionTraceProviders = Extensions.extensionServer.traceProviders().
slice(); |
39 | 37 |
40 /** | 38 /** |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 this._extensionSessions = | 70 this._extensionSessions = |
73 providers.map(provider => new Timeline.ExtensionTracingSession(provider,
this._performanceModel)); | 71 providers.map(provider => new Timeline.ExtensionTracingSession(provider,
this._performanceModel)); |
74 this._extensionSessions.forEach(session => session.start()); | 72 this._extensionSessions.forEach(session => session.start()); |
75 this._startRecordingWithCategories(categoriesArray.join(','), options.enable
JSSampling); | 73 this._startRecordingWithCategories(categoriesArray.join(','), options.enable
JSSampling); |
76 this._performanceModel.setRecordStartTime(Date.now()); | 74 this._performanceModel.setRecordStartTime(Date.now()); |
77 } | 75 } |
78 | 76 |
79 stopRecording() { | 77 stopRecording() { |
80 var tracingStoppedPromises = []; | 78 var tracingStoppedPromises = []; |
81 tracingStoppedPromises.push(new Promise(resolve => this._tracingCompleteCall
back = resolve)); | 79 tracingStoppedPromises.push(new Promise(resolve => this._tracingCompleteCall
back = resolve)); |
82 tracingStoppedPromises.push(this._stopProfilingOnAllTargets()); | 80 tracingStoppedPromises.push(this._stopProfilingOnAllModels()); |
83 this._target.tracingManager.stop(); | 81 this._target.tracingManager.stop(); |
84 tracingStoppedPromises.push(SDK.targetManager.resumeAllTargets()); | 82 tracingStoppedPromises.push(SDK.targetManager.resumeAllTargets()); |
85 | 83 |
86 this._client.loadingStarted(); | 84 this._client.loadingStarted(); |
87 | 85 |
88 var extensionCompletionPromises = this._extensionSessions.map(session => ses
sion.stop()); | 86 var extensionCompletionPromises = this._extensionSessions.map(session => ses
sion.stop()); |
89 if (extensionCompletionPromises.length) { | 87 if (extensionCompletionPromises.length) { |
90 var timerId; | 88 var timerId; |
91 var timeoutPromise = new Promise(fulfill => timerId = setTimeout(fulfill,
5000)); | 89 var timeoutPromise = new Promise(fulfill => timerId = setTimeout(fulfill,
5000)); |
92 tracingStoppedPromises.push( | 90 tracingStoppedPromises.push( |
93 Promise.race([Promise.all(extensionCompletionPromises).then(() => clea
rTimeout(timerId)), timeoutPromise])); | 91 Promise.race([Promise.all(extensionCompletionPromises).then(() => clea
rTimeout(timerId)), timeoutPromise])); |
94 } | 92 } |
95 Promise.all(tracingStoppedPromises).then(() => this._allSourcesFinished()); | 93 Promise.all(tracingStoppedPromises).then(() => this._allSourcesFinished()); |
96 } | 94 } |
97 | 95 |
98 /** | 96 /** |
99 * @override | 97 * @override |
100 * @param {!SDK.Target} target | 98 * @param {!SDK.CPUProfilerModel} cpuProfilerModel |
101 */ | 99 */ |
102 targetAdded(target) { | 100 modelAdded(cpuProfilerModel) { |
103 this._targets.push(target); | |
104 if (this._profiling) | 101 if (this._profiling) |
105 this._startProfilingOnTarget(target); | 102 cpuProfilerModel.startRecording(); |
106 } | 103 } |
107 | 104 |
108 /** | 105 /** |
109 * @override | 106 * @override |
110 * @param {!SDK.Target} target | 107 * @param {!SDK.CPUProfilerModel} cpuProfilerModel |
111 */ | 108 */ |
112 targetRemoved(target) { | 109 modelRemoved(cpuProfilerModel) { |
113 this._targets.remove(target, true); | |
114 // FIXME: We'd like to stop profiling on the target and retrieve a profile | 110 // FIXME: We'd like to stop profiling on the target and retrieve a profile |
115 // but it's too late. Backend connection is closed. | 111 // but it's too late. Backend connection is closed. |
116 } | 112 } |
117 | 113 |
118 /** | 114 /** |
119 * @param {!SDK.Target} target | |
120 * @return {!Promise} | 115 * @return {!Promise} |
121 */ | 116 */ |
122 _startProfilingOnTarget(target) { | 117 _startProfilingOnAllModels() { |
123 return target.hasJSCapability() ? target.profilerAgent().start() : Promise.r
esolve(); | |
124 } | |
125 | |
126 /** | |
127 * @return {!Promise} | |
128 */ | |
129 _startProfilingOnAllTargets() { | |
130 var intervalUs = Common.moduleSetting('highResolutionCpuProfiling').get() ?
100 : 1000; | |
131 this._target.profilerAgent().setSamplingInterval(intervalUs); | |
132 this._profiling = true; | 118 this._profiling = true; |
133 return Promise.all(this._targets.map(this._startProfilingOnTarget)); | 119 var models = SDK.targetManager.models(SDK.CPUProfilerModel); |
134 } | 120 return Promise.all(models.map(model => model.startRecording())); |
135 | |
136 /** | |
137 * @param {!SDK.Target} target | |
138 * @return {!Promise} | |
139 */ | |
140 _stopProfilingOnTarget(target) { | |
141 return target.hasJSCapability() ? target.profilerAgent().stop(this._addCpuPr
ofile.bind(this, target.id())) : | |
142 Promise.resolve(); | |
143 } | 121 } |
144 | 122 |
145 /** | 123 /** |
146 * @param {string} targetId | 124 * @param {string} targetId |
147 * @param {?Protocol.Error} error | |
148 * @param {?Protocol.Profiler.Profile} cpuProfile | 125 * @param {?Protocol.Profiler.Profile} cpuProfile |
149 */ | 126 */ |
150 _addCpuProfile(targetId, error, cpuProfile) { | 127 _addCpuProfile(targetId, cpuProfile) { |
151 if (!cpuProfile) { | 128 if (!cpuProfile) { |
152 Common.console.warn(Common.UIString('CPU profile for a target is not avail
able. %s', error || '')); | 129 Common.console.warn(Common.UIString('CPU profile for a target is not avail
able.')); |
153 return; | 130 return; |
154 } | 131 } |
155 if (!this._cpuProfiles) | 132 if (!this._cpuProfiles) |
156 this._cpuProfiles = new Map(); | 133 this._cpuProfiles = new Map(); |
157 this._cpuProfiles.set(targetId, cpuProfile); | 134 this._cpuProfiles.set(targetId, cpuProfile); |
158 } | 135 } |
159 | 136 |
160 /** | 137 /** |
161 * @return {!Promise} | 138 * @return {!Promise} |
162 */ | 139 */ |
163 _stopProfilingOnAllTargets() { | 140 _stopProfilingOnAllModels() { |
164 var targets = this._profiling ? this._targets : []; | 141 var models = this._profiling ? SDK.targetManager.models(SDK.CPUProfilerModel
) : []; |
165 this._profiling = false; | 142 this._profiling = false; |
166 return Promise.all(targets.map(this._stopProfilingOnTarget, this)); | 143 var promises = []; |
| 144 for (var model of models) { |
| 145 var targetId = model.target().id(); |
| 146 var modelPromise = model.stopRecording().then(this._addCpuProfile.bind(thi
s, targetId)); |
| 147 promises.push(modelPromise); |
| 148 } |
| 149 return Promise.all(promises); |
167 } | 150 } |
168 | 151 |
169 /** | 152 /** |
170 * @param {string} categories | 153 * @param {string} categories |
171 * @param {boolean=} enableJSSampling | 154 * @param {boolean=} enableJSSampling |
172 * @param {function(?string)=} callback | 155 * @param {function(?string)=} callback |
173 */ | 156 */ |
174 _startRecordingWithCategories(categories, enableJSSampling, callback) { | 157 _startRecordingWithCategories(categories, enableJSSampling, callback) { |
175 SDK.targetManager.suspendAllTargets(); | 158 SDK.targetManager.suspendAllTargets(); |
176 var profilingStartedPromise = enableJSSampling && !Runtime.experiments.isEna
bled('timelineTracingJSProfile') ? | 159 var profilingStartedPromise = enableJSSampling && !Runtime.experiments.isEna
bled('timelineTracingJSProfile') ? |
177 this._startProfilingOnAllTargets() : | 160 this._startProfilingOnAllModels() : |
178 Promise.resolve(); | 161 Promise.resolve(); |
179 var samplingFrequencyHz = Common.moduleSetting('highResolutionCpuProfiling')
.get() ? 10000 : 1000; | 162 var samplingFrequencyHz = Common.moduleSetting('highResolutionCpuProfiling')
.get() ? 10000 : 1000; |
180 var options = 'sampling-frequency=' + samplingFrequencyHz; | 163 var options = 'sampling-frequency=' + samplingFrequencyHz; |
181 var target = this._target; | 164 var target = this._target; |
182 var tracingManager = target.tracingManager; | 165 var tracingManager = target.tracingManager; |
183 SDK.targetManager.suspendReload(target); | 166 SDK.targetManager.suspendReload(target); |
184 profilingStartedPromise.then(tracingManager.start.bind(tracingManager, this,
categories, options, onTraceStarted)); | 167 profilingStartedPromise.then(tracingManager.start.bind(tracingManager, this,
categories, options, onTraceStarted)); |
185 /** | 168 /** |
186 * @param {?string} error | 169 * @param {?string} error |
187 */ | 170 */ |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 }; | 290 }; |
308 | 291 |
309 /** | 292 /** |
310 * @typedef {!{ | 293 * @typedef {!{ |
311 * enableJSSampling: (boolean|undefined), | 294 * enableJSSampling: (boolean|undefined), |
312 * capturePictures: (boolean|undefined), | 295 * capturePictures: (boolean|undefined), |
313 * captureFilmStrip: (boolean|undefined) | 296 * captureFilmStrip: (boolean|undefined) |
314 * }} | 297 * }} |
315 */ | 298 */ |
316 Timeline.TimelineController.RecordingOptions; | 299 Timeline.TimelineController.RecordingOptions; |
OLD | NEW |