Chromium Code Reviews| 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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 132 return "disabled-by-default-" + category; | 132 return "disabled-by-default-" + category; |
| 133 } | 133 } |
| 134 var categoriesArray = [ | 134 var categoriesArray = [ |
| 135 "-*", | 135 "-*", |
| 136 disabledByDefault("devtools.timeline"), | 136 disabledByDefault("devtools.timeline"), |
| 137 disabledByDefault("devtools.timeline.frame"), | 137 disabledByDefault("devtools.timeline.frame"), |
| 138 WebInspector.TracingModel.ConsoleEventCategory | 138 WebInspector.TracingModel.ConsoleEventCategory |
| 139 ]; | 139 ]; |
| 140 if (captureStacks) { | 140 if (captureStacks) { |
| 141 categoriesArray.push(disabledByDefault("devtools.timeline.stack")); | 141 categoriesArray.push(disabledByDefault("devtools.timeline.stack")); |
| 142 if (Runtime.experiments.isEnabled("timelineJSCPUProfile")) { | 142 if (Runtime.experiments.isEnabled("timelineJSCPUProfile")) |
| 143 this._jsProfilerStarted = true; | 143 this._startCpuProfilingOnAllTargets(); |
| 144 this._currentTarget = WebInspector.context.flavor(WebInspector.T arget); | |
| 145 this._configureCpuProfilerSamplingInterval(); | |
| 146 this._currentTarget.profilerAgent().start(); | |
| 147 } | |
| 148 } | 144 } |
| 149 if (capturePictures) { | 145 if (capturePictures) { |
| 150 categoriesArray = categoriesArray.concat([ | 146 categoriesArray = categoriesArray.concat([ |
| 151 disabledByDefault("devtools.timeline.layers"), | 147 disabledByDefault("devtools.timeline.layers"), |
| 152 disabledByDefault("devtools.timeline.picture"), | 148 disabledByDefault("devtools.timeline.picture"), |
| 153 disabledByDefault("blink.graphics_context_annotations")]); | 149 disabledByDefault("blink.graphics_context_annotations")]); |
| 154 } | 150 } |
| 155 var categories = categoriesArray.join(","); | 151 var categories = categoriesArray.join(","); |
| 156 this._startRecordingWithCategories(categories); | 152 this._startRecordingWithCategories(categories); |
| 157 }, | 153 }, |
| 158 | 154 |
| 159 stopRecording: function() | 155 stopRecording: function() |
| 160 { | 156 { |
| 161 if (this._jsProfilerStarted) { | 157 this._stopCallbackBarrier = new CallbackBarrier(); |
| 162 this._stopCallbackBarrier = new CallbackBarrier(); | 158 this._stopProfilingOnAllTargets(); |
| 163 this._currentTarget.profilerAgent().stop(this._stopCallbackBarrier.c reateCallback(this._didStopRecordingJSSamples.bind(this))); | |
| 164 this._jsProfilerStarted = false; | |
| 165 } | |
| 166 this._tracingManager.stop(); | 159 this._tracingManager.stop(); |
| 167 }, | 160 }, |
| 168 | 161 |
| 169 /** | 162 /** |
| 170 * @param {!Array.<!WebInspector.TracingManager.EventPayload>} events | 163 * @param {!Array.<!WebInspector.TracingManager.EventPayload>} events |
| 171 */ | 164 */ |
| 172 setEventsForTest: function(events) | 165 setEventsForTest: function(events) |
| 173 { | 166 { |
| 174 this._onTracingStarted(); | 167 this._onTracingStarted(); |
| 175 this._tracingModel.addEvents(events); | 168 this._tracingModel.addEvents(events); |
| 176 this._onTracingComplete(); | 169 this._onTracingComplete(); |
| 177 }, | 170 }, |
| 178 | 171 |
| 179 _configureCpuProfilerSamplingInterval: function() | 172 _startCpuProfilingOnAllTargets: function() |
| 173 { | |
| 174 this._profilingTargets = WebInspector.targetManager.targets(); | |
| 175 for (var i = 0; i < this._profilingTargets.length; ++i) { | |
| 176 var target = this._profilingTargets[i]; | |
| 177 this._configureCpuProfilerSamplingInterval(target); | |
|
loislo
2014/10/10 17:13:08
what would happen when we start another worker jus
alph
2014/11/11 10:18:07
I plan to address this usecase in a separate patch
| |
| 178 target.profilerAgent().start(); | |
| 179 } | |
| 180 }, | |
| 181 | |
| 182 _stopProfilingOnAllTargets: function() | |
| 183 { | |
| 184 if (!this._profilingTargets) | |
| 185 return; | |
| 186 for (var i = 0; i < this._profilingTargets.length; ++i) { | |
| 187 var target = this._profilingTargets[i]; | |
| 188 target.profilerAgent().stop(this._stopCallbackBarrier.createCallback (this._didStopRecordingJSSamples.bind(this, target))); | |
| 189 } | |
| 190 this._profilingTargets = null; | |
| 191 }, | |
| 192 | |
| 193 /** | |
| 194 * @param {!WebInspector.Target} target | |
| 195 */ | |
| 196 _configureCpuProfilerSamplingInterval: function(target) | |
| 180 { | 197 { |
| 181 var intervalUs = WebInspector.settings.highResolutionCpuProfiling.get() ? 100 : 1000; | 198 var intervalUs = WebInspector.settings.highResolutionCpuProfiling.get() ? 100 : 1000; |
| 182 this._currentTarget.profilerAgent().setSamplingInterval(intervalUs, didC hangeInterval); | 199 target.profilerAgent().setSamplingInterval(intervalUs, didChangeInterval ); |
| 183 | 200 |
| 184 function didChangeInterval(error) | 201 function didChangeInterval(error) |
| 185 { | 202 { |
| 186 if (error) | 203 if (error) |
| 187 WebInspector.console.error(error); | 204 WebInspector.console.error(error); |
| 188 } | 205 } |
| 189 }, | 206 }, |
| 190 | 207 |
| 191 /** | 208 /** |
| 192 * @param {string} categories | 209 * @param {string} categories |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 207 * @param {!WebInspector.Event} event | 224 * @param {!WebInspector.Event} event |
| 208 */ | 225 */ |
| 209 _onEventsCollected: function(event) | 226 _onEventsCollected: function(event) |
| 210 { | 227 { |
| 211 var traceEvents = /** @type {!Array.<!WebInspector.TracingManager.EventP ayload>} */ (event.data); | 228 var traceEvents = /** @type {!Array.<!WebInspector.TracingManager.EventP ayload>} */ (event.data); |
| 212 this._tracingModel.addEvents(traceEvents); | 229 this._tracingModel.addEvents(traceEvents); |
| 213 }, | 230 }, |
| 214 | 231 |
| 215 _onTracingComplete: function() | 232 _onTracingComplete: function() |
| 216 { | 233 { |
| 217 if (this._stopCallbackBarrier) | 234 if (this._stopCallbackBarrier) { |
|
loislo
2014/10/10 17:13:08
As far as I see we always have _stopCallbackBarrie
alph
2014/11/11 10:18:07
No. Tests do not call stopRecording. They use setE
| |
| 218 this._stopCallbackBarrier.callWhenDone(this._didStopRecordingTraceEv ents.bind(this)); | 235 this._stopCallbackBarrier.callWhenDone(this._didStopRecordingTraceEv ents.bind(this)); |
| 219 else | 236 this._stopCallbackBarrier = null; |
| 237 } else { | |
| 220 this._didStopRecordingTraceEvents(); | 238 this._didStopRecordingTraceEvents(); |
| 239 } | |
| 221 }, | 240 }, |
| 222 | 241 |
| 223 /** | 242 /** |
| 243 * @param {!WebInspector.Target} target | |
| 224 * @param {?Protocol.Error} error | 244 * @param {?Protocol.Error} error |
| 225 * @param {?ProfilerAgent.CPUProfile} cpuProfile | 245 * @param {?ProfilerAgent.CPUProfile} cpuProfile |
| 226 */ | 246 */ |
| 227 _didStopRecordingJSSamples: function(error, cpuProfile) | 247 _didStopRecordingJSSamples: function(target, error, cpuProfile) |
| 228 { | 248 { |
| 229 if (error) | 249 if (error) |
| 230 WebInspector.console.error(error); | 250 WebInspector.console.error(error); |
| 231 this._recordedCpuProfile = cpuProfile; | 251 if (!this._cpuProfiles) |
| 252 this._cpuProfiles = {}; | |
| 253 this._cpuProfiles[target.id()] = cpuProfile; | |
| 232 }, | 254 }, |
| 233 | 255 |
| 234 _didStopRecordingTraceEvents: function() | 256 _didStopRecordingTraceEvents: function() |
| 235 { | 257 { |
| 236 this._stopCallbackBarrier = null; | |
| 237 | |
| 238 if (this._recordedCpuProfile) { | |
| 239 this._injectCpuProfileEvent(this._recordedCpuProfile); | |
| 240 this._recordedCpuProfile = null; | |
| 241 } | |
| 242 this._tracingModel.tracingComplete(); | 258 this._tracingModel.tracingComplete(); |
| 243 | 259 |
| 244 var events = this._tracingModel.devtoolsPageMetadataEvents(); | 260 var events = this._tracingModel.devtoolsPageMetadataEvents(); |
| 245 var workerMetadataEvents = this._tracingModel.devtoolsWorkerMetadataEven ts(); | 261 var workerMetadataEvents = this._tracingModel.devtoolsWorkerMetadataEven ts(); |
| 246 | 262 |
| 247 this._resetProcessingState(); | 263 this._resetProcessingState(); |
| 248 for (var i = 0, length = events.length; i < length; i++) { | 264 for (var i = 0, length = events.length; i < length; i++) { |
| 249 var event = events[i]; | 265 var event = events[i]; |
| 250 var process = event.thread.process(); | 266 var process = event.thread.process(); |
| 251 var startTime = event.startTime; | 267 var startTime = event.startTime; |
| 252 | 268 |
| 253 var endTime = Infinity; | 269 var endTime = Infinity; |
| 254 if (i + 1 < length) | 270 if (i + 1 < length) |
| 255 endTime = events[i + 1].startTime; | 271 endTime = events[i + 1].startTime; |
| 256 | 272 |
| 257 var threads = process.sortedThreads(); | 273 var threads = process.sortedThreads(); |
| 258 for (var j = 0; j < threads.length; j++) { | 274 for (var j = 0; j < threads.length; j++) { |
| 259 var thread = threads[j]; | 275 var thread = threads[j]; |
| 260 if (thread.name() === "WebCore: Worker" && !workerMetadataEvents .some(function(e) { return e.args["data"]["workerThreadId"] === thread.id(); })) | 276 if (thread.name() === "WebCore: Worker" && workerMetadataEvents. every(function(e) { return e.args["data"]["workerThreadId"] !== thread.id(); })) |
| 261 continue; | 277 continue; |
| 262 this._processThreadEvents(startTime, endTime, event.thread, thre ad); | 278 this._processThreadEvents(startTime, endTime, event.thread, thre ad); |
| 263 } | 279 } |
| 264 } | 280 } |
| 265 this._resetProcessingState(); | 281 this._resetProcessingState(); |
| 266 | 282 |
| 267 this._inspectedTargetEvents.sort(WebInspector.TracingModel.Event.compare StartTime); | 283 this._inspectedTargetEvents.sort(WebInspector.TracingModel.Event.compare StartTime); |
| 268 | 284 |
| 269 if (this._cpuProfile) { | 285 this._cpuProfiles = null; |
| 270 this._processCpuProfile(this._cpuProfile); | 286 |
| 271 this._cpuProfile = null; | |
| 272 } | |
| 273 this._buildTimelineRecords(); | 287 this._buildTimelineRecords(); |
| 274 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin gStopped); | 288 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin gStopped); |
| 275 }, | 289 }, |
| 276 | 290 |
| 277 /** | 291 /** |
| 278 * @param {!ProfilerAgent.CPUProfile} cpuProfile | 292 * @param {!ProfilerAgent.CPUProfile} cpuProfile |
| 279 */ | 293 */ |
| 280 _injectCpuProfileEvent: function(cpuProfile) | 294 _injectCpuProfileEvent: function(cpuProfile) |
| 281 { | 295 { |
| 282 var metaEvent = this._tracingModel.devtoolsPageMetadataEvents().peekLast (); | 296 var metaEvent = this._tracingModel.devtoolsPageMetadataEvents().peekLast (); |
| 283 if (!metaEvent) | 297 if (!metaEvent) |
| 284 return; | 298 return; |
| 285 var cpuProfileEvent = /** @type {!WebInspector.TracingManager.EventPaylo ad} */ ({ | 299 var cpuProfileEvent = /** @type {!WebInspector.TracingManager.EventPaylo ad} */ ({ |
| 286 cat: WebInspector.TracingModel.DevToolsMetadataEventCategory, | 300 cat: WebInspector.TracingModel.DevToolsMetadataEventCategory, |
| 287 ph: WebInspector.TracingModel.Phase.Instant, | 301 ph: WebInspector.TracingModel.Phase.Instant, |
| 288 ts: this._tracingModel.maximumRecordTime() * 1000, | 302 ts: this._tracingModel.maximumRecordTime() * 1000, |
| 289 pid: metaEvent.thread.process().id(), | 303 pid: metaEvent.thread.process().id(), |
| 290 tid: metaEvent.thread.id(), | 304 tid: metaEvent.thread.id(), |
| 291 name: WebInspector.TracingTimelineModel.RecordType.CpuProfile, | 305 name: WebInspector.TracingTimelineModel.RecordType.CpuProfile, |
| 292 args: { data: { cpuProfile: cpuProfile } } | 306 args: { data: { cpuProfile: cpuProfile } } |
| 293 }); | 307 }); |
| 294 this._tracingModel.addEvents([cpuProfileEvent]); | 308 this._tracingModel.addEvents([cpuProfileEvent]); |
| 295 }, | 309 }, |
| 296 | 310 |
| 297 /** | 311 /** |
| 298 * @param {!ProfilerAgent.CPUProfile} cpuProfile | |
| 299 */ | |
| 300 _processCpuProfile: function(cpuProfile) | |
| 301 { | |
| 302 var jsSamples = WebInspector.TimelineJSProfileProcessor.generateTracingE ventsFromCpuProfile(this, cpuProfile); | |
| 303 this._inspectedTargetEvents = this._inspectedTargetEvents.mergeOrdered(j sSamples, WebInspector.TracingModel.Event.orderedCompareStartTime); | |
| 304 this._setMainThreadEvents(this.mainThreadEvents().mergeOrdered(jsSamples , WebInspector.TracingModel.Event.orderedCompareStartTime)); | |
| 305 }, | |
| 306 | |
| 307 /** | |
| 308 * @return {number} | 312 * @return {number} |
| 309 */ | 313 */ |
| 310 minimumRecordTime: function() | 314 minimumRecordTime: function() |
| 311 { | 315 { |
| 312 return this._tracingModel.minimumRecordTime(); | 316 return this._tracingModel.minimumRecordTime(); |
| 313 }, | 317 }, |
| 314 | 318 |
| 315 /** | 319 /** |
| 316 * @return {number} | 320 * @return {number} |
| 317 */ | 321 */ |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 491 * @param {!WebInspector.TracingModel.Thread} mainThread | 495 * @param {!WebInspector.TracingModel.Thread} mainThread |
| 492 * @param {!WebInspector.TracingModel.Thread} thread | 496 * @param {!WebInspector.TracingModel.Thread} thread |
| 493 */ | 497 */ |
| 494 _processThreadEvents: function(startTime, endTime, mainThread, thread) | 498 _processThreadEvents: function(startTime, endTime, mainThread, thread) |
| 495 { | 499 { |
| 496 var events = thread.events(); | 500 var events = thread.events(); |
| 497 var length = events.length; | 501 var length = events.length; |
| 498 var i = events.lowerBound(startTime, function (time, event) { return tim e - event.startTime }); | 502 var i = events.lowerBound(startTime, function (time, event) { return tim e - event.startTime }); |
| 499 | 503 |
| 500 var threadEvents; | 504 var threadEvents; |
| 505 var virtualThread = null; | |
| 501 if (thread === mainThread) { | 506 if (thread === mainThread) { |
| 502 threadEvents = this._mainThreadEvents; | 507 threadEvents = this._mainThreadEvents; |
| 503 this._mainThreadAsyncEvents = this._mainThreadAsyncEvents.concat(thr ead.asyncEvents()); | 508 this._mainThreadAsyncEvents = this._mainThreadAsyncEvents.concat(thr ead.asyncEvents()); |
| 504 } else { | 509 } else { |
| 505 var virtualThread = new WebInspector.TracingTimelineModel.VirtualThr ead(thread.name()); | 510 virtualThread = new WebInspector.TracingTimelineModel.VirtualThread( thread.name()); |
| 506 threadEvents = virtualThread.events; | 511 threadEvents = virtualThread.events; |
| 507 virtualThread.asyncEvents = virtualThread.asyncEvents.concat(thread. asyncEvents()); | 512 virtualThread.asyncEvents = virtualThread.asyncEvents.concat(thread. asyncEvents()); |
| 508 this._virtualThreads.push(virtualThread); | 513 this._virtualThreads.push(virtualThread); |
| 509 } | 514 } |
| 510 | 515 |
| 511 this._eventStack = []; | 516 this._eventStack = []; |
| 512 for (; i < length; i++) { | 517 for (; i < length; i++) { |
| 513 var event = events[i]; | 518 var event = events[i]; |
| 514 if (endTime && event.startTime >= endTime) | 519 if (endTime && event.startTime >= endTime) |
| 515 break; | 520 break; |
| 516 this._processEvent(event); | 521 this._processEvent(event); |
| 517 threadEvents.push(event); | 522 threadEvents.push(event); |
| 518 this._inspectedTargetEvents.push(event); | 523 this._inspectedTargetEvents.push(event); |
| 519 } | 524 } |
| 525 | |
| 526 if (this._cpuProfiles) { | |
| 527 var cpuProfile = this._cpuProfiles[thread.target().id()]; | |
| 528 if (cpuProfile) { | |
| 529 var jsSamples = WebInspector.TimelineJSProfileProcessor.generate TracingEventsFromCpuProfile(cpuProfile, thread); | |
| 530 var mergedEvents = threadEvents.mergeOrdered(jsSamples, WebInspe ctor.TracingModel.Event.orderedCompareStartTime); | |
| 531 if (virtualThread) | |
| 532 virtualThread.events = mergedEvents; | |
| 533 else | |
| 534 this._mainThreadEvents = mergedEvents; | |
| 535 this._inspectedTargetEvents = this._inspectedTargetEvents.concat (jsSamples); | |
| 536 } | |
| 537 } | |
| 520 }, | 538 }, |
| 521 | 539 |
| 522 /** | 540 /** |
| 523 * @param {!WebInspector.TracingModel.Event} event | 541 * @param {!WebInspector.TracingModel.Event} event |
| 524 */ | 542 */ |
| 525 _processEvent: function(event) | 543 _processEvent: function(event) |
| 526 { | 544 { |
| 527 var recordTypes = WebInspector.TracingTimelineModel.RecordType; | 545 var recordTypes = WebInspector.TracingTimelineModel.RecordType; |
| 528 | 546 |
| 529 var eventStack = this._eventStack; | 547 var eventStack = this._eventStack; |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1096 * @param {!WebInspector.ChunkedReader} reader | 1114 * @param {!WebInspector.ChunkedReader} reader |
| 1097 */ | 1115 */ |
| 1098 onChunkTransferred: function(reader) { }, | 1116 onChunkTransferred: function(reader) { }, |
| 1099 | 1117 |
| 1100 /** | 1118 /** |
| 1101 * @param {!WebInspector.ChunkedReader} reader | 1119 * @param {!WebInspector.ChunkedReader} reader |
| 1102 * @param {!Event} event | 1120 * @param {!Event} event |
| 1103 */ | 1121 */ |
| 1104 onError: function(reader, event) { }, | 1122 onError: function(reader, event) { }, |
| 1105 } | 1123 } |
| OLD | NEW |