OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 * @constructor | 6 * @constructor |
7 * @param {!WebInspector.TracingManager} tracingManager | 7 * @param {!WebInspector.TracingManager} tracingManager |
8 * @param {!WebInspector.TracingModel} tracingModel | 8 * @param {!WebInspector.TracingModel} tracingModel |
9 * @param {!WebInspector.TimelineModel.Filter} recordFilter | 9 * @param {!WebInspector.TimelineModel.Filter} recordFilter |
10 * @extends {WebInspector.TimelineModel} | 10 * @extends {WebInspector.TimelineModel} |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 return "disabled-by-default-" + category; | 138 return "disabled-by-default-" + category; |
139 } | 139 } |
140 var categoriesArray = [ | 140 var categoriesArray = [ |
141 "-*", | 141 "-*", |
142 disabledByDefault("devtools.timeline"), | 142 disabledByDefault("devtools.timeline"), |
143 disabledByDefault("devtools.timeline.frame"), | 143 disabledByDefault("devtools.timeline.frame"), |
144 WebInspector.TracingModel.ConsoleEventCategory | 144 WebInspector.TracingModel.ConsoleEventCategory |
145 ]; | 145 ]; |
146 if (captureCauses || enableJSSampling) | 146 if (captureCauses || enableJSSampling) |
147 categoriesArray.push(disabledByDefault("devtools.timeline.stack")); | 147 categoriesArray.push(disabledByDefault("devtools.timeline.stack")); |
148 if (enableJSSampling) { | 148 if (enableJSSampling) |
149 this._jsProfilerStarted = true; | 149 this._startCpuProfilingOnAllTargets(); |
150 this._currentTarget = WebInspector.context.flavor(WebInspector.Targe
t); | |
151 this._configureCpuProfilerSamplingInterval(); | |
152 this._currentTarget.profilerAgent().start(); | |
153 } | |
154 if (captureCauses && Runtime.experiments.isEnabled("timelineInvalidation
Tracking")) | 150 if (captureCauses && Runtime.experiments.isEnabled("timelineInvalidation
Tracking")) |
155 categoriesArray.push(disabledByDefault("devtools.timeline.invalidati
onTracking")); | 151 categoriesArray.push(disabledByDefault("devtools.timeline.invalidati
onTracking")); |
156 if (capturePictures) { | 152 if (capturePictures) { |
157 categoriesArray = categoriesArray.concat([ | 153 categoriesArray = categoriesArray.concat([ |
158 disabledByDefault("devtools.timeline.layers"), | 154 disabledByDefault("devtools.timeline.layers"), |
159 disabledByDefault("devtools.timeline.picture"), | 155 disabledByDefault("devtools.timeline.picture"), |
160 disabledByDefault("blink.graphics_context_annotations")]); | 156 disabledByDefault("blink.graphics_context_annotations")]); |
161 } | 157 } |
162 var categories = categoriesArray.join(","); | 158 var categories = categoriesArray.join(","); |
163 this._startRecordingWithCategories(categories); | 159 this._startRecordingWithCategories(categories); |
164 }, | 160 }, |
165 | 161 |
166 stopRecording: function() | 162 stopRecording: function() |
167 { | 163 { |
168 if (this._jsProfilerStarted) { | 164 this._stopCallbackBarrier = new CallbackBarrier(); |
169 this._stopCallbackBarrier = new CallbackBarrier(); | 165 this._stopProfilingOnAllTargets(); |
170 this._currentTarget.profilerAgent().stop(this._stopCallbackBarrier.c
reateCallback(this._didStopRecordingJSSamples.bind(this))); | |
171 this._jsProfilerStarted = false; | |
172 } | |
173 this._tracingManager.stop(); | 166 this._tracingManager.stop(); |
174 }, | 167 }, |
175 | 168 |
176 /** | 169 /** |
177 * @param {!Array.<!WebInspector.TracingManager.EventPayload>} events | 170 * @param {!Array.<!WebInspector.TracingManager.EventPayload>} events |
178 */ | 171 */ |
179 setEventsForTest: function(events) | 172 setEventsForTest: function(events) |
180 { | 173 { |
181 this._startCollectingTraceEvents(false); | 174 this._startCollectingTraceEvents(false); |
182 this._tracingModel.addEvents(events); | 175 this._tracingModel.addEvents(events); |
183 this._onTracingComplete(); | 176 this._onTracingComplete(); |
184 }, | 177 }, |
185 | 178 |
186 _configureCpuProfilerSamplingInterval: function() | 179 _startCpuProfilingOnAllTargets: function() |
| 180 { |
| 181 this._profilingTargets = WebInspector.targetManager.targets(); |
| 182 for (var i = 0; i < this._profilingTargets.length; ++i) { |
| 183 var target = this._profilingTargets[i]; |
| 184 this._configureCpuProfilerSamplingInterval(target); |
| 185 target.profilerAgent().start(); |
| 186 } |
| 187 }, |
| 188 |
| 189 _stopProfilingOnAllTargets: function() |
| 190 { |
| 191 if (!this._profilingTargets) |
| 192 return; |
| 193 for (var i = 0; i < this._profilingTargets.length; ++i) { |
| 194 var target = this._profilingTargets[i]; |
| 195 target.profilerAgent().stop(this._stopCallbackBarrier.createCallback
(this._didStopRecordingJSSamples.bind(this, target))); |
| 196 } |
| 197 this._profilingTargets = null; |
| 198 }, |
| 199 |
| 200 /** |
| 201 * @param {!WebInspector.Target} target |
| 202 */ |
| 203 _configureCpuProfilerSamplingInterval: function(target) |
187 { | 204 { |
188 var intervalUs = WebInspector.settings.highResolutionCpuProfiling.get()
? 100 : 1000; | 205 var intervalUs = WebInspector.settings.highResolutionCpuProfiling.get()
? 100 : 1000; |
189 this._currentTarget.profilerAgent().setSamplingInterval(intervalUs, didC
hangeInterval); | 206 target.profilerAgent().setSamplingInterval(intervalUs, didChangeInterval
); |
190 | 207 |
191 function didChangeInterval(error) | 208 function didChangeInterval(error) |
192 { | 209 { |
193 if (error) | 210 if (error) |
194 WebInspector.console.error(error); | 211 WebInspector.console.error(error); |
195 } | 212 } |
196 }, | 213 }, |
197 | 214 |
198 /** | 215 /** |
199 * @param {string} categories | 216 * @param {string} categories |
(...skipping 22 matching lines...) Expand all Loading... |
222 * @param {!WebInspector.Event} event | 239 * @param {!WebInspector.Event} event |
223 */ | 240 */ |
224 _onEventsCollected: function(event) | 241 _onEventsCollected: function(event) |
225 { | 242 { |
226 var traceEvents = /** @type {!Array.<!WebInspector.TracingManager.EventP
ayload>} */ (event.data); | 243 var traceEvents = /** @type {!Array.<!WebInspector.TracingManager.EventP
ayload>} */ (event.data); |
227 this._tracingModel.addEvents(traceEvents); | 244 this._tracingModel.addEvents(traceEvents); |
228 }, | 245 }, |
229 | 246 |
230 _onTracingComplete: function() | 247 _onTracingComplete: function() |
231 { | 248 { |
232 if (this._stopCallbackBarrier) | 249 if (this._stopCallbackBarrier) { |
233 this._stopCallbackBarrier.callWhenDone(this._didStopRecordingTraceEv
ents.bind(this)); | 250 this._stopCallbackBarrier.callWhenDone(this._didStopRecordingTraceEv
ents.bind(this)); |
234 else | 251 this._stopCallbackBarrier = null; |
| 252 } else { |
235 this._didStopRecordingTraceEvents(); | 253 this._didStopRecordingTraceEvents(); |
| 254 } |
236 }, | 255 }, |
237 | 256 |
238 /** | 257 /** |
| 258 * @param {!WebInspector.Target} target |
239 * @param {?Protocol.Error} error | 259 * @param {?Protocol.Error} error |
240 * @param {?ProfilerAgent.CPUProfile} cpuProfile | 260 * @param {?ProfilerAgent.CPUProfile} cpuProfile |
241 */ | 261 */ |
242 _didStopRecordingJSSamples: function(error, cpuProfile) | 262 _didStopRecordingJSSamples: function(target, error, cpuProfile) |
243 { | 263 { |
244 if (error) | 264 if (error) |
245 WebInspector.console.error(error); | 265 WebInspector.console.error(error); |
246 this._recordedCpuProfile = cpuProfile; | 266 if (!this._cpuProfiles) |
| 267 this._cpuProfiles = {}; |
| 268 this._cpuProfiles[target.id()] = cpuProfile; |
247 }, | 269 }, |
248 | 270 |
249 _didStopRecordingTraceEvents: function() | 271 _didStopRecordingTraceEvents: function() |
250 { | 272 { |
251 this._stopCallbackBarrier = null; | |
252 | |
253 if (this._recordedCpuProfile) { | |
254 this._injectCpuProfileEvent(this._recordedCpuProfile); | |
255 this._recordedCpuProfile = null; | |
256 } | |
257 this._tracingModel.tracingComplete(); | 273 this._tracingModel.tracingComplete(); |
258 | 274 |
259 var events = this._tracingModel.devtoolsPageMetadataEvents(); | 275 var events = this._tracingModel.devtoolsPageMetadataEvents(); |
260 var workerMetadataEvents = this._tracingModel.devtoolsWorkerMetadataEven
ts(); | 276 var workerMetadataEvents = this._tracingModel.devtoolsWorkerMetadataEven
ts(); |
261 | 277 |
262 this._resetProcessingState(); | 278 this._resetProcessingState(); |
263 for (var i = 0, length = events.length; i < length; i++) { | 279 for (var i = 0, length = events.length; i < length; i++) { |
264 var event = events[i]; | 280 var event = events[i]; |
265 var process = event.thread.process(); | 281 var process = event.thread.process(); |
266 var startTime = event.startTime; | 282 var startTime = event.startTime; |
267 | 283 |
268 var endTime = Infinity; | 284 var endTime = Infinity; |
269 if (i + 1 < length) | 285 if (i + 1 < length) |
270 endTime = events[i + 1].startTime; | 286 endTime = events[i + 1].startTime; |
271 | 287 |
272 var threads = process.sortedThreads(); | 288 var threads = process.sortedThreads(); |
273 for (var j = 0; j < threads.length; j++) { | 289 for (var j = 0; j < threads.length; j++) { |
274 var thread = threads[j]; | 290 var thread = threads[j]; |
275 if (thread.name() === "WebCore: Worker" && !workerMetadataEvents
.some(function(e) { return e.args["data"]["workerThreadId"] === thread.id(); })) | 291 if (thread.name() === "WebCore: Worker" && workerMetadataEvents.
every(function(e) { return e.args["data"]["workerThreadId"] !== thread.id(); })) |
276 continue; | 292 continue; |
277 this._processThreadEvents(startTime, endTime, event.thread, thre
ad); | 293 this._processThreadEvents(startTime, endTime, event.thread, thre
ad); |
278 } | 294 } |
279 } | 295 } |
280 this._resetProcessingState(); | 296 this._resetProcessingState(); |
281 | 297 |
282 this._inspectedTargetEvents.sort(WebInspector.TracingModel.Event.compare
StartTime); | 298 this._inspectedTargetEvents.sort(WebInspector.TracingModel.Event.compare
StartTime); |
283 | 299 |
284 if (this._cpuProfile) { | 300 this._cpuProfiles = null; |
285 this._processCpuProfile(this._cpuProfile); | 301 |
286 this._cpuProfile = null; | |
287 } | |
288 this._buildTimelineRecords(); | 302 this._buildTimelineRecords(); |
289 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin
gStopped); | 303 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin
gStopped); |
290 }, | 304 }, |
291 | 305 |
292 /** | 306 /** |
293 * @param {!ProfilerAgent.CPUProfile} cpuProfile | 307 * @param {!ProfilerAgent.CPUProfile} cpuProfile |
294 */ | 308 */ |
295 _injectCpuProfileEvent: function(cpuProfile) | 309 _injectCpuProfileEvent: function(cpuProfile) |
296 { | 310 { |
297 var metaEvent = this._tracingModel.devtoolsPageMetadataEvents().peekLast
(); | 311 var metaEvent = this._tracingModel.devtoolsPageMetadataEvents().peekLast
(); |
298 if (!metaEvent) | 312 if (!metaEvent) |
299 return; | 313 return; |
300 var cpuProfileEvent = /** @type {!WebInspector.TracingManager.EventPaylo
ad} */ ({ | 314 var cpuProfileEvent = /** @type {!WebInspector.TracingManager.EventPaylo
ad} */ ({ |
301 cat: WebInspector.TracingModel.DevToolsMetadataEventCategory, | 315 cat: WebInspector.TracingModel.DevToolsMetadataEventCategory, |
302 ph: WebInspector.TracingModel.Phase.Instant, | 316 ph: WebInspector.TracingModel.Phase.Instant, |
303 ts: this._tracingModel.maximumRecordTime() * 1000, | 317 ts: this._tracingModel.maximumRecordTime() * 1000, |
304 pid: metaEvent.thread.process().id(), | 318 pid: metaEvent.thread.process().id(), |
305 tid: metaEvent.thread.id(), | 319 tid: metaEvent.thread.id(), |
306 name: WebInspector.TracingTimelineModel.RecordType.CpuProfile, | 320 name: WebInspector.TracingTimelineModel.RecordType.CpuProfile, |
307 args: { data: { cpuProfile: cpuProfile } } | 321 args: { data: { cpuProfile: cpuProfile } } |
308 }); | 322 }); |
309 this._tracingModel.addEvents([cpuProfileEvent]); | 323 this._tracingModel.addEvents([cpuProfileEvent]); |
310 }, | 324 }, |
311 | 325 |
312 /** | 326 /** |
313 * @param {!ProfilerAgent.CPUProfile} cpuProfile | |
314 */ | |
315 _processCpuProfile: function(cpuProfile) | |
316 { | |
317 var jsSamples = WebInspector.TimelineJSProfileProcessor.generateTracingE
ventsFromCpuProfile(this, cpuProfile); | |
318 this._inspectedTargetEvents = this._inspectedTargetEvents.mergeOrdered(j
sSamples, WebInspector.TracingModel.Event.orderedCompareStartTime); | |
319 this._setMainThreadEvents(this.mainThreadEvents().mergeOrdered(jsSamples
, WebInspector.TracingModel.Event.orderedCompareStartTime)); | |
320 var jsFrameEvents = WebInspector.TimelineJSProfileProcessor.generateJSFr
ameEvents(this.mainThreadEvents()); | |
321 this._setMainThreadEvents(jsFrameEvents.mergeOrdered(this.mainThreadEven
ts(), WebInspector.TracingModel.Event.orderedCompareStartTime)); | |
322 this._inspectedTargetEvents = jsFrameEvents.mergeOrdered(this._inspected
TargetEvents, WebInspector.TracingModel.Event.orderedCompareStartTime); | |
323 }, | |
324 | |
325 /** | |
326 * @return {number} | 327 * @return {number} |
327 */ | 328 */ |
328 minimumRecordTime: function() | 329 minimumRecordTime: function() |
329 { | 330 { |
330 return this._tracingModel.minimumRecordTime(); | 331 return this._tracingModel.minimumRecordTime(); |
331 }, | 332 }, |
332 | 333 |
333 /** | 334 /** |
334 * @return {number} | 335 * @return {number} |
335 */ | 336 */ |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 * @param {!WebInspector.TracingModel.Thread} mainThread | 505 * @param {!WebInspector.TracingModel.Thread} mainThread |
505 * @param {!WebInspector.TracingModel.Thread} thread | 506 * @param {!WebInspector.TracingModel.Thread} thread |
506 */ | 507 */ |
507 _processThreadEvents: function(startTime, endTime, mainThread, thread) | 508 _processThreadEvents: function(startTime, endTime, mainThread, thread) |
508 { | 509 { |
509 var events = thread.events(); | 510 var events = thread.events(); |
510 var length = events.length; | 511 var length = events.length; |
511 var i = events.lowerBound(startTime, function (time, event) { return tim
e - event.startTime }); | 512 var i = events.lowerBound(startTime, function (time, event) { return tim
e - event.startTime }); |
512 | 513 |
513 var threadEvents; | 514 var threadEvents; |
| 515 var virtualThread = null; |
514 if (thread === mainThread) { | 516 if (thread === mainThread) { |
515 threadEvents = this._mainThreadEvents; | 517 threadEvents = this._mainThreadEvents; |
516 this._mainThreadAsyncEvents = this._mainThreadAsyncEvents.concat(thr
ead.asyncEvents()); | 518 this._mainThreadAsyncEvents = this._mainThreadAsyncEvents.concat(thr
ead.asyncEvents()); |
517 } else { | 519 } else { |
518 var virtualThread = new WebInspector.TracingTimelineModel.VirtualThr
ead(thread.name()); | 520 virtualThread = new WebInspector.TracingTimelineModel.VirtualThread(
thread.name()); |
519 threadEvents = virtualThread.events; | 521 threadEvents = virtualThread.events; |
520 virtualThread.asyncEvents = virtualThread.asyncEvents.concat(thread.
asyncEvents()); | 522 virtualThread.asyncEvents = virtualThread.asyncEvents.concat(thread.
asyncEvents()); |
521 this._virtualThreads.push(virtualThread); | 523 this._virtualThreads.push(virtualThread); |
522 } | 524 } |
523 | 525 |
524 this._eventStack = []; | 526 this._eventStack = []; |
525 for (; i < length; i++) { | 527 for (; i < length; i++) { |
526 var event = events[i]; | 528 var event = events[i]; |
527 if (endTime && event.startTime >= endTime) | 529 if (endTime && event.startTime >= endTime) |
528 break; | 530 break; |
529 this._processEvent(event); | 531 this._processEvent(event); |
530 threadEvents.push(event); | 532 threadEvents.push(event); |
531 this._inspectedTargetEvents.push(event); | 533 this._inspectedTargetEvents.push(event); |
532 } | 534 } |
| 535 |
| 536 if (this._cpuProfiles && thread.target()) { |
| 537 var cpuProfile = this._cpuProfiles[thread.target().id()]; |
| 538 if (cpuProfile) { |
| 539 var jsSamples = WebInspector.TimelineJSProfileProcessor.generate
TracingEventsFromCpuProfile(cpuProfile, thread); |
| 540 var mergedEvents = threadEvents.mergeOrdered(jsSamples, WebInspe
ctor.TracingModel.Event.orderedCompareStartTime); |
| 541 var jsFrameEvents = WebInspector.TimelineJSProfileProcessor.gene
rateJSFrameEvents(mergedEvents); |
| 542 mergedEvents = jsFrameEvents.mergeOrdered(mergedEvents, WebInspe
ctor.TracingModel.Event.orderedCompareStartTime); |
| 543 if (virtualThread) |
| 544 virtualThread.events = mergedEvents; |
| 545 else |
| 546 this._mainThreadEvents = mergedEvents; |
| 547 this._inspectedTargetEvents = this._inspectedTargetEvents.concat
(jsSamples, jsFrameEvents); |
| 548 } |
| 549 } |
533 }, | 550 }, |
534 | 551 |
535 /** | 552 /** |
536 * @param {!WebInspector.TracingModel.Event} event | 553 * @param {!WebInspector.TracingModel.Event} event |
537 */ | 554 */ |
538 _processEvent: function(event) | 555 _processEvent: function(event) |
539 { | 556 { |
540 var recordTypes = WebInspector.TracingTimelineModel.RecordType; | 557 var recordTypes = WebInspector.TracingTimelineModel.RecordType; |
541 | 558 |
542 var eventStack = this._eventStack; | 559 var eventStack = this._eventStack; |
(...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1276 _initializePerFrameState: function() | 1293 _initializePerFrameState: function() |
1277 { | 1294 { |
1278 /** @type {!Array.<!WebInspector.InvalidationTrackingEvent>} */ | 1295 /** @type {!Array.<!WebInspector.InvalidationTrackingEvent>} */ |
1279 this._invalidationEvents = []; | 1296 this._invalidationEvents = []; |
1280 this._lastStyleRecalcEventIndex = 0; | 1297 this._lastStyleRecalcEventIndex = 0; |
1281 this._lastLayoutEventIndex = 0; | 1298 this._lastLayoutEventIndex = 0; |
1282 this._lastPaintWithLayer = undefined; | 1299 this._lastPaintWithLayer = undefined; |
1283 this._didPaint = false; | 1300 this._didPaint = false; |
1284 } | 1301 } |
1285 } | 1302 } |
OLD | NEW |