Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 TimelineModel.TimelineProfileTree = {}; | 5 TimelineModel.TimelineProfileTree = class { | 
| 6 /** | |
| 7 * @param {!Array<!SDK.TracingModel.Event>} events | |
| 8 * @param {!Array<!TimelineModel.TimelineModelFilter>} filters | |
| 9 * @param {number} startTime | |
| 10 * @param {number} endTime | |
| 11 * @param {function(!SDK.TracingModel.Event):string=} eventGroupIdCallback | |
| 12 */ | |
| 13 constructor(events, filters, startTime, endTime, eventGroupIdCallback) { | |
| 14 this._events = events; | |
| 15 this._filter = e => TimelineModel.TimelineModel.isVisible(filters, e); | |
| 16 this._startTime = startTime; | |
| 17 this._endTime = endTime; | |
| 18 this._eventGroupIdCallback = eventGroupIdCallback; | |
| 19 } | |
| 20 | |
| 21 /** | |
| 22 * @return {!TimelineModel.TimelineProfileTree.Node} | |
| 23 */ | |
| 24 bottomUpTreeRoot() { | |
| 25 return new TimelineModel.TimelineProfileTree.BottomUpTreeRootNode(this); | |
| 26 } | |
| 27 }; | |
| 6 | 28 | 
| 7 /** | 29 /** | 
| 8 * @unrestricted | 30 * @unrestricted | 
| 9 */ | 31 */ | 
| 10 TimelineModel.TimelineProfileTree.Node = class { | 32 TimelineModel.TimelineProfileTree.Node = class { | 
| 11 constructor() { | 33 /** | 
| 34 * @param {string} id | |
| 35 * @param {?SDK.TracingModel.Event} event | |
| 36 */ | |
| 37 constructor(id, event) { | |
| 12 /** @type {number} */ | 38 /** @type {number} */ | 
| 13 this.totalTime; | 39 this.totalTime = 0; | 
| 14 /** @type {number} */ | 40 /** @type {number} */ | 
| 15 this.selfTime; | 41 this.selfTime = 0; | 
| 16 /** @type {string} */ | 42 /** @type {string} */ | 
| 17 this.id; | 43 this.id = id; | 
| 18 /** @type {!SDK.TracingModel.Event} */ | 44 /** @type {?SDK.TracingModel.Event} */ | 
| 19 this.event; | 45 this.event = event; | 
| 20 /** @type {?Map<string|symbol,!TimelineModel.TimelineProfileTree.Node>} */ | |
| 21 this.children; | |
| 22 /** @type {?TimelineModel.TimelineProfileTree.Node} */ | 46 /** @type {?TimelineModel.TimelineProfileTree.Node} */ | 
| 23 this.parent; | 47 this.parent; | 
| 24 | 48 | 
| 25 /** @type {string} */ | 49 /** @type {string} */ | 
| 26 this._groupId = ''; | 50 this._groupId = ''; | 
| 27 this._isGroupNode = false; | 51 this._isGroupNode = false; | 
| 28 } | 52 } | 
| 29 | 53 | 
| 30 /** | 54 /** | 
| 31 * @return {boolean} | 55 * @return {boolean} | 
| 32 */ | 56 */ | 
| 33 isGroupNode() { | 57 isGroupNode() { | 
| 34 return this._isGroupNode; | 58 return this._isGroupNode; | 
| 35 } | 59 } | 
| 60 | |
| 61 /** | |
| 62 * @return {boolean} | |
| 63 */ | |
| 64 hasChildren() { | |
| 65 throw 'Not implemented'; | |
| 66 } | |
| 67 | |
| 68 /** | |
| 69 * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>} | |
| 70 */ | |
| 71 children() { | |
| 72 throw 'Not implemented'; | |
| 73 } | |
| 74 }; | |
| 75 | |
| 76 TimelineModel.TimelineProfileTree.TopDownNode = class extends TimelineModel.Time lineProfileTree.Node { | |
| 77 /** | |
| 78 * @param {string} id | |
| 79 * @param {?SDK.TracingModel.Event} event | |
| 80 */ | |
| 81 constructor(id, event) { | |
| 82 super(id, event); | |
| 83 /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Node>} */ | |
| 84 this._children = new Map(); | |
| 85 } | |
| 86 | |
| 87 /** | |
| 88 * @override | |
| 89 * @return {boolean} | |
| 90 */ | |
| 91 hasChildren() { | |
| 92 return !!this._children.size; | |
| 93 } | |
| 94 | |
| 95 /** | |
| 96 * @override | |
| 97 * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>} | |
| 98 */ | |
| 99 children() { | |
| 100 return this._children; | |
| 101 } | |
| 36 }; | 102 }; | 
| 37 | 103 | 
| 38 /** | 104 /** | 
| 39 * @param {!Array<!SDK.TracingModel.Event>} events | 105 * @param {!Array<!SDK.TracingModel.Event>} events | 
| 40 * @param {!Array<!TimelineModel.TimelineModelFilter>} filters | 106 * @param {!Array<!TimelineModel.TimelineModelFilter>} filters | 
| 41 * @param {number} startTime | 107 * @param {number} startTime | 
| 42 * @param {number} endTime | 108 * @param {number} endTime | 
| 43 * @param {function(!SDK.TracingModel.Event):string=} eventGroupIdCallback | 109 * @param {function(!SDK.TracingModel.Event):string=} eventGroupIdCallback | 
| 44 * @return {!TimelineModel.TimelineProfileTree.Node} | 110 * @return {!TimelineModel.TimelineProfileTree.Node} | 
| 45 */ | 111 */ | 
| 46 TimelineModel.TimelineProfileTree.buildTopDown = function(events, filters, start Time, endTime, eventGroupIdCallback) { | 112 TimelineModel.TimelineProfileTree.buildTopDown = function(events, filters, start Time, endTime, eventGroupIdCallback) { | 
| 47 // Temporarily deposit a big enough value that exceeds the max recording time. | 113 // Temporarily deposit a big enough value that exceeds the max recording time. | 
| 48 var /** @const */ initialTime = 1e7; | 114 var /** @const */ initialTime = 1e7; | 
| 49 var root = new TimelineModel.TimelineProfileTree.Node(); | 115 var root = new TimelineModel.TimelineProfileTree.TopDownNode('', null); | 
| 50 root.totalTime = initialTime; | 116 root.totalTime = initialTime; | 
| 51 root.selfTime = initialTime; | 117 root.selfTime = initialTime; | 
| 52 root.children = /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Nod e>} */ (new Map()); | |
| 53 var parent = root; | 118 var parent = root; | 
| 54 | 119 | 
| 55 /** | 120 /** | 
| 56 * @param {!SDK.TracingModel.Event} e | 121 * @param {!SDK.TracingModel.Event} e | 
| 57 */ | 122 */ | 
| 58 function onStartEvent(e) { | 123 function onStartEvent(e) { | 
| 59 if (!TimelineModel.TimelineModel.isVisible(filters, e)) | 124 if (!TimelineModel.TimelineModel.isVisible(filters, e)) | 
| 60 return; | 125 return; | 
| 61 var time = e.endTime ? Math.min(endTime, e.endTime) - Math.max(startTime, e. startTime) : 0; | 126 var time = e.endTime ? Math.min(endTime, e.endTime) - Math.max(startTime, e. startTime) : 0; | 
| 62 var groupId = eventGroupIdCallback ? eventGroupIdCallback(e) : Symbol('uniqu eGroupId'); | 127 var groupId = eventGroupIdCallback ? eventGroupIdCallback(e) : Symbol('uniqu eGroupId'); | 
| 63 var id = eventGroupIdCallback ? TimelineModel.TimelineProfileTree._eventId(e ) : Symbol('uniqueEventId'); | 128 var id = eventGroupIdCallback ? TimelineModel.TimelineProfileTree._eventId(e ) : Symbol('uniqueEventId'); | 
| 64 if (typeof groupId === 'string' && typeof id === 'string') | 129 if (typeof groupId === 'string' && typeof id === 'string') | 
| 65 id += '/' + groupId; | 130 id += '/' + groupId; | 
| 66 if (!parent.children) | 131 var node = parent.children().get(id); | 
| 67 parent.children = /** @type {!Map<string,!TimelineModel.TimelineProfileTre e.Node>} */ (new Map()); | |
| 68 var node = parent.children.get(id); | |
| 69 if (node) { | 132 if (node) { | 
| 70 node.selfTime += time; | 133 node.selfTime += time; | 
| 71 node.totalTime += time; | 134 node.totalTime += time; | 
| 72 } else { | 135 } else { | 
| 73 node = new TimelineModel.TimelineProfileTree.Node(); | 136 node = new TimelineModel.TimelineProfileTree.TopDownNode(id, e); | 
| 74 node.totalTime = time; | 137 node.totalTime = time; | 
| 75 node.selfTime = time; | 138 node.selfTime = time; | 
| 76 node.parent = parent; | 139 node.parent = parent; | 
| 77 node.id = id; | |
| 78 node.event = e; | |
| 79 node._groupId = groupId; | 140 node._groupId = groupId; | 
| 80 parent.children.set(id, node); | 141 parent.children().set(id, node); | 
| 81 } | 142 } | 
| 82 parent.selfTime -= time; | 143 parent.selfTime -= time; | 
| 83 if (parent.selfTime < 0) { | 144 if (parent.selfTime < 0) { | 
| 84 console.error('Error: Negative self of ' + parent.selfTime, e); | 145 console.error('Error: Negative self of ' + parent.selfTime, e); | 
| 85 parent.selfTime = 0; | 146 parent.selfTime = 0; | 
| 86 } | 147 } | 
| 87 if (e.endTime) | 148 if (e.endTime) | 
| 88 parent = node; | 149 parent = node; | 
| 89 } | 150 } | 
| 90 | 151 | 
| 91 /** | 152 /** | 
| 92 * @param {!SDK.TracingModel.Event} e | 153 * @param {!SDK.TracingModel.Event} e | 
| 93 */ | 154 */ | 
| 94 function onEndEvent(e) { | 155 function onEndEvent(e) { | 
| 95 if (!TimelineModel.TimelineModel.isVisible(filters, e)) | 156 if (!TimelineModel.TimelineModel.isVisible(filters, e)) | 
| 96 return; | 157 return; | 
| 97 parent = parent.parent; | 158 parent = parent.parent; | 
| 98 } | 159 } | 
| 99 | 160 | 
| 100 var instantEventCallback = | 161 var instantEventCallback = | 
| 101 eventGroupIdCallback ? undefined : onStartEvent; // Ignore instant events when aggregating. | 162 eventGroupIdCallback ? undefined : onStartEvent; // Ignore instant events when aggregating. | 
| 102 TimelineModel.TimelineModel.forEachEvent(events, onStartEvent, onEndEvent, ins tantEventCallback, startTime, endTime); | 163 TimelineModel.TimelineModel.forEachEvent(events, onStartEvent, onEndEvent, ins tantEventCallback, startTime, endTime); | 
| 103 root.totalTime -= root.selfTime; | 164 root.totalTime -= root.selfTime; | 
| 104 root.selfTime = 0; | 165 root.selfTime = 0; | 
| 105 return root; | 166 return root; | 
| 106 }; | 167 }; | 
| 107 | 168 | 
| 169 TimelineModel.TimelineProfileTree.BottomUpTreeRootNode = class extends TimelineM odel.TimelineProfileTree.Node { | |
| 170 /** | |
| 171 * @param {!TimelineModel.TimelineProfileTree} tree | |
| 172 */ | |
| 173 constructor(tree) { | |
| 174 super('', null); | |
| 175 this._tree = tree; | |
| 176 this.totalTime = this._tree._endTime - this._tree._startTime; | |
| 177 } | |
| 178 | |
| 179 /** | |
| 180 * @override | |
| 181 * @return {boolean} | |
| 182 */ | |
| 183 hasChildren() { | |
| 184 return true; | |
| 185 } | |
| 186 | |
| 187 /** | |
| 188 * @override | |
| 189 * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>} | |
| 190 */ | |
| 191 children() { | |
| 192 return this._grouppedTopNodes(); | |
| 193 } | |
| 194 | |
| 195 /** | |
| 196 * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>} | |
| 197 */ | |
| 198 _ungrouppedTopNodes() { | |
| 199 var root = this; | |
| 200 var startTime = this._tree._startTime; | |
| 201 var endTime = this._tree._endTime; | |
| 202 /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Node>} */ | |
| 203 var nodeById = new Map(); | |
| 204 /** @type {!Array<number>} */ | |
| 205 var selfTimeStack = [endTime - startTime]; | |
| 206 /** @type {!Array<boolean>} */ | |
| 207 var firstNodeStack = []; | |
| 208 /** @type {!Map<string, number>} */ | |
| 209 var totalTimeById = new Map(); | |
| 210 TimelineModel.TimelineModel.forEachEvent( | |
| 211 this._tree._events, onStartEvent, onEndEvent, undefined, startTime, endT ime, this._tree._filter); | |
| 212 | |
| 213 /** | |
| 214 * @param {!SDK.TracingModel.Event} e | |
| 215 */ | |
| 216 function onStartEvent(e) { | |
| 217 var duration = Math.min(e.endTime, endTime) - Math.max(e.startTime, startT ime); | |
| 218 selfTimeStack[selfTimeStack.length - 1] -= duration; | |
| 219 selfTimeStack.push(duration); | |
| 220 var id = TimelineModel.TimelineProfileTree._eventId(e); | |
| 221 var noNodeOnStack = !totalTimeById.has(id); | |
| 222 if (noNodeOnStack) | |
| 223 totalTimeById.set(id, duration); | |
| 224 firstNodeStack.push(noNodeOnStack); | |
| 225 } | |
| 226 | |
| 227 /** | |
| 228 * @param {!SDK.TracingModel.Event} e | |
| 229 */ | |
| 230 function onEndEvent(e) { | |
| 231 var id = TimelineModel.TimelineProfileTree._eventId(e); | |
| 232 var node = nodeById.get(id); | |
| 233 if (!node) { | |
| 234 node = new TimelineModel.TimelineProfileTree.BottomUpTreeNode(root._tree , id, e, root); | |
| 235 nodeById.set(id, node); | |
| 236 } | |
| 237 node.selfTime += selfTimeStack.pop(); | |
| 238 if (firstNodeStack.pop()) { | |
| 239 node.totalTime += totalTimeById.get(id); | |
| 240 totalTimeById.delete(id); | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 this.selfTime = selfTimeStack.pop(); | |
| 245 for (var pair of nodeById) { | |
| 246 if (pair[1].selfTime <= 0) | |
| 247 nodeById.delete(/** @type {string} */ (pair[0])); | |
| 248 } | |
| 249 return nodeById; | |
| 250 } | |
| 251 | |
| 252 /** | |
| 253 * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>} | |
| 254 */ | |
| 255 _grouppedTopNodes() { | |
| 256 var flatNodes = this._ungrouppedTopNodes(); | |
| 257 var groupNodes = new Map(); | |
| 258 for (var node of flatNodes.values()) { | |
| 259 var groupId = this._tree._eventGroupIdCallback(/** @type {!SDK.TracingMode l.Event} */ (node.event)); | |
| 260 if (typeof groupId !== 'string') | |
| 261 return flatNodes; | |
| 262 var groupNode = groupNodes.get(groupId); | |
| 263 if (!groupNode) { | |
| 264 groupNode = new TimelineModel.TimelineProfileTree.BottomUpTreeGroupNode( | |
| 265 groupId, /** @type {!SDK.TracingModel.Event} */ (node.event)); | |
| 266 groupNode.parent = this; | |
| 267 groupNodes.set(groupId, groupNode); | |
| 268 } | |
| 269 groupNode.addChild(node); | |
| 270 node.parent = groupNode; | |
| 271 } | |
| 272 return groupNodes; | |
| 273 } | |
| 274 }; | |
| 275 | |
| 276 TimelineModel.TimelineProfileTree.BottomUpTreeGroupNode = class extends Timeline Model.TimelineProfileTree.Node { | |
| 277 /** | |
| 278 * @param {string} id | |
| 279 * @param {!SDK.TracingModel.Event} event | |
| 280 */ | |
| 281 constructor(id, event) { | |
| 282 super(id, event); | |
| 283 this._children = new Map(); | |
| 284 this._isGroupNode = true; | |
| 285 } | |
| 286 | |
| 287 /** | |
| 288 * @param {!TimelineModel.TimelineProfileTree.BottomUpTreeNode} child | |
| 289 */ | |
| 290 addChild(child) { | |
| 291 this._children.set(child.id, child); | |
| 292 this.selfTime += child.selfTime; | |
| 293 this.totalTime += child.selfTime; | |
| 294 } | |
| 295 | |
| 296 /** | |
| 297 * @override | |
| 298 * @return {boolean} | |
| 299 */ | |
| 300 hasChildren() { | |
| 301 return true; | |
| 302 } | |
| 303 | |
| 304 /** | |
| 305 * @override | |
| 306 * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>} | |
| 307 */ | |
| 308 children() { | |
| 309 return this._children; | |
| 310 } | |
| 311 }; | |
| 312 | |
| 313 TimelineModel.TimelineProfileTree.BottomUpTreeNode = class extends TimelineModel .TimelineProfileTree.Node { | |
| 314 /** | |
| 315 * @param {!TimelineModel.TimelineProfileTree} tree | |
| 316 * @param {string} id | |
| 317 * @param {!SDK.TracingModel.Event} event | |
| 318 * @param {!TimelineModel.TimelineProfileTree.Node} parent | |
| 319 */ | |
| 320 constructor(tree, id, event, parent) { | |
| 321 super(id, event); | |
| 322 this.parent = parent; | |
| 323 this._tree = tree; | |
| 324 this._depth = (parent._depth || 0) + 1; | |
| 325 this._cachedChildren = null; | |
| 326 this._hasChildren = true; | |
| 
 
caseq
2017/02/03 19:55:25
let's pass the correct value
 
alph
2017/02/03 20:06:01
Done.
 
 | |
| 327 } | |
| 328 | |
| 329 /** | |
| 330 * @override | |
| 331 * @return {boolean} | |
| 332 */ | |
| 333 hasChildren() { | |
| 334 return this._hasChildren; | |
| 335 } | |
| 336 | |
| 337 /** | |
| 338 * @override | |
| 339 * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>} | |
| 340 */ | |
| 341 children() { | |
| 342 if (this._cachedChildren) | |
| 343 return this._cachedChildren; | |
| 344 /** @type {!Array<number>} */ | |
| 345 var selfTimeStack = [0]; | |
| 346 /** @type {!Array<string>} */ | |
| 347 var eventIdStack = []; | |
| 348 /** @type {!Array<!SDK.TracingModel.Event>} */ | |
| 349 var eventStack = []; | |
| 350 /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Node>} */ | |
| 351 var nodeById = new Map(); | |
| 352 var startTime = this._tree._startTime; | |
| 353 var endTime = this._tree._endTime; | |
| 354 var lastTimeMarker = startTime; | |
| 355 var self = this; | |
| 356 TimelineModel.TimelineModel.forEachEvent( | |
| 357 this._tree._events, onStartEvent, onEndEvent, undefined, startTime, endT ime, this._tree._filter); | |
| 358 | |
| 359 /** | |
| 360 * @param {!SDK.TracingModel.Event} e | |
| 361 */ | |
| 362 function onStartEvent(e) { | |
| 363 var duration = Math.min(e.endTime, endTime) - Math.max(e.startTime, startT ime); | |
| 364 console.assert(duration >= 0); | |
| 
 
caseq
2017/02/03 19:55:25
if (duration < 0) console.assert(false, ...);
 
alph
2017/02/03 20:06:01
Done.
 
 | |
| 365 selfTimeStack[selfTimeStack.length - 1] -= duration; | |
| 366 selfTimeStack.push(duration); | |
| 367 var id = TimelineModel.TimelineProfileTree._eventId(e); | |
| 368 eventIdStack.push(id); | |
| 369 eventStack.push(e); | |
| 370 } | |
| 371 | |
| 372 /** | |
| 373 * @param {!SDK.TracingModel.Event} e | |
| 374 */ | |
| 375 function onEndEvent(e) { | |
| 376 var selfTime = selfTimeStack.pop(); | |
| 377 var id = eventIdStack.pop(); | |
| 378 eventStack.pop(); | |
| 379 for (var node = self; node._depth > 1; node = node.parent) { | |
| 380 if (node.id !== eventIdStack[eventIdStack.length + 1 - node._depth]) | |
| 381 return; | |
| 382 } | |
| 383 if (node.id !== id || eventIdStack.length < self._depth) | |
| 384 return; | |
| 385 var childId = eventIdStack[eventIdStack.length - self._depth]; | |
| 386 var node = nodeById.get(childId); | |
| 387 if (!node) { | |
| 388 var event = eventStack[eventStack.length - self._depth]; | |
| 389 node = new TimelineModel.TimelineProfileTree.BottomUpTreeNode(self._tree , childId, event, self); | |
| 390 node._hasChildren = eventStack.length > self._depth; | |
| 391 nodeById.set(childId, node); | |
| 392 } | |
| 393 var totalTime = Math.min(e.endTime, endTime) - Math.max(e.startTime, lastT imeMarker); | |
| 394 node.selfTime += selfTime; | |
| 395 node.totalTime += totalTime; | |
| 396 lastTimeMarker = Math.min(e.endTime, endTime); | |
| 397 } | |
| 398 | |
| 399 this._cachedChildren = nodeById; | |
| 400 return nodeById; | |
| 401 } | |
| 402 }; | |
| 403 | |
| 108 /** | 404 /** | 
| 109 * @param {!TimelineModel.TimelineProfileTree.Node} topDownTree | |
| 110 * @return {!TimelineModel.TimelineProfileTree.Node} | |
| 111 */ | |
| 112 TimelineModel.TimelineProfileTree.buildBottomUp = function(topDownTree) { | |
| 113 var buRoot = new TimelineModel.TimelineProfileTree.Node(); | |
| 114 var aggregator = new TimelineModel.TimelineAggregator(); | |
| 115 buRoot.selfTime = 0; | |
| 116 buRoot.totalTime = 0; | |
| 117 /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Node>} */ | |
| 118 buRoot.children = new Map(); | |
| 119 var nodesOnStack = /** @type {!Set<string>} */ (new Set()); | |
| 120 if (topDownTree.children) | |
| 121 topDownTree.children.forEach(processNode); | |
| 122 buRoot.totalTime = topDownTree.totalTime; | |
| 123 | |
| 124 /** | |
| 125 * @param {!TimelineModel.TimelineProfileTree.Node} tdNode | |
| 126 */ | |
| 127 function processNode(tdNode) { | |
| 128 var buParent = | |
| 129 typeof tdNode._groupId === 'string' ? aggregator.groupNodeForId(tdNode._ groupId, tdNode.event) : buRoot; | |
| 130 if (buParent !== buRoot && !buParent.parent) { | |
| 131 buRoot.children.set(buParent.id, buParent); | |
| 132 buParent.parent = buRoot; | |
| 133 } | |
| 134 appendNode(tdNode, buParent); | |
| 135 var hadNode = nodesOnStack.has(tdNode.id); | |
| 136 if (!hadNode) | |
| 137 nodesOnStack.add(tdNode.id); | |
| 138 if (tdNode.children) | |
| 139 tdNode.children.forEach(processNode); | |
| 140 if (!hadNode) | |
| 141 nodesOnStack.delete(tdNode.id); | |
| 142 } | |
| 143 | |
| 144 /** | |
| 145 * @param {!TimelineModel.TimelineProfileTree.Node} tdNode | |
| 146 * @param {!TimelineModel.TimelineProfileTree.Node} buParent | |
| 147 */ | |
| 148 function appendNode(tdNode, buParent) { | |
| 149 var selfTime = tdNode.selfTime; | |
| 150 var totalTime = tdNode.totalTime; | |
| 151 buParent.selfTime += selfTime; | |
| 152 buParent.totalTime += selfTime; | |
| 153 while (tdNode.parent) { | |
| 154 if (!buParent.children) | |
| 155 buParent.children = /** @type {!Map<string,!TimelineModel.TimelineProfil eTree.Node>} */ (new Map()); | |
| 156 var id = tdNode.id; | |
| 157 var buNode = buParent.children.get(id); | |
| 158 if (!buNode) { | |
| 159 buNode = new TimelineModel.TimelineProfileTree.Node(); | |
| 160 buNode.selfTime = selfTime; | |
| 161 buNode.totalTime = totalTime; | |
| 162 buNode.event = tdNode.event; | |
| 163 buNode.id = id; | |
| 164 buNode.parent = buParent; | |
| 165 buParent.children.set(id, buNode); | |
| 166 } else { | |
| 167 buNode.selfTime += selfTime; | |
| 168 if (!nodesOnStack.has(id)) | |
| 169 buNode.totalTime += totalTime; | |
| 170 } | |
| 171 tdNode = tdNode.parent; | |
| 172 buParent = buNode; | |
| 173 } | |
| 174 } | |
| 175 | |
| 176 // Purge zero self time nodes. | |
| 177 var rootChildren = buRoot.children; | |
| 178 for (var item of rootChildren.entries()) { | |
| 179 if (item[1].selfTime === 0) | |
| 180 rootChildren.delete(/** @type {string} */ (item[0])); | |
| 181 } | |
| 182 | |
| 183 return buRoot; | |
| 184 }; | |
| 185 | |
| 186 /** | |
| 187 * @param {!SDK.TracingModel.Event} event | 405 * @param {!SDK.TracingModel.Event} event | 
| 188 * @return {?string} | 406 * @return {?string} | 
| 189 */ | 407 */ | 
| 190 TimelineModel.TimelineProfileTree.eventURL = function(event) { | 408 TimelineModel.TimelineProfileTree.eventURL = function(event) { | 
| 191 var data = event.args['data'] || event.args['beginData']; | 409 var data = event.args['data'] || event.args['beginData']; | 
| 192 if (data && data['url']) | 410 if (data && data['url']) | 
| 193 return data['url']; | 411 return data['url']; | 
| 194 var frame = TimelineModel.TimelineProfileTree.eventStackFrame(event); | 412 var frame = TimelineModel.TimelineProfileTree.eventStackFrame(event); | 
| 195 while (frame) { | 413 while (frame) { | 
| 196 var url = frame['url']; | 414 var url = frame['url']; | 
| (...skipping 28 matching lines...) Expand all Loading... | |
| 225 TimelineModel.TimelineJSProfileProcessor.nativeGroup(functionName) || func tionName : | 443 TimelineModel.TimelineJSProfileProcessor.nativeGroup(functionName) || func tionName : | 
| 226 functionName; | 444 functionName; | 
| 227 return `f:${name}@${location}`; | 445 return `f:${name}@${location}`; | 
| 228 }; | 446 }; | 
| 229 | 447 | 
| 230 /** | 448 /** | 
| 231 * @unrestricted | 449 * @unrestricted | 
| 232 */ | 450 */ | 
| 233 TimelineModel.TimelineAggregator = class { | 451 TimelineModel.TimelineAggregator = class { | 
| 234 constructor() { | 452 constructor() { | 
| 235 /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Node>} */ | 453 /** @type {!Map<string, !TimelineModel.TimelineProfileTree.TopDownNode>} */ | 
| 236 this._groupNodes = new Map(); | 454 this._groupNodes = new Map(); | 
| 237 } | 455 } | 
| 238 | 456 | 
| 239 /** | 457 /** | 
| 240 * @param {!TimelineModel.TimelineProfileTree.Node} root | 458 * @param {!TimelineModel.TimelineProfileTree.Node} root | 
| 241 * @return {!TimelineModel.TimelineProfileTree.Node} | 459 * @return {!TimelineModel.TimelineProfileTree.Node} | 
| 242 */ | 460 */ | 
| 243 performGrouping(root) { | 461 performGrouping(root) { | 
| 244 for (var node of root.children.values()) { | 462 for (var node of root.children().values()) { | 
| 245 var groupNode = this.groupNodeForId(node._groupId, node.event); | 463 var groupNode = this.groupNodeForId(node._groupId, /** @type {!SDK.Tracing Model.Event} */ (node.event)); | 
| 246 groupNode.parent = root; | 464 groupNode.parent = root; | 
| 247 groupNode.selfTime += node.selfTime; | 465 groupNode.selfTime += node.selfTime; | 
| 248 groupNode.totalTime += node.totalTime; | 466 groupNode.totalTime += node.totalTime; | 
| 249 groupNode.children.set(node.id, node); | 467 groupNode.children().set(node.id, node); | 
| 250 node.parent = root; | 468 node.parent = root; | 
| 251 } | 469 } | 
| 252 root.children = this._groupNodes; | 470 root._children = this._groupNodes; | 
| 253 return root; | 471 return root; | 
| 254 } | 472 } | 
| 255 | 473 | 
| 256 /** | 474 /** | 
| 257 * @param {string} groupId | 475 * @param {string} groupId | 
| 258 * @param {!SDK.TracingModel.Event} event | 476 * @param {!SDK.TracingModel.Event} event | 
| 259 * @return {!TimelineModel.TimelineProfileTree.Node} | 477 * @return {!TimelineModel.TimelineProfileTree.Node} | 
| 260 */ | 478 */ | 
| 261 groupNodeForId(groupId, event) { | 479 groupNodeForId(groupId, event) { | 
| 262 var node = this._groupNodes.get(groupId); | 480 var node = this._groupNodes.get(groupId); | 
| 263 return node || this._buildGroupNode(groupId, event); | 481 return node || this._buildGroupNode(groupId, event); | 
| 264 } | 482 } | 
| 265 | 483 | 
| 266 /** | 484 /** | 
| 267 * @param {string} id | 485 * @param {string} id | 
| 268 * @param {!SDK.TracingModel.Event} event | 486 * @param {!SDK.TracingModel.Event} event | 
| 269 * @return {!TimelineModel.TimelineProfileTree.Node} | 487 * @return {!TimelineModel.TimelineProfileTree.Node} | 
| 270 */ | 488 */ | 
| 271 _buildGroupNode(id, event) { | 489 _buildGroupNode(id, event) { | 
| 272 var groupNode = new TimelineModel.TimelineProfileTree.Node(); | 490 var groupNode = new TimelineModel.TimelineProfileTree.TopDownNode(id, event) ; | 
| 273 groupNode.id = id; | |
| 274 groupNode.selfTime = 0; | 491 groupNode.selfTime = 0; | 
| 275 groupNode.totalTime = 0; | 492 groupNode.totalTime = 0; | 
| 276 groupNode.children = new Map(); | |
| 277 groupNode.event = event; | |
| 278 groupNode._isGroupNode = true; | 493 groupNode._isGroupNode = true; | 
| 279 this._groupNodes.set(id, groupNode); | 494 this._groupNodes.set(id, groupNode); | 
| 280 return groupNode; | 495 return groupNode; | 
| 281 } | 496 } | 
| 282 }; | 497 }; | 
| 283 | |
| 284 TimelineModel.TimelineAggregator._groupNodeFlag = Symbol('groupNode'); | |
| OLD | NEW |