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

Side by Side Diff: Source/devtools/front_end/sdk/TracingModel.js

Issue 270553005: Support warning decorations in Timeline flame chart based on trace events (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fixed timeline tests Created 6 years, 7 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
OLDNEW
(Empty)
1 /*
2 * Copyright 2014 The Chromium Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7 /**
8 * @constructor
9 * @extends {WebInspector.Object}
10 */
11 WebInspector.TracingModel = function()
12 {
13 WebInspector.Object.call(this);
14 this.reset();
15 this._active = false;
16 InspectorBackend.registerTracingDispatcher(new WebInspector.TracingDispatche r(this));
17 }
18
19 WebInspector.TracingModel.Events = {
20 "BufferUsage": "BufferUsage"
21 }
22
23 /** @typedef {!{
24 cat: string,
25 pid: number,
26 tid: number,
27 ts: number,
28 ph: string,
29 name: string,
30 args: !Object,
31 dur: number,
32 id: number,
33 s: string
34 }}
35 */
36 WebInspector.TracingModel.EventPayload;
37
38 /**
39 * @enum {string}
40 */
41 WebInspector.TracingModel.Phase = {
42 Begin: "B",
43 End: "E",
44 Complete: "X",
45 Instant: "i",
46 AsyncBegin: "S",
47 AsyncStepInto: "T",
48 AsyncStepPast: "p",
49 AsyncEnd: "F",
50 FlowBegin: "s",
51 FlowStep: "t",
52 FlowEnd: "f",
53 Metadata: "M",
54 Counter: "C",
55 Sample: "P",
56 CreateObject: "N",
57 SnapshotObject: "O",
58 DeleteObject: "D"
59 };
60
61 WebInspector.TracingModel.MetadataEvent = {
62 ProcessSortIndex: "process_sort_index",
63 ProcessName: "process_name",
64 ThreadSortIndex: "thread_sort_index",
65 ThreadName: "thread_name"
66 }
67
68 WebInspector.TracingModel.DevToolsMetadataEventCategory = "disabled-by-default-d evtools.timeline";
69
70 WebInspector.TracingModel.FrameLifecycleEventCategory = "cc,devtools";
71
72 WebInspector.TracingModel.DevToolsMetadataEvent = {
73 TracingStartedInPage: "TracingStartedInPage",
74 SetLayerTreeId: "SetLayerTreeId"
75 };
76
77 WebInspector.TracingModel.TraceEventName = {
78 ActivateLayerTree: "ActivateLayerTree",
79 BeginFrame: "BeginFrame",
80 BeginMainThreadFrame: "BeginMainThreadFrame",
81 CompositeLayers: "CompositeLayers",
82 DrawFrame: "DrawFrame",
83 PaintSetup: "PaintSetup",
84 RasterTask: "RasterTask",
85 RequestMainThreadFrame: "RequestMainThreadFrame"
86 };
87
88 WebInspector.TracingModel.prototype = {
89 /**
90 * @return {!Array.<!WebInspector.TracingModel.Event>}
91 */
92 inspectedTargetMainThreadEvents: function()
93 {
94 return this._inspectedTargetMainThreadEvents;
95 },
96
97 /**
98 * @return {!Array.<!WebInspector.TracingModel.Event>}
99 */
100 frameLifecycleEvents: function()
101 {
102 /**
103 * @param {!WebInspector.TracingModel.Event} a
104 * @param {!WebInspector.TracingModel.Event} b
105 */
106 function compareStartTime(a, b)
107 {
108 return a.startTime - b.startTime;
109 }
110 return this._frameLifecycleEvents.sort(compareStartTime);
111 },
112
113 /**
114 * @param {string} categoryFilter
115 * @param {string} options
116 * @param {function(?string)=} callback
117 */
118 start: function(categoryFilter, options, callback)
119 {
120 this.reset();
121 var bufferUsageReportingIntervalMs = 500;
122 /**
123 * @param {?string} error
124 * @param {string} sessionId
125 * @this {WebInspector.TracingModel}
126 */
127 function callbackWrapper(error, sessionId)
128 {
129 this._sessionId = sessionId;
130 if (callback)
131 callback(error);
132 }
133 TracingAgent.start(categoryFilter, options, bufferUsageReportingInterval Ms, callbackWrapper.bind(this));
134 this._active = true;
135 },
136
137 /**
138 * @param {function()} callback
139 */
140 stop: function(callback)
141 {
142 if (!this._active) {
143 callback();
144 return;
145 }
146 this._pendingStopCallback = callback;
147 TracingAgent.end();
148 },
149
150 /**
151 * @return {?string}
152 */
153 sessionId: function()
154 {
155 return this._sessionId;
156 },
157
158 /**
159 * @param {number} usage
160 */
161 _bufferUsage: function(usage)
162 {
163 this.dispatchEventToListeners(WebInspector.TracingModel.Events.BufferUsa ge, usage);
164 },
165
166 /**
167 * @param {!Array.<!WebInspector.TracingModel.EventPayload>} events
168 */
169 _eventsCollected: function(events)
170 {
171 for (var i = 0; i < events.length; ++i)
172 this._addEvent(events[i]);
173 },
174
175 _tracingComplete: function()
176 {
177 this._active = false;
178 if (!this._pendingStopCallback)
179 return;
180 this._pendingStopCallback();
181 this._pendingStopCallback = null;
182 },
183
184 reset: function()
185 {
186 this._processById = {};
187 this._minimumRecordTime = null;
188 this._maximumRecordTime = null;
189 this._sessionId = null;
190 this._inspectedTargetProcessId = null;
191 this._inspectedTargetMainThread = null;
192 this._inspectedTargetMainThreadEvents = [];
193 this._inspectedTargetLayerTreeHostId = 0;
194 this._frameLifecycleEvents = [];
195 },
196
197 /**
198 * @param {!WebInspector.TracingModel.EventPayload} payload
199 */
200 _addEvent: function(payload)
201 {
202 var process = this._processById[payload.pid];
203 if (!process) {
204 process = new WebInspector.TracingModel.Process(payload.pid);
205 this._processById[payload.pid] = process;
206 }
207 if (payload.ph === WebInspector.TracingModel.Phase.SnapshotObject) {
208 process.addObject(payload);
209 return;
210 }
211 var thread = process.threadById(payload.tid);
212 if (payload.ph !== WebInspector.TracingModel.Phase.Metadata) {
213 var timestamp = payload.ts;
214 // We do allow records for unrelated threads to arrive out-of-order,
215 // so there's a chance we're getting records from the past.
216 if (timestamp && (!this._minimumRecordTime || timestamp < this._mini mumRecordTime))
217 this._minimumRecordTime = timestamp;
218 if (!this._maximumRecordTime || timestamp > this._maximumRecordTime)
219 this._maximumRecordTime = timestamp;
220 if (payload.cat === WebInspector.TracingModel.DevToolsMetadataEventC ategory)
221 this._processDevToolsMetadataEvent(payload);
222 var event = thread.addEvent(payload);
223 if (!event)
224 return;
225 if (thread === this._inspectedTargetMainThread)
226 this._inspectedTargetMainThreadEvents.push(event);
227 if (payload.cat === WebInspector.TracingModel.FrameLifecycleEventCat egory && payload.pid === this._inspectedTargetProcessId &&
228 payload.args && payload.args["layerTreeId"] === this._inspectedT argetLayerTreeId) {
229 this._frameLifecycleEvents.push(event);
230 }
231 return;
232 }
233 switch (payload.name) {
234 case WebInspector.TracingModel.MetadataEvent.ProcessSortIndex:
235 process._setSortIndex(payload.args["sort_index"]);
236 break;
237 case WebInspector.TracingModel.MetadataEvent.ProcessName:
238 process._setName(payload.args["name"]);
239 break;
240 case WebInspector.TracingModel.MetadataEvent.ThreadSortIndex:
241 thread._setSortIndex(payload.args["sort_index"]);
242 break;
243 case WebInspector.TracingModel.MetadataEvent.ThreadName:
244 thread._setName(payload.args["name"]);
245 break;
246 }
247 },
248
249 /**
250 * @param {!WebInspector.TracingModel.EventPayload} payload
251 */
252 _processDevToolsMetadataEvent: function(payload)
253 {
254 if (payload.args["sessionId"] !== this._sessionId)
255 return;
256 if (payload.name === WebInspector.TracingModel.DevToolsMetadataEvent.Tra cingStartedInPage) {
257 var thread = this._processById[payload.pid].threadById(payload.tid)
258 this._inspectedTargetProcessId = payload.pid;
259 this._inspectedTargetMainThread = thread;
260 this._inspectedTargetMainThreadEvents = this._inspectedTargetMainThr eadEvents.concat(thread.events());
261 } else if (payload.name === WebInspector.TracingModel.DevToolsMetadataEv ent.SetLayerTreeId) {
262 this._inspectedTargetLayerTreeId = payload.args["layerTreeId"];
263 }
264 },
265
266 /**
267 * @return {?number}
268 */
269 minimumRecordTime: function()
270 {
271 return this._minimumRecordTime;
272 },
273
274 /**
275 * @return {?number}
276 */
277 maximumRecordTime: function()
278 {
279 return this._maximumRecordTime;
280 },
281
282 /**
283 * @return {!Array.<!WebInspector.TracingModel.Process>}
284 */
285 sortedProcesses: function()
286 {
287 return WebInspector.TracingModel.NamedObject._sort(Object.values(this._p rocessById));
288 },
289
290 __proto__: WebInspector.Object.prototype
291 }
292
293 /**
294 * @constructor
295 * @param {!WebInspector.TracingModel.EventPayload} payload
296 * @param {number} level
297 */
298 WebInspector.TracingModel.Event = function(payload, level)
299 {
300 this.name = payload.name;
301 this.category = payload.cat;
302 this.startTime = payload.ts;
303 this.args = payload.args;
304 this.phase = payload.ph;
305 this.level = level;
306 }
307
308 WebInspector.TracingModel.Event.prototype = {
309 /**
310 * @param {number} duration
311 */
312 _setDuration: function(duration)
313 {
314 this.endTime = this.startTime + duration;
315 this.duration = duration;
316 },
317
318 /**
319 * @param {!WebInspector.TracingModel.EventPayload} payload
320 */
321 _complete: function(payload)
322 {
323 if (this.name !== payload.name) {
324 console.assert(false, "Open/close event mismatch: " + this.name + " vs. " + payload.name);
325 return;
326 }
327 var duration = payload.ts - this.startTime;
328 if (duration < 0) {
329 console.assert(false, "Event out of order: " + this.name);
330 return;
331 }
332 this._setDuration(duration);
333 }
334 }
335
336 /**
337 * @constructor
338 */
339 WebInspector.TracingModel.NamedObject = function()
340 {
341 }
342
343 WebInspector.TracingModel.NamedObject.prototype =
344 {
345 /**
346 * @param {string} name
347 */
348 _setName: function(name)
349 {
350 this._name = name;
351 },
352
353 /**
354 * @return {string}
355 */
356 name: function()
357 {
358 return this._name;
359 },
360
361 /**
362 * @param {number} sortIndex
363 */
364 _setSortIndex: function(sortIndex)
365 {
366 this._sortIndex = sortIndex;
367 },
368 }
369
370 /**
371 * @param {!Array.<!WebInspector.TracingModel.NamedObject>} array
372 */
373 WebInspector.TracingModel.NamedObject._sort = function(array)
374 {
375 /**
376 * @param {!WebInspector.TracingModel.NamedObject} a
377 * @param {!WebInspector.TracingModel.NamedObject} b
378 */
379 function comparator(a, b)
380 {
381 return a._sortIndex !== b._sortIndex ? a._sortIndex - b._sortIndex : a.n ame().localeCompare(b.name());
382 }
383 return array.sort(comparator);
384 }
385
386 /**
387 * @constructor
388 * @extends {WebInspector.TracingModel.NamedObject}
389 * @param {number} id
390 */
391 WebInspector.TracingModel.Process = function(id)
392 {
393 WebInspector.TracingModel.NamedObject.call(this);
394 this._setName("Process " + id);
395 this._threads = {};
396 this._objects = {};
397 }
398
399 WebInspector.TracingModel.Process.prototype = {
400 /**
401 * @param {number} id
402 * @return {!WebInspector.TracingModel.Thread}
403 */
404 threadById: function(id)
405 {
406 var thread = this._threads[id];
407 if (!thread) {
408 thread = new WebInspector.TracingModel.Thread(id);
409 this._threads[id] = thread;
410 }
411 return thread;
412 },
413
414 /**
415 * @param {!WebInspector.TracingModel.EventPayload} event
416 */
417 addObject: function(event)
418 {
419 this.objectsByName(event.name).push(new WebInspector.TracingModel.Event( event, 0));
420 },
421
422 /**
423 * @param {string} name
424 * @return {!Array.<!WebInspector.TracingModel.Event>}
425 */
426 objectsByName: function(name)
427 {
428 var objects = this._objects[name];
429 if (!objects) {
430 objects = [];
431 this._objects[name] = objects;
432 }
433 return objects;
434 },
435
436 /**
437 * @return {!Array.<string>}
438 */
439 sortedObjectNames: function()
440 {
441 return Object.keys(this._objects).sort();
442 },
443
444 /**
445 * @return {!Array.<!WebInspector.TracingModel.Thread>}
446 */
447 sortedThreads: function()
448 {
449 return WebInspector.TracingModel.NamedObject._sort(Object.values(this._t hreads));
450 },
451
452 __proto__: WebInspector.TracingModel.NamedObject.prototype
453 }
454
455 /**
456 * @constructor
457 * @extends {WebInspector.TracingModel.NamedObject}
458 * @param {number} id
459 */
460 WebInspector.TracingModel.Thread = function(id)
461 {
462 WebInspector.TracingModel.NamedObject.call(this);
463 this._setName("Thread " + id);
464 this._events = [];
465 this._stack = [];
466 this._maxStackDepth = 0;
467 }
468
469 WebInspector.TracingModel.Thread.prototype = {
470 /**
471 * @param {!WebInspector.TracingModel.EventPayload} payload
472 * @return {?WebInspector.TracingModel.Event} event
473 */
474 addEvent: function(payload)
475 {
476 for (var top = this._stack.peekLast(); top && top.endTime && top.endTime <= payload.ts;) {
477 this._stack.pop();
478 top = this._stack.peekLast();
479 }
480 if (payload.ph === WebInspector.TracingModel.Phase.End) {
481 var openEvent = this._stack.pop();
482 // Quietly ignore unbalanced close events, they're legit (we could h ave missed start one).
483 if (openEvent)
484 openEvent._complete(payload);
485 return null;
486 }
487
488 var event = new WebInspector.TracingModel.Event(payload, this._stack.len gth);
489 if (payload.ph === WebInspector.TracingModel.Phase.Begin || payload.ph = == WebInspector.TracingModel.Phase.Complete) {
490 if (payload.ph === WebInspector.TracingModel.Phase.Complete)
491 event._setDuration(payload.dur);
492 this._stack.push(event);
493 if (this._maxStackDepth < this._stack.length)
494 this._maxStackDepth = this._stack.length;
495 }
496 if (this._events.length && this._events.peekLast().startTime > event.sta rtTime)
497 console.assert(false, "Event is our of order: " + event.name);
498 this._events.push(event);
499 return event;
500 },
501
502 /**
503 * @return {!Array.<!WebInspector.TracingModel.Event>}
504 */
505 events: function()
506 {
507 return this._events;
508 },
509
510 /**
511 * @return {number}
512 */
513 maxStackDepth: function()
514 {
515 // Reserve one for non-container events.
516 return this._maxStackDepth + 1;
517 },
518
519 __proto__: WebInspector.TracingModel.NamedObject.prototype
520 }
521
522
523 /**
524 * @constructor
525 * @implements {TracingAgent.Dispatcher}
526 * @param {!WebInspector.TracingModel} tracingModel
527 */
528 WebInspector.TracingDispatcher = function(tracingModel)
529 {
530 this._tracingModel = tracingModel;
531 }
532
533 WebInspector.TracingDispatcher.prototype = {
534 /**
535 * @param {number} usage
536 */
537 bufferUsage: function(usage)
538 {
539 this._tracingModel._bufferUsage(usage);
540 },
541
542 /**
543 * @param {!Array.<!WebInspector.TracingModel.EventPayload>} data
544 */
545 dataCollected: function(data)
546 {
547 this._tracingModel._eventsCollected(data);
548 },
549
550 tracingComplete: function()
551 {
552 this._tracingModel._tracingComplete();
553 }
554 }
OLDNEW
« no previous file with comments | « Source/devtools/front_end/inspector.html ('k') | Source/devtools/front_end/timeline/TimelineFlameChart.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698