OLD | NEW |
(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 */ |
| 10 WebInspector.TracingModel = function() |
| 11 { |
| 12 this.reset(); |
| 13 } |
| 14 |
| 15 WebInspector.TracingModel.prototype = { |
| 16 reset: function() |
| 17 { |
| 18 this._processById = {}; |
| 19 this._minimumRecordTime = null; |
| 20 this._maximumRecordTime = null; |
| 21 }, |
| 22 |
| 23 /** |
| 24 * @param {!Array.<!WebInspector.TracingAgent.Event>} payload |
| 25 */ |
| 26 addEvents: function(payload) |
| 27 { |
| 28 for (var i = 0; i < payload.length; ++i) |
| 29 this.addEvent(payload[i]); |
| 30 }, |
| 31 |
| 32 /** |
| 33 * @param {!WebInspector.TracingAgent.Event} payload |
| 34 */ |
| 35 addEvent: function(payload) |
| 36 { |
| 37 var process = this._processById[payload.pid]; |
| 38 if (!process) { |
| 39 process = new WebInspector.TracingModel.Process(payload.pid); |
| 40 this._processById[payload.pid] = process; |
| 41 } |
| 42 var thread = process.threadById(payload.tid); |
| 43 if (payload.ph !== WebInspector.TracingAgent.Phase.Metadata) { |
| 44 var timestamp = payload.ts; |
| 45 // We do allow records for unrelated threads to arrive out-of-order, |
| 46 // so there's a chance we're getting records from the past. |
| 47 if (timestamp && (!this._minimumRecordTime || timestamp < this._mini
mumRecordTime)) |
| 48 this._minimumRecordTime = timestamp; |
| 49 if (!this._maximumRecordTime || timestamp > this._maximumRecordTime) |
| 50 this._maximumRecordTime = timestamp; |
| 51 thread.addEvent(payload); |
| 52 return; |
| 53 } |
| 54 switch (payload.name) { |
| 55 case WebInspector.TracingAgent.MetadataEvent.ProcessSortIndex: |
| 56 process._setSortIndex(payload.args["sort_index"]); |
| 57 break; |
| 58 case WebInspector.TracingAgent.MetadataEvent.ProcessName: |
| 59 process._setName(payload.args["name"]); |
| 60 break; |
| 61 case WebInspector.TracingAgent.MetadataEvent.ThreadSortIndex: |
| 62 thread._setSortIndex(payload.args["sort_index"]); |
| 63 break; |
| 64 case WebInspector.TracingAgent.MetadataEvent.ThreadName: |
| 65 thread._setName(payload.args["name"]); |
| 66 break; |
| 67 } |
| 68 }, |
| 69 |
| 70 /** |
| 71 * @return {?number} |
| 72 */ |
| 73 minimumRecordTime: function() |
| 74 { |
| 75 return this._minimumRecordTime; |
| 76 }, |
| 77 |
| 78 /** |
| 79 * @return {?number} |
| 80 */ |
| 81 maximumRecordTime: function() |
| 82 { |
| 83 return this._maximumRecordTime; |
| 84 }, |
| 85 |
| 86 /** |
| 87 * @return {!Array.<!WebInspector.TracingModel.Process>} |
| 88 */ |
| 89 sortedProcesses: function() |
| 90 { |
| 91 return WebInspector.TracingModel.NamedObject._sort(Object.values(this._p
rocessById)); |
| 92 } |
| 93 } |
| 94 |
| 95 /** |
| 96 * @constructor |
| 97 * @param {!WebInspector.TracingAgent.Event} payload |
| 98 * @param {number} level |
| 99 */ |
| 100 WebInspector.TracingModel.Event = function(payload, level) |
| 101 { |
| 102 this.name = payload.name; |
| 103 this.startTime = payload.ts; |
| 104 this.args = payload.args; |
| 105 this.phase = payload.phase; |
| 106 this.level = level; |
| 107 } |
| 108 |
| 109 WebInspector.TracingModel.Event.prototype = { |
| 110 /** |
| 111 * @param {number} duration |
| 112 */ |
| 113 _setDuration: function(duration) |
| 114 { |
| 115 this.endTime = this.startTime + duration; |
| 116 this.duration = duration; |
| 117 }, |
| 118 |
| 119 /** |
| 120 * @param {!WebInspector.TracingAgent.Event} payload |
| 121 */ |
| 122 _complete: function(payload) |
| 123 { |
| 124 if (this.name !== payload.name) { |
| 125 console.assert(false, "Open/close event mismatch: " + this.name + "
vs. " + payload.name); |
| 126 return; |
| 127 } |
| 128 var duration = payload.ts - this.startTime; |
| 129 if (duration < 0) { |
| 130 console.assert(false, "Event out of order: " + this.name); |
| 131 return; |
| 132 } |
| 133 this._setDuration(duration); |
| 134 } |
| 135 } |
| 136 |
| 137 /** |
| 138 * @constructor |
| 139 */ |
| 140 WebInspector.TracingModel.NamedObject = function() |
| 141 { |
| 142 } |
| 143 |
| 144 WebInspector.TracingModel.NamedObject.prototype = |
| 145 { |
| 146 /** |
| 147 * @param {string} name |
| 148 */ |
| 149 _setName: function(name) |
| 150 { |
| 151 this._name = name; |
| 152 }, |
| 153 |
| 154 /** |
| 155 * @return {string} |
| 156 */ |
| 157 name: function() |
| 158 { |
| 159 return this._name; |
| 160 }, |
| 161 |
| 162 /** |
| 163 * @param {number} sortIndex |
| 164 */ |
| 165 _setSortIndex: function(sortIndex) |
| 166 { |
| 167 this._sortIndex = sortIndex; |
| 168 }, |
| 169 } |
| 170 |
| 171 /** |
| 172 * @param {!Array.<!WebInspector.TracingModel.NamedObject>} array |
| 173 */ |
| 174 WebInspector.TracingModel.NamedObject._sort = function(array) |
| 175 { |
| 176 /** |
| 177 * @param {!WebInspector.TracingModel.NamedObject} a |
| 178 * @param {!WebInspector.TracingModel.NamedObject} b |
| 179 */ |
| 180 function comparator(a, b) |
| 181 { |
| 182 return a._sortIndex !== b._sortIndex ? a._sortIndex - b._sortIndex : a.n
ame().localeCompare(b.name()); |
| 183 } |
| 184 return array.sort(comparator); |
| 185 } |
| 186 |
| 187 /** |
| 188 * @constructor |
| 189 * @extends {WebInspector.TracingModel.NamedObject} |
| 190 * @param {number} id |
| 191 */ |
| 192 WebInspector.TracingModel.Process = function(id) |
| 193 { |
| 194 WebInspector.TracingModel.NamedObject.call(this); |
| 195 this._setName("Process " + id); |
| 196 this._threads = {}; |
| 197 } |
| 198 |
| 199 WebInspector.TracingModel.Process.prototype = { |
| 200 /** |
| 201 * @param {number} id |
| 202 * @return {!WebInspector.TracingModel.Thread} |
| 203 */ |
| 204 threadById: function(id) |
| 205 { |
| 206 var thread = this._threads[id]; |
| 207 if (!thread) { |
| 208 thread = new WebInspector.TracingModel.Thread(id); |
| 209 this._threads[id] = thread; |
| 210 } |
| 211 return thread; |
| 212 }, |
| 213 |
| 214 /** |
| 215 * @return {!Array.<!WebInspector.TracingModel.Thread>} |
| 216 */ |
| 217 sortedThreads: function() |
| 218 { |
| 219 return WebInspector.TracingModel.NamedObject._sort(Object.values(this._t
hreads)); |
| 220 }, |
| 221 |
| 222 __proto__: WebInspector.TracingModel.NamedObject.prototype |
| 223 } |
| 224 |
| 225 /** |
| 226 * @constructor |
| 227 * @extends {WebInspector.TracingModel.NamedObject} |
| 228 * @param {number} id |
| 229 */ |
| 230 WebInspector.TracingModel.Thread = function(id) |
| 231 { |
| 232 WebInspector.TracingModel.NamedObject.call(this); |
| 233 this._setName("Thread " + id); |
| 234 this._events = []; |
| 235 this._stack = []; |
| 236 this._maxStackDepth = 0; |
| 237 } |
| 238 |
| 239 WebInspector.TracingModel.Thread.prototype = { |
| 240 /** |
| 241 * @param {!WebInspector.TracingAgent.Event} payload |
| 242 */ |
| 243 addEvent: function(payload) |
| 244 { |
| 245 for (var top = this._stack.peekLast(); top && top.endTime && top.endTime
<= payload.ts;) { |
| 246 this._stack.pop(); |
| 247 top = this._stack.peekLast(); |
| 248 } |
| 249 if (payload.ph === WebInspector.TracingAgent.Phase.End) { |
| 250 var openEvent = this._stack.pop(); |
| 251 // Quietly ignore unbalanced close events, they're legit (we could h
ave missed start one). |
| 252 if (openEvent) |
| 253 openEvent._complete(payload); |
| 254 return; |
| 255 } |
| 256 |
| 257 var event = new WebInspector.TracingModel.Event(payload, this._stack.len
gth); |
| 258 if (payload.ph === WebInspector.TracingAgent.Phase.Begin || payload.ph =
== WebInspector.TracingAgent.Phase.Complete) { |
| 259 if (payload.ph === WebInspector.TracingAgent.Phase.Complete) |
| 260 event._setDuration(payload.dur); |
| 261 this._stack.push(event); |
| 262 if (this._maxStackDepth < this._stack.length) |
| 263 this._maxStackDepth = this._stack.length; |
| 264 } |
| 265 if (this._events.length && this._events.peekLast().startTime > event.sta
rtTime) |
| 266 console.assert(false, "Event is our of order: " + event.name); |
| 267 this._events.push(event); |
| 268 }, |
| 269 |
| 270 /** |
| 271 * @return {!Array.<!WebInspector.TracingModel.Event>} |
| 272 */ |
| 273 events: function() |
| 274 { |
| 275 return this._events; |
| 276 }, |
| 277 |
| 278 /** |
| 279 * @return {number} |
| 280 */ |
| 281 maxStackDepth: function() |
| 282 { |
| 283 // Reserve one for non-container events. |
| 284 return this._maxStackDepth + 1; |
| 285 }, |
| 286 |
| 287 __proto__: WebInspector.TracingModel.NamedObject.prototype |
| 288 } |
OLD | NEW |