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

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

Issue 276793002: Revert "Support warning decorations in Timeline flame chart based on trace events" (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: upload correct patch thsi time 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._bindings = new WebInspector.TracingModel.EventBindings(this);
178 this._active = false;
179 if (!this._pendingStopCallback)
180 return;
181 this._pendingStopCallback();
182 this._pendingStopCallback = null;
183 },
184
185 /**
186 * @return {!WebInspector.TracingModel.EventBindings}
187 */
188 bindings: function()
189 {
190 return this._bindings;
191 },
192
193 reset: function()
194 {
195 this._processById = {};
196 this._minimumRecordTime = null;
197 this._maximumRecordTime = null;
198 this._sessionId = null;
199 this._inspectedTargetProcessId = null;
200 this._inspectedTargetMainThread = null;
201 this._inspectedTargetMainThreadEvents = [];
202 this._inspectedTargetLayerTreeHostId = 0;
203 this._frameLifecycleEvents = [];
204 this._bindings = null;
205 },
206
207 /**
208 * @param {!WebInspector.TracingModel.EventPayload} payload
209 */
210 _addEvent: function(payload)
211 {
212 var process = this._processById[payload.pid];
213 if (!process) {
214 process = new WebInspector.TracingModel.Process(payload.pid);
215 this._processById[payload.pid] = process;
216 }
217 if (payload.ph === WebInspector.TracingModel.Phase.SnapshotObject) {
218 process.addObject(payload);
219 return;
220 }
221 var thread = process.threadById(payload.tid);
222 if (payload.ph !== WebInspector.TracingModel.Phase.Metadata) {
223 var timestamp = payload.ts;
224 // We do allow records for unrelated threads to arrive out-of-order,
225 // so there's a chance we're getting records from the past.
226 if (timestamp && (!this._minimumRecordTime || timestamp < this._mini mumRecordTime))
227 this._minimumRecordTime = timestamp;
228 if (!this._maximumRecordTime || timestamp > this._maximumRecordTime)
229 this._maximumRecordTime = timestamp;
230 if (payload.cat === WebInspector.TracingModel.DevToolsMetadataEventC ategory)
231 this._processDevToolsMetadataEvent(payload);
232 var event = thread.addEvent(payload);
233 if (!event)
234 return;
235 if (thread === this._inspectedTargetMainThread)
236 this._inspectedTargetMainThreadEvents.push(event);
237 if (payload.cat === WebInspector.TracingModel.FrameLifecycleEventCat egory && payload.pid === this._inspectedTargetProcessId &&
238 payload.args && payload.args["layerTreeId"] === this._inspectedT argetLayerTreeId) {
239 this._frameLifecycleEvents.push(event);
240 }
241 return;
242 }
243 switch (payload.name) {
244 case WebInspector.TracingModel.MetadataEvent.ProcessSortIndex:
245 process._setSortIndex(payload.args["sort_index"]);
246 break;
247 case WebInspector.TracingModel.MetadataEvent.ProcessName:
248 process._setName(payload.args["name"]);
249 break;
250 case WebInspector.TracingModel.MetadataEvent.ThreadSortIndex:
251 thread._setSortIndex(payload.args["sort_index"]);
252 break;
253 case WebInspector.TracingModel.MetadataEvent.ThreadName:
254 thread._setName(payload.args["name"]);
255 break;
256 }
257 },
258
259 /**
260 * @param {!WebInspector.TracingModel.EventPayload} payload
261 */
262 _processDevToolsMetadataEvent: function(payload)
263 {
264 if (payload.args["sessionId"] !== this._sessionId)
265 return;
266 if (payload.name === WebInspector.TracingModel.DevToolsMetadataEvent.Tra cingStartedInPage) {
267 var thread = this._processById[payload.pid].threadById(payload.tid)
268 this._inspectedTargetProcessId = payload.pid;
269 this._inspectedTargetMainThread = thread;
270 this._inspectedTargetMainThreadEvents = this._inspectedTargetMainThr eadEvents.concat(thread.events());
271 } else if (payload.name === WebInspector.TracingModel.DevToolsMetadataEv ent.SetLayerTreeId) {
272 this._inspectedTargetLayerTreeId = payload.args["layerTreeId"];
273 }
274 },
275
276 /**
277 * @return {?number}
278 */
279 minimumRecordTime: function()
280 {
281 return this._minimumRecordTime;
282 },
283
284 /**
285 * @return {?number}
286 */
287 maximumRecordTime: function()
288 {
289 return this._maximumRecordTime;
290 },
291
292 /**
293 * @return {!Array.<!WebInspector.TracingModel.Process>}
294 */
295 sortedProcesses: function()
296 {
297 return WebInspector.TracingModel.NamedObject._sort(Object.values(this._p rocessById));
298 },
299
300 __proto__: WebInspector.Object.prototype
301 }
302
303 /**
304 * @param {!WebInspector.TracingModel} model
305 * @constructor
306 */
307 WebInspector.TracingModel.EventBindings = function(model)
308 {
309 this._eventToWarning = new Map();
310 this._model = model;
311 this._calculateWarnings();
312 }
313
314 WebInspector.TracingModel.EventBindings.prototype = {
315 /**
316 * @param {!WebInspector.TracingModel.Event} event
317 * @return {string|undefined}
318 */
319 eventWarning: function(event)
320 {
321 return this._eventToWarning.get(event);
322 },
323
324 _calculateWarnings: function()
325 {
326 var events = this._model.inspectedTargetMainThreadEvents();
327 var currentScriptEvent = null;
328 for (var i = 0, length = events.length; i < length; i++) {
329 var event = events[i];
330 if (currentScriptEvent && event.startTime > currentScriptEvent.endTi me)
331 currentScriptEvent = null;
332 if (event.name === WebInspector.TimelineModel.RecordType.Layout && c urrentScriptEvent)
333 this._eventToWarning.put(event, WebInspector.UIString("Forced sy nchronous layout is a possible performance bottleneck."));
334 if (!currentScriptEvent && (event.name === WebInspector.TimelineMode l.RecordType.EvaluateScript || event.name === WebInspector.TimelineModel.RecordT ype.FunctionCall))
335 currentScriptEvent = event;
336 }
337 }
338 }
339
340 /**
341 * @constructor
342 * @param {!WebInspector.TracingModel.EventPayload} payload
343 * @param {number} level
344 */
345 WebInspector.TracingModel.Event = function(payload, level)
346 {
347 this.name = payload.name;
348 this.category = payload.cat;
349 this.startTime = payload.ts;
350 this.args = payload.args;
351 this.phase = payload.ph;
352 this.level = level;
353 }
354
355 WebInspector.TracingModel.Event.prototype = {
356 /**
357 * @param {number} duration
358 */
359 _setDuration: function(duration)
360 {
361 this.endTime = this.startTime + duration;
362 this.duration = duration;
363 },
364
365 /**
366 * @param {!WebInspector.TracingModel.EventPayload} payload
367 */
368 _complete: function(payload)
369 {
370 if (this.name !== payload.name) {
371 console.assert(false, "Open/close event mismatch: " + this.name + " vs. " + payload.name);
372 return;
373 }
374 var duration = payload.ts - this.startTime;
375 if (duration < 0) {
376 console.assert(false, "Event out of order: " + this.name);
377 return;
378 }
379 this._setDuration(duration);
380 }
381 }
382
383 /**
384 * @constructor
385 */
386 WebInspector.TracingModel.NamedObject = function()
387 {
388 }
389
390 WebInspector.TracingModel.NamedObject.prototype =
391 {
392 /**
393 * @param {string} name
394 */
395 _setName: function(name)
396 {
397 this._name = name;
398 },
399
400 /**
401 * @return {string}
402 */
403 name: function()
404 {
405 return this._name;
406 },
407
408 /**
409 * @param {number} sortIndex
410 */
411 _setSortIndex: function(sortIndex)
412 {
413 this._sortIndex = sortIndex;
414 },
415 }
416
417 /**
418 * @param {!Array.<!WebInspector.TracingModel.NamedObject>} array
419 */
420 WebInspector.TracingModel.NamedObject._sort = function(array)
421 {
422 /**
423 * @param {!WebInspector.TracingModel.NamedObject} a
424 * @param {!WebInspector.TracingModel.NamedObject} b
425 */
426 function comparator(a, b)
427 {
428 return a._sortIndex !== b._sortIndex ? a._sortIndex - b._sortIndex : a.n ame().localeCompare(b.name());
429 }
430 return array.sort(comparator);
431 }
432
433 /**
434 * @constructor
435 * @extends {WebInspector.TracingModel.NamedObject}
436 * @param {number} id
437 */
438 WebInspector.TracingModel.Process = function(id)
439 {
440 WebInspector.TracingModel.NamedObject.call(this);
441 this._setName("Process " + id);
442 this._threads = {};
443 this._objects = {};
444 }
445
446 WebInspector.TracingModel.Process.prototype = {
447 /**
448 * @param {number} id
449 * @return {!WebInspector.TracingModel.Thread}
450 */
451 threadById: function(id)
452 {
453 var thread = this._threads[id];
454 if (!thread) {
455 thread = new WebInspector.TracingModel.Thread(id);
456 this._threads[id] = thread;
457 }
458 return thread;
459 },
460
461 /**
462 * @param {!WebInspector.TracingModel.EventPayload} event
463 */
464 addObject: function(event)
465 {
466 this.objectsByName(event.name).push(new WebInspector.TracingModel.Event( event, 0));
467 },
468
469 /**
470 * @param {string} name
471 * @return {!Array.<!WebInspector.TracingModel.Event>}
472 */
473 objectsByName: function(name)
474 {
475 var objects = this._objects[name];
476 if (!objects) {
477 objects = [];
478 this._objects[name] = objects;
479 }
480 return objects;
481 },
482
483 /**
484 * @return {!Array.<string>}
485 */
486 sortedObjectNames: function()
487 {
488 return Object.keys(this._objects).sort();
489 },
490
491 /**
492 * @return {!Array.<!WebInspector.TracingModel.Thread>}
493 */
494 sortedThreads: function()
495 {
496 return WebInspector.TracingModel.NamedObject._sort(Object.values(this._t hreads));
497 },
498
499 __proto__: WebInspector.TracingModel.NamedObject.prototype
500 }
501
502 /**
503 * @constructor
504 * @extends {WebInspector.TracingModel.NamedObject}
505 * @param {number} id
506 */
507 WebInspector.TracingModel.Thread = function(id)
508 {
509 WebInspector.TracingModel.NamedObject.call(this);
510 this._setName("Thread " + id);
511 this._events = [];
512 this._stack = [];
513 this._maxStackDepth = 0;
514 }
515
516 WebInspector.TracingModel.Thread.prototype = {
517 /**
518 * @param {!WebInspector.TracingModel.EventPayload} payload
519 * @return {?WebInspector.TracingModel.Event} event
520 */
521 addEvent: function(payload)
522 {
523 for (var top = this._stack.peekLast(); top && top.endTime && top.endTime <= payload.ts;) {
524 this._stack.pop();
525 top = this._stack.peekLast();
526 }
527 if (payload.ph === WebInspector.TracingModel.Phase.End) {
528 var openEvent = this._stack.pop();
529 // Quietly ignore unbalanced close events, they're legit (we could h ave missed start one).
530 if (openEvent)
531 openEvent._complete(payload);
532 return null;
533 }
534
535 var event = new WebInspector.TracingModel.Event(payload, this._stack.len gth);
536 if (payload.ph === WebInspector.TracingModel.Phase.Begin || payload.ph = == WebInspector.TracingModel.Phase.Complete) {
537 if (payload.ph === WebInspector.TracingModel.Phase.Complete)
538 event._setDuration(payload.dur);
539 this._stack.push(event);
540 if (this._maxStackDepth < this._stack.length)
541 this._maxStackDepth = this._stack.length;
542 }
543 if (this._events.length && this._events.peekLast().startTime > event.sta rtTime)
544 console.assert(false, "Event is our of order: " + event.name);
545 this._events.push(event);
546 return event;
547 },
548
549 /**
550 * @return {!Array.<!WebInspector.TracingModel.Event>}
551 */
552 events: function()
553 {
554 return this._events;
555 },
556
557 /**
558 * @return {number}
559 */
560 maxStackDepth: function()
561 {
562 // Reserve one for non-container events.
563 return this._maxStackDepth + 1;
564 },
565
566 __proto__: WebInspector.TracingModel.NamedObject.prototype
567 }
568
569
570 /**
571 * @constructor
572 * @implements {TracingAgent.Dispatcher}
573 * @param {!WebInspector.TracingModel} tracingModel
574 */
575 WebInspector.TracingDispatcher = function(tracingModel)
576 {
577 this._tracingModel = tracingModel;
578 }
579
580 WebInspector.TracingDispatcher.prototype = {
581 /**
582 * @param {number} usage
583 */
584 bufferUsage: function(usage)
585 {
586 this._tracingModel._bufferUsage(usage);
587 },
588
589 /**
590 * @param {!Array.<!WebInspector.TracingModel.EventPayload>} data
591 */
592 dataCollected: function(data)
593 {
594 this._tracingModel._eventsCollected(data);
595 },
596
597 tracingComplete: function()
598 {
599 this._tracingModel._tracingComplete();
600 }
601 }
OLDNEW
« no previous file with comments | « Source/devtools/front_end/timeline/TimelinePanel.js ('k') | Source/devtools/scripts/frontend_modules.json » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698