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

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

Issue 470553002: DevTools: move TracingModel.js into the sdk module. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Review comments addressed. Created 6 years, 4 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.SDKObject}
10 */
11 WebInspector.TracingModel = function(target)
12 {
13 WebInspector.SDKObject.call(this, target);
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 "TracingStarted": "TracingStarted",
22 "TracingStopped": "TracingStopped",
23 "TracingComplete": "TracingComplete"
24 }
25
26 /** @typedef {!{
27 cat: string,
28 pid: number,
29 tid: number,
30 ts: number,
31 ph: string,
32 name: string,
33 args: !Object,
34 dur: number,
35 id: number,
36 s: string
37 }}
38 */
39 WebInspector.TracingModel.EventPayload;
40
41 /**
42 * @enum {string}
43 */
44 WebInspector.TracingModel.Phase = {
45 Begin: "B",
46 End: "E",
47 Complete: "X",
48 Instant: "i",
49 AsyncBegin: "S",
50 AsyncStepInto: "T",
51 AsyncStepPast: "p",
52 AsyncEnd: "F",
53 FlowBegin: "s",
54 FlowStep: "t",
55 FlowEnd: "f",
56 Metadata: "M",
57 Counter: "C",
58 Sample: "P",
59 CreateObject: "N",
60 SnapshotObject: "O",
61 DeleteObject: "D"
62 };
63
64 WebInspector.TracingModel.MetadataEvent = {
65 ProcessSortIndex: "process_sort_index",
66 ProcessName: "process_name",
67 ThreadSortIndex: "thread_sort_index",
68 ThreadName: "thread_name"
69 }
70
71 WebInspector.TracingModel.DevToolsMetadataEventCategory = "disabled-by-default-d evtools.timeline";
72
73 WebInspector.TracingModel.FrameLifecycleEventCategory = "cc,devtools";
74
75 WebInspector.TracingModel.DevToolsMetadataEvent = {
76 TracingStartedInPage: "TracingStartedInPage",
77 TracingStartedInWorker: "TracingStartedInWorker",
78 };
79
80 WebInspector.TracingModel.prototype = {
81 /**
82 * @return {!Array.<!WebInspector.TracingModel.Event>}
83 */
84 devtoolsMetadataEvents: function()
85 {
86 return this._devtoolsMetadataEvents;
87 },
88
89 /**
90 * @param {string} categoryFilter
91 * @param {string} options
92 * @param {function(?string)=} callback
93 */
94 start: function(categoryFilter, options, callback)
95 {
96 this.target().profilingLock.acquire();
97 this.reset();
98 var bufferUsageReportingIntervalMs = 500;
99 TracingAgent.start(categoryFilter, options, bufferUsageReportingInterval Ms, callback);
100 this._active = true;
101 },
102
103 stop: function()
104 {
105 if (!this._active)
106 return;
107 TracingAgent.end(this._onStop.bind(this));
108 this.target().profilingLock.release();
109 },
110
111 /**
112 * @return {?string}
113 */
114 sessionId: function()
115 {
116 return this._sessionId;
117 },
118
119 /**
120 * @param {string} sessionId
121 * @param {!Array.<!WebInspector.TracingModel.EventPayload>} events
122 */
123 setEventsForTest: function(sessionId, events)
124 {
125 this.reset();
126 this._sessionId = sessionId;
127 this._eventsCollected(events);
128 },
129
130 /**
131 * @param {number} usage
132 */
133 _bufferUsage: function(usage)
134 {
135 this.dispatchEventToListeners(WebInspector.TracingModel.Events.BufferUsa ge, usage);
136 },
137
138 /**
139 * @param {!Array.<!WebInspector.TracingModel.EventPayload>} events
140 */
141 _eventsCollected: function(events)
142 {
143 for (var i = 0; i < events.length; ++i) {
144 this._addEvent(events[i]);
145 this._rawEvents.push(events[i]);
146 }
147 },
148
149 _tracingComplete: function()
150 {
151 this._active = false;
152 this.dispatchEventToListeners(WebInspector.TracingModel.Events.TracingCo mplete);
153 },
154
155 /**
156 * @param {string} sessionId
157 */
158 _tracingStarted: function(sessionId)
159 {
160 this.reset();
161 this._active = true;
162 this._sessionId = sessionId;
163 this.dispatchEventToListeners(WebInspector.TracingModel.Events.TracingSt arted);
164 },
165
166 _onStop: function()
167 {
168 this.dispatchEventToListeners(WebInspector.TracingModel.Events.TracingSt opped);
169 this._active = false;
170 },
171
172 reset: function()
173 {
174 this._processById = {};
175 this._minimumRecordTime = 0;
176 this._maximumRecordTime = 0;
177 this._sessionId = null;
178 this._devtoolsMetadataEvents = [];
179 this._rawEvents = [];
180 },
181
182 /**
183 * @return {!Array.<!WebInspector.TracingModel.EventPayload>}
184 */
185 rawEvents: function()
186 {
187 return this._rawEvents;
188 },
189
190 /**
191 * @param {!WebInspector.TracingModel.EventPayload} payload
192 */
193 _addEvent: function(payload)
194 {
195 var process = this._processById[payload.pid];
196 if (!process) {
197 process = new WebInspector.TracingModel.Process(payload.pid);
198 this._processById[payload.pid] = process;
199 }
200 var thread = process.threadById(payload.tid);
201 if (payload.ph !== WebInspector.TracingModel.Phase.Metadata) {
202 var timestamp = payload.ts / 1000;
203 // We do allow records for unrelated threads to arrive out-of-order,
204 // so there's a chance we're getting records from the past.
205 if (timestamp && (!this._minimumRecordTime || timestamp < this._mini mumRecordTime))
206 this._minimumRecordTime = timestamp;
207 if (!this._maximumRecordTime || timestamp > this._maximumRecordTime)
208 this._maximumRecordTime = timestamp;
209 var event = thread.addEvent(payload);
210 if (payload.ph === WebInspector.TracingModel.Phase.SnapshotObject)
211 process.addObject(event);
212 if (event && event.name === WebInspector.TracingModel.DevToolsMetada taEvent.TracingStartedInPage &&
213 event.category === WebInspector.TracingModel.DevToolsMetadataEve ntCategory &&
214 event.args["sessionId"] === this._sessionId)
215 this._devtoolsMetadataEvents.push(event);
216 return;
217 }
218 switch (payload.name) {
219 case WebInspector.TracingModel.MetadataEvent.ProcessSortIndex:
220 process._setSortIndex(payload.args["sort_index"]);
221 break;
222 case WebInspector.TracingModel.MetadataEvent.ProcessName:
223 process._setName(payload.args["name"]);
224 break;
225 case WebInspector.TracingModel.MetadataEvent.ThreadSortIndex:
226 thread._setSortIndex(payload.args["sort_index"]);
227 break;
228 case WebInspector.TracingModel.MetadataEvent.ThreadName:
229 thread._setName(payload.args["name"]);
230 break;
231 }
232 },
233
234 /**
235 * @return {number}
236 */
237 minimumRecordTime: function()
238 {
239 return this._minimumRecordTime;
240 },
241
242 /**
243 * @return {number}
244 */
245 maximumRecordTime: function()
246 {
247 return this._maximumRecordTime;
248 },
249
250 /**
251 * @return {!Array.<!WebInspector.TracingModel.Process>}
252 */
253 sortedProcesses: function()
254 {
255 return WebInspector.TracingModel.NamedObject._sort(Object.values(this._p rocessById));
256 },
257
258 __proto__: WebInspector.SDKObject.prototype
259 }
260
261
262 /**
263 * @constructor
264 * @param {!WebInspector.TracingModel} tracingModel
265 */
266 WebInspector.TracingModel.Loader = function(tracingModel)
267 {
268 this._tracingModel = tracingModel;
269 this._events = [];
270 this._sessionIdFound = false;
271 }
272
273 WebInspector.TracingModel.Loader.prototype = {
274 /**
275 * @param {!Array.<!WebInspector.TracingModel.EventPayload>} events
276 */
277 loadNextChunk: function(events) {
278 if (this._sessionIdFound) {
279 this._tracingModel._eventsCollected(events);
280 return;
281 }
282
283 var sessionId = null;
284 for (var i = 0, length = events.length; i < length; i++) {
285 var event = events[i];
286 this._events.push(event);
287
288 if (event.name === WebInspector.TracingModel.DevToolsMetadataEvent.T racingStartedInPage &&
289 event.cat.indexOf(WebInspector.TracingModel.DevToolsMetadataEven tCategory) !== -1 &&
290 !this._sessionIdFound) {
291 sessionId = event.args["sessionId"];
292 this._sessionIdFound = true;
293 }
294 }
295
296 if (this._sessionIdFound) {
297 this._tracingModel._tracingStarted(sessionId);
298 this._tracingModel._eventsCollected(this._events);
299 }
300 },
301
302 finish: function()
303 {
304 if (this._sessionIdFound)
305 this._tracingModel._tracingComplete();
306 else
307 WebInspector.console.error(WebInspector.UIString("Trace event %s not found while loading tracing model.", WebInspector.TracingModel.DevToolsMetadata Event.TracingStartedInPage));
308 }
309 }
310
311
312 /**
313 * @constructor
314 * @param {!WebInspector.TracingModel.EventPayload} payload
315 * @param {number} level
316 * @param {?WebInspector.TracingModel.Thread} thread
317 */
318 WebInspector.TracingModel.Event = function(payload, level, thread)
319 {
320 this.name = payload.name;
321 this.category = payload.cat;
322 this.startTime = payload.ts / 1000;
323 if (payload.args) {
324 // Create a new object to avoid modifying original payload which may be saved to file.
325 this.args = {};
326 for (var name in payload.args)
327 this.args[name] = payload.args[name];
328 }
329 this.phase = payload.ph;
330 this.level = level;
331
332 if (typeof payload.dur === "number")
333 this._setEndTime((payload.ts + payload.dur) / 1000);
334
335 if (payload.id)
336 this.id = payload.id;
337
338 this.thread = thread;
339
340 /** @type {?string} */
341 this.warning = null;
342 /** @type {?WebInspector.TracingModel.Event} */
343 this.initiator = null;
344 /** @type {?Array.<!ConsoleAgent.CallFrame>} */
345 this.stackTrace = null;
346 /** @type {?Element} */
347 this.previewElement = null;
348 /** @type {?string} */
349 this.imageURL = null;
350 /** @type {number} */
351 this.backendNodeId = 0;
352
353 /** @type {number} */
354 this.selfTime = 0;
355 }
356
357 WebInspector.TracingModel.Event.prototype = {
358 /**
359 * @param {number} endTime
360 */
361 _setEndTime: function(endTime)
362 {
363 if (endTime < this.startTime) {
364 console.assert(false, "Event out of order: " + this.name);
365 return;
366 }
367 this.endTime = endTime;
368 this.duration = endTime - this.startTime;
369 },
370
371 /**
372 * @param {!WebInspector.TracingModel.EventPayload} payload
373 */
374 _complete: function(payload)
375 {
376 if (this.name !== payload.name) {
377 console.assert(false, "Open/close event mismatch: " + this.name + " vs. " + payload.name + " at " + (payload.ts / 1000));
378 return;
379 }
380 if (payload.args) {
381 for (var name in payload.args) {
382 if (name in this.args)
383 console.error("Same argument name (" + name + ") is used fo r begin and end phases of " + this.name);
384 this.args[name] = payload.args[name];
385 }
386 }
387 this._setEndTime(payload.ts / 1000);
388 }
389 }
390
391 /**
392 * @param {!WebInspector.TracingModel.Event} a
393 * @param {!WebInspector.TracingModel.Event} b
394 * @return {number}
395 */
396 WebInspector.TracingModel.Event.compareStartTime = function (a, b)
397 {
398 return a.startTime - b.startTime;
399 }
400
401 /**
402 * @param {!WebInspector.TracingModel.Event} a
403 * @param {!WebInspector.TracingModel.Event} b
404 * @return {number}
405 */
406 WebInspector.TracingModel.Event.orderedCompareStartTime = function (a, b)
407 {
408 // Array.mergeOrdered coalesces objects if comparator returns 0.
409 // To change this behavior this comparator return -1 in the case events
410 // startTime's are equal, so both events got placed into the result array.
411 return a.startTime - b.startTime || -1;
412 }
413
414 /**
415 * @constructor
416 */
417 WebInspector.TracingModel.NamedObject = function()
418 {
419 }
420
421 WebInspector.TracingModel.NamedObject.prototype =
422 {
423 /**
424 * @param {string} name
425 */
426 _setName: function(name)
427 {
428 this._name = name;
429 },
430
431 /**
432 * @return {string}
433 */
434 name: function()
435 {
436 return this._name;
437 },
438
439 /**
440 * @param {number} sortIndex
441 */
442 _setSortIndex: function(sortIndex)
443 {
444 this._sortIndex = sortIndex;
445 },
446 }
447
448 /**
449 * @param {!Array.<!WebInspector.TracingModel.NamedObject>} array
450 */
451 WebInspector.TracingModel.NamedObject._sort = function(array)
452 {
453 /**
454 * @param {!WebInspector.TracingModel.NamedObject} a
455 * @param {!WebInspector.TracingModel.NamedObject} b
456 */
457 function comparator(a, b)
458 {
459 return a._sortIndex !== b._sortIndex ? a._sortIndex - b._sortIndex : a.n ame().localeCompare(b.name());
460 }
461 return array.sort(comparator);
462 }
463
464 /**
465 * @constructor
466 * @extends {WebInspector.TracingModel.NamedObject}
467 * @param {number} id
468 */
469 WebInspector.TracingModel.Process = function(id)
470 {
471 WebInspector.TracingModel.NamedObject.call(this);
472 this._setName("Process " + id);
473 this._threads = {};
474 this._objects = {};
475 }
476
477 WebInspector.TracingModel.Process.prototype = {
478 /**
479 * @param {number} id
480 * @return {!WebInspector.TracingModel.Thread}
481 */
482 threadById: function(id)
483 {
484 var thread = this._threads[id];
485 if (!thread) {
486 thread = new WebInspector.TracingModel.Thread(this, id);
487 this._threads[id] = thread;
488 }
489 return thread;
490 },
491
492 /**
493 * @param {!WebInspector.TracingModel.Event} event
494 */
495 addObject: function(event)
496 {
497 this.objectsByName(event.name).push(event);
498 },
499
500 /**
501 * @param {string} name
502 * @return {!Array.<!WebInspector.TracingModel.Event>}
503 */
504 objectsByName: function(name)
505 {
506 var objects = this._objects[name];
507 if (!objects) {
508 objects = [];
509 this._objects[name] = objects;
510 }
511 return objects;
512 },
513
514 /**
515 * @return {!Array.<string>}
516 */
517 sortedObjectNames: function()
518 {
519 return Object.keys(this._objects).sort();
520 },
521
522 /**
523 * @return {!Array.<!WebInspector.TracingModel.Thread>}
524 */
525 sortedThreads: function()
526 {
527 return WebInspector.TracingModel.NamedObject._sort(Object.values(this._t hreads));
528 },
529
530 __proto__: WebInspector.TracingModel.NamedObject.prototype
531 }
532
533 /**
534 * @constructor
535 * @extends {WebInspector.TracingModel.NamedObject}
536 * @param {!WebInspector.TracingModel.Process} process
537 * @param {number} id
538 */
539 WebInspector.TracingModel.Thread = function(process, id)
540 {
541 WebInspector.TracingModel.NamedObject.call(this);
542 this._process = process;
543 this._setName("Thread " + id);
544 this._events = [];
545 this._stack = [];
546 this._maxStackDepth = 0;
547 }
548
549 WebInspector.TracingModel.Thread.prototype = {
550
551 /**
552 * @return {?WebInspector.Target}
553 */
554 target: function()
555 {
556 //FIXME: correctly specify target
557 return WebInspector.targetManager.targets()[0];
558 },
559
560 /**
561 * @param {!WebInspector.TracingModel.EventPayload} payload
562 * @return {?WebInspector.TracingModel.Event} event
563 */
564 addEvent: function(payload)
565 {
566 var timestamp = payload.ts / 1000;
567 for (var top = this._stack.peekLast(); top;) {
568 // For B/E pairs, ignore time and look for top matching B event,
569 // otherwise, only pop event if it's definitely is in the past.
570 if (payload.ph === WebInspector.TracingModel.Phase.End) {
571 if (payload.name === top.name) {
572 top._complete(payload);
573 this._stack.pop();
574 return null;
575 }
576 } else if (top.phase === WebInspector.TracingModel.Phase.Begin || (t op.endTime && (top.endTime > timestamp))) {
577 break;
578 }
579 this._stack.pop();
580 top = this._stack.peekLast();
581 }
582 // Quietly ignore unbalanced close events, they're legit (we could have missed start one).
583 if (payload.ph === WebInspector.TracingModel.Phase.End)
584 return null;
585
586 var event = new WebInspector.TracingModel.Event(payload, this._stack.len gth, this);
587 if (payload.ph === WebInspector.TracingModel.Phase.Begin || payload.ph = == WebInspector.TracingModel.Phase.Complete) {
588 this._stack.push(event);
589 if (this._maxStackDepth < this._stack.length)
590 this._maxStackDepth = this._stack.length;
591 }
592 if (this._events.length && this._events.peekLast().startTime > event.sta rtTime)
593 console.assert(false, "Event is our of order: " + event.name);
594 this._events.push(event);
595 return event;
596 },
597
598 /**
599 * @return {!WebInspector.TracingModel.Process}
600 */
601 process: function()
602 {
603 return this._process;
604 },
605
606 /**
607 * @return {!Array.<!WebInspector.TracingModel.Event>}
608 */
609 events: function()
610 {
611 return this._events;
612 },
613
614 /**
615 * @return {number}
616 */
617 maxStackDepth: function()
618 {
619 // Reserve one for non-container events.
620 return this._maxStackDepth + 1;
621 },
622
623 __proto__: WebInspector.TracingModel.NamedObject.prototype
624 }
625
626
627 /**
628 * @constructor
629 * @implements {TracingAgent.Dispatcher}
630 * @param {!WebInspector.TracingModel} tracingModel
631 */
632 WebInspector.TracingDispatcher = function(tracingModel)
633 {
634 this._tracingModel = tracingModel;
635 }
636
637 WebInspector.TracingDispatcher.prototype = {
638 /**
639 * @param {number} usage
640 */
641 bufferUsage: function(usage)
642 {
643 this._tracingModel._bufferUsage(usage);
644 },
645
646 /**
647 * @param {!Array.<!WebInspector.TracingModel.EventPayload>} data
648 */
649 dataCollected: function(data)
650 {
651 this._tracingModel._eventsCollected(data);
652 },
653
654 tracingComplete: function()
655 {
656 this._tracingModel._tracingComplete();
657 },
658
659 /**
660 * @param {boolean} consoleTimeline
661 * @param {string} sessionId
662 */
663 started: function(consoleTimeline, sessionId)
664 {
665 this._tracingModel._tracingStarted(sessionId);
666 },
667
668 stopped: function()
669 {
670 this._tracingModel._onStop();
671 }
672 }
OLDNEW
« no previous file with comments | « Source/devtools/front_end/timeline/TimelineFlameChart.js ('k') | Source/devtools/front_end/timeline/TracingTimelineModel.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698