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

Side by Side Diff: Source/devtools/front_end/TracingAgent.js

Issue 212683005: Timeline Trace viewer prototype (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: rebased Created 6 years, 8 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
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 12 matching lines...) Expand all
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 /** 31 /**
32 * @constructor 32 * @constructor
33 * @extends {WebInspector.Object}
33 */ 34 */
34 WebInspector.TracingAgent = function() 35 WebInspector.TracingAgent = function()
35 { 36 {
37 WebInspector.Object.call(this);
36 this._active = false; 38 this._active = false;
37 InspectorBackend.registerTracingDispatcher(new WebInspector.TracingDispatche r(this)); 39 InspectorBackend.registerTracingDispatcher(new WebInspector.TracingDispatche r(this));
38 } 40 }
39 41
42 WebInspector.TracingAgent.Events = {
43 EventsCollected: "EventsCollected"
44 };
45
46 /** @typedef {!{
47 cat: string,
48 pid: number,
49 tid: number,
50 ts: number,
51 ph: string,
52 name: string,
53 args: !Object,
54 dur: number,
55 id: number,
56 s: string
57 }}
58 */
59 WebInspector.TracingAgent.Event;
60
61 /**
62 * @enum {string}
63 */
64 WebInspector.TracingAgent.Phase = {
65 Begin: "B",
66 End: "E",
67 Complete: "X",
68 Instant: "i",
69 AsyncBegin: "S",
70 AsyncStepInto: "T",
71 AsyncStepPast: "p",
72 AsyncEnd: "F",
73 FlowBegin: "s",
74 FlowStep: "t",
75 FlowEnd: "f",
76 Metadata: "M",
77 Counter: "C",
78 Sample: "P",
79 CreateObject: "N",
80 SnapshotObject: "O",
81 DeleteObject: "D"
82 };
83
84 WebInspector.TracingAgent.MetadataEvent = {
85 ProcessSortIndex: "process_sort_index",
86 ProcessName: "process_name",
87 ThreadSortIndex: "thread_sort_index",
88 ThreadName: "thread_name"
89 }
90
40 WebInspector.TracingAgent.prototype = { 91 WebInspector.TracingAgent.prototype = {
41 /** 92 /**
42 * @param {string} categoryPatterns 93 * @param {string} categoryPatterns
43 * @param {string} options 94 * @param {string} options
44 * @param {function(?string)=} callback 95 * @param {function(?string)=} callback
45 */ 96 */
46 start: function(categoryPatterns, options, callback) 97 start: function(categoryPatterns, options, callback)
47 { 98 {
48 TracingAgent.start(categoryPatterns, options, callback); 99 TracingAgent.start(categoryPatterns, options, callback);
49 this._active = true; 100 this._active = true;
50 this._events = [];
51 }, 101 },
52 102
53 /** 103 /**
54 * @param {function()} callback 104 * @param {function()} callback
55 */ 105 */
56 stop: function(callback) 106 stop: function(callback)
57 { 107 {
58 if (!this._active) { 108 if (!this._active) {
59 callback(); 109 callback();
60 return; 110 return;
61 } 111 }
62 this._pendingStopCallback = callback; 112 this._pendingStopCallback = callback;
63 TracingAgent.end(); 113 TracingAgent.end();
64 }, 114 },
65 115
66 /**
67 * @return {!Array.<!{cat: string, args: !Object, ph: string, ts: number}>}
68 */
69 events: function()
70 {
71 return this._events;
72 },
73
74 _eventsCollected: function(events) 116 _eventsCollected: function(events)
75 { 117 {
76 Array.prototype.push.apply(this._events, events); 118 this.dispatchEventToListeners(WebInspector.TracingAgent.Events.EventsCol lected, events);
77 }, 119 },
78 120
79 _tracingComplete: function() 121 _tracingComplete: function()
80 { 122 {
81 this._active = false; 123 this._active = false;
82 if (this._pendingStopCallback) { 124 if (!this._pendingStopCallback)
83 this._pendingStopCallback(); 125 return;
84 this._pendingStopCallback = null; 126 this._pendingStopCallback();
85 } 127 this._pendingStopCallback = null;
86 } 128 },
129
130 __proto__: WebInspector.Object.prototype
87 } 131 }
88 132
89 /** 133 /**
90 * @constructor 134 * @constructor
91 * @implements {TracingAgent.Dispatcher} 135 * @implements {TracingAgent.Dispatcher}
92 * @param {!WebInspector.TracingAgent} tracingAgent 136 * @param {!WebInspector.TracingAgent} tracingAgent
93 */ 137 */
94 WebInspector.TracingDispatcher = function(tracingAgent) 138 WebInspector.TracingDispatcher = function(tracingAgent)
95 { 139 {
96 this._tracingAgent = tracingAgent; 140 this._tracingAgent = tracingAgent;
97 } 141 }
98 142
99 WebInspector.TracingDispatcher.prototype = { 143 WebInspector.TracingDispatcher.prototype = {
100 dataCollected: function(data) 144 dataCollected: function(data)
101 { 145 {
102 this._tracingAgent._eventsCollected(data); 146 this._tracingAgent._eventsCollected(data);
103 }, 147 },
104 148
105 tracingComplete: function() 149 tracingComplete: function()
106 { 150 {
107 this._tracingAgent._tracingComplete(); 151 this._tracingAgent._tracingComplete();
108 } 152 }
109 } 153 }
110 154
111 /** 155 /**
112 * @type {!WebInspector.TracingAgent} 156 * @type {!WebInspector.TracingAgent}
113 */ 157 */
114 WebInspector.tracingAgent; 158 WebInspector.tracingAgent;
159
160 /**
161 * @constructor
162 */
163 WebInspector.TracingModel = function()
pfeldman 2014/03/31 09:28:43 Lets have this in its own file.
164 {
165 this.reset();
166 }
167
168 WebInspector.TracingModel.prototype = {
169 reset: function()
170 {
171 this._processById = {};
172 this._minimumRecordTime = null;
173 this._maximumRecordTime = null;
174 },
175
176 /**
177 * @param {!Array.<!WebInspector.TracingAgent.Event>} payload
178 */
179 addEvents: function(payload)
180 {
181 for (var i = 0; i < payload.length; ++i)
182 this.addEvent(payload[i]);
183 },
184
185 /**
186 * @param {!WebInspector.TracingAgent.Event} payload
187 */
188 addEvent: function(payload)
189 {
190 var process = this._processById[payload.pid];
191 if (!process) {
192 process = new WebInspector.TracingModel.Process(payload.pid);
193 this._processById[payload.pid] = process;
194 }
195 var thread = process.threadById(payload.tid);
196 if (payload.ph !== WebInspector.TracingAgent.Phase.Metadata) {
197 var timestamp = payload.ts;
198 // We do allow records for unrelated threads to arrive out-of-order,
199 // so there's a chance we're getting records from the past.
200 if (timestamp && (!this._minimumRecordTime || timestamp < this._mini mumRecordTime))
201 this._minimumRecordTime = timestamp;
202 if (!this._maximumRecordTime || timestamp > this._maximumRecordTime)
203 this._maximumRecordTime = timestamp;
204 thread.addEvent(payload);
205 return;
206 }
207 switch (payload.name) {
208 case WebInspector.TracingAgent.MetadataEvent.ProcessSortIndex:
209 process._setSortIndex(payload.args["sort_index"]);
210 break;
211 case WebInspector.TracingAgent.MetadataEvent.ProcessName:
212 process._setName(payload.args["name"]);
213 break;
214 case WebInspector.TracingAgent.MetadataEvent.ThreadSortIndex:
215 thread._setSortIndex(payload.args["sort_index"]);
216 break;
217 case WebInspector.TracingAgent.MetadataEvent.ThreadName:
218 thread._setName(payload.args["name"]);
219 break;
220 }
221 },
222
223 /**
224 * @return {?number}
225 */
226 minimumRecordTime: function()
227 {
228 return this._minimumRecordTime;
229 },
230
231 /**
232 * @return {?number}
233 */
234 maximumRecordTime: function()
235 {
236 return this._maximumRecordTime;
237 },
238
239 /**
240 * @return {!Array.<!WebInspector.TracingModel.Process>}
241 */
242 sortedProcesses: function()
243 {
244 return WebInspector.TracingModel.NamedObject._sort(Object.values(this._p rocessById));
245 }
246 }
247
248 /**
249 * @constructor
250 * @param {!WebInspector.TracingAgent.Event} payload
251 * @param {number} level
252 */
253 WebInspector.TracingModel.Event = function(payload, level)
254 {
255 this.name = payload.name;
256 this.startTime = payload.ts;
257 this.args = payload.args;
258 this.phase = payload.phase;
259 this.level = level;
260 }
261
262 WebInspector.TracingModel.Event.prototype = {
263 /**
264 * @param {number} duration
265 */
266 _setDuration: function(duration)
267 {
268 this.endTime = this.startTime + duration;
269 this.duration = duration;
270 },
271
272 /**
273 * @param {!WebInspector.TracingAgent.Event} payload
274 */
275 _complete: function(payload)
276 {
277 if (this.name !== payload.name) {
278 console.assert(false, "Open/close event mismatch: " + this.name + " vs. " + payload.name);
279 return;
280 }
281 var duration = payload.ts - this.startTime;
282 if (duration < 0) {
283 console.assert(false, "Event out of order: " + this.name);
284 return;
285 }
286 this._setDuration(duration);
287 }
288 };
pfeldman 2014/03/31 09:28:43 remove ;
289
290 /**
291 * @constructor
292 */
293 WebInspector.TracingModel.NamedObject = function()
294 {
295 }
296
297 WebInspector.TracingModel.NamedObject.prototype =
298 {
299 /**
300 * @param {string} name
301 */
302 _setName: function(name)
303 {
304 this._name = name;
305 },
306
307 /**
308 * @return {string}
309 */
310 name: function()
311 {
312 return this._name;
313 },
314
315 /**
316 * @param {number} sortIndex
317 */
318 _setSortIndex: function(sortIndex)
319 {
320 this._sortIndex = sortIndex;
321 },
322 }
323
324 /**
325 * @param {!Array.<!WebInspector.TracingModel.NamedObject>} array
326 */
327 WebInspector.TracingModel.NamedObject._sort = function(array)
328 {
329 /**
330 * @param {!WebInspector.TracingModel.NamedObject} a
331 * @param {!WebInspector.TracingModel.NamedObject} b
332 */
333 function comparator(a, b)
334 {
335 return a._sortIndex !== b._sortIndex ? a._sortIndex - b._sortIndex : a.n ame().localeCompare(b.name());
336 }
337 return array.sort(comparator);
338 }
339
340 /**
341 * @constructor
342 * @extends {WebInspector.TracingModel.NamedObject}
343 * @param {number} id
344 */
345 WebInspector.TracingModel.Process = function(id)
346 {
347 WebInspector.TracingModel.NamedObject.call(this);
348 this._setName("Process " + id);
349 this._threads = {};
350 }
351
352 WebInspector.TracingModel.Process.prototype = {
353 /**
354 * @param {number} id
355 * @return {!WebInspector.TracingModel.Thread}
356 */
357 threadById: function(id)
358 {
359 var thread = this._threads[id];
360 if (!thread) {
361 thread = new WebInspector.TracingModel.Thread(id);
362 this._threads[id] = thread;
363 }
364 return thread;
365 },
366
367 /**
368 * @return {!Array.<!WebInspector.TracingModel.Thread>}
369 */
370 sortedThreads: function()
371 {
372 return WebInspector.TracingModel.NamedObject._sort(Object.values(this._t hreads));
373 },
374
375 __proto__: WebInspector.TracingModel.NamedObject.prototype
376 }
377
378 /**
379 * @constructor
380 * @extends {WebInspector.TracingModel.NamedObject}
381 * @param {number} id
382 */
383 WebInspector.TracingModel.Thread = function(id)
384 {
385 WebInspector.TracingModel.NamedObject.call(this);
386 this._setName("Thread " + id);
387 this._events = [];
388 this._stack = [];
389 this._maxStackDepth = 0;
390 }
391
392 WebInspector.TracingModel.Thread.prototype = {
393 /**
394 * @param {!WebInspector.TracingAgent.Event} payload
395 */
396 addEvent: function(payload)
397 {
398 for (var top = this._stack.peekLast(); top && top.endTime && top.endTime <= payload.ts;) {
399 this._stack.pop();
400 top = this._stack.peekLast();
401 }
402 if (payload.ph === WebInspector.TracingAgent.Phase.End) {
403 var openEvent = this._stack.pop();
404 // Quietly ignore unbalanced close events, they're legit (we could h ave missed start one).
405 if (openEvent)
406 openEvent._complete(payload);
407 return;
408 }
409
410 var event = new WebInspector.TracingModel.Event(payload, this._stack.len gth);
411 if (payload.ph === WebInspector.TracingAgent.Phase.Begin || payload.ph = == WebInspector.TracingAgent.Phase.Complete) {
412 if (payload.ph === WebInspector.TracingAgent.Phase.Complete)
413 event._setDuration(payload.dur);
414 this._stack.push(event);
415 if (this._maxStackDepth < this._stack.length)
416 this._maxStackDepth = this._stack.length;
417 }
418 if (this._events.length && this._events.peekLast().startTime > event.sta rtTime)
419 console.assert(false, "Event is our of order: " + event.name);
420 this._events.push(event);
421 },
422
423 /**
424 * @return {!Array.<!WebInspector.TracingModel.Event>}
425 */
426 events: function()
427 {
428 return this._events;
429 },
430
431 /**
432 * @return {number}
433 */
434 maxStackDepth: function()
435 {
436 // Reserve one for non-container events.
437 return this._maxStackDepth + 1;
438 },
439
440 __proto__: WebInspector.TracingModel.NamedObject.prototype
441 }
OLDNEW
« no previous file with comments | « Source/devtools/front_end/TimelineView.js ('k') | Source/devtools/scripts/frontend_modules.json » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698