Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(253)

Side by Side Diff: Source/devtools/front_end/timeline/TracingTimelineModel.js

Issue 622843002: DevTools: Support timeline JS sampling for all threads. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebaseline Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/devtools/front_end/timeline/TimelineJSProfile.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « Source/devtools/front_end/timeline/TimelineJSProfile.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698