| 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 WebInspector.TimelineProfileTree = {}; | 5 TimelineModel.TimelineProfileTree = {}; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * @unrestricted | 8 * @unrestricted |
| 9 */ | 9 */ |
| 10 WebInspector.TimelineProfileTree.Node = class { | 10 TimelineModel.TimelineProfileTree.Node = class { |
| 11 constructor() { | 11 constructor() { |
| 12 /** @type {number} */ | 12 /** @type {number} */ |
| 13 this.totalTime; | 13 this.totalTime; |
| 14 /** @type {number} */ | 14 /** @type {number} */ |
| 15 this.selfTime; | 15 this.selfTime; |
| 16 /** @type {string} */ | 16 /** @type {string} */ |
| 17 this.id; | 17 this.id; |
| 18 /** @type {!WebInspector.TracingModel.Event} */ | 18 /** @type {!SDK.TracingModel.Event} */ |
| 19 this.event; | 19 this.event; |
| 20 /** @type {?Map<string|symbol,!WebInspector.TimelineProfileTree.Node>} */ | 20 /** @type {?Map<string|symbol,!TimelineModel.TimelineProfileTree.Node>} */ |
| 21 this.children; | 21 this.children; |
| 22 /** @type {?WebInspector.TimelineProfileTree.Node} */ | 22 /** @type {?TimelineModel.TimelineProfileTree.Node} */ |
| 23 this.parent; | 23 this.parent; |
| 24 | 24 |
| 25 /** @type {string} */ | 25 /** @type {string} */ |
| 26 this._groupId = ''; | 26 this._groupId = ''; |
| 27 this._isGroupNode = false; | 27 this._isGroupNode = false; |
| 28 } | 28 } |
| 29 | 29 |
| 30 /** | 30 /** |
| 31 * @return {boolean} | 31 * @return {boolean} |
| 32 */ | 32 */ |
| 33 isGroupNode() { | 33 isGroupNode() { |
| 34 return this._isGroupNode; | 34 return this._isGroupNode; |
| 35 } | 35 } |
| 36 }; | 36 }; |
| 37 | 37 |
| 38 /** | 38 /** |
| 39 * @param {!Array<!WebInspector.TracingModel.Event>} events | 39 * @param {!Array<!SDK.TracingModel.Event>} events |
| 40 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters | 40 * @param {!Array<!TimelineModel.TimelineModel.Filter>} filters |
| 41 * @param {number} startTime | 41 * @param {number} startTime |
| 42 * @param {number} endTime | 42 * @param {number} endTime |
| 43 * @param {function(!WebInspector.TracingModel.Event):string=} eventGroupIdCallb
ack | 43 * @param {function(!SDK.TracingModel.Event):string=} eventGroupIdCallback |
| 44 * @return {!WebInspector.TimelineProfileTree.Node} | 44 * @return {!TimelineModel.TimelineProfileTree.Node} |
| 45 */ | 45 */ |
| 46 WebInspector.TimelineProfileTree.buildTopDown = function(events, filters, startT
ime, endTime, eventGroupIdCallback) { | 46 TimelineModel.TimelineProfileTree.buildTopDown = function(events, filters, start
Time, endTime, eventGroupIdCallback) { |
| 47 // Temporarily deposit a big enough value that exceeds the max recording time. | 47 // Temporarily deposit a big enough value that exceeds the max recording time. |
| 48 var /** @const */ initialTime = 1e7; | 48 var /** @const */ initialTime = 1e7; |
| 49 var root = new WebInspector.TimelineProfileTree.Node(); | 49 var root = new TimelineModel.TimelineProfileTree.Node(); |
| 50 root.totalTime = initialTime; | 50 root.totalTime = initialTime; |
| 51 root.selfTime = initialTime; | 51 root.selfTime = initialTime; |
| 52 root.children = /** @type {!Map<string, !WebInspector.TimelineProfileTree.Node
>} */ (new Map()); | 52 root.children = /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Nod
e>} */ (new Map()); |
| 53 var parent = root; | 53 var parent = root; |
| 54 | 54 |
| 55 /** | 55 /** |
| 56 * @param {!WebInspector.TracingModel.Event} e | 56 * @param {!SDK.TracingModel.Event} e |
| 57 */ | 57 */ |
| 58 function onStartEvent(e) { | 58 function onStartEvent(e) { |
| 59 if (!WebInspector.TimelineModel.isVisible(filters, e)) | 59 if (!TimelineModel.TimelineModel.isVisible(filters, e)) |
| 60 return; | 60 return; |
| 61 var time = e.endTime ? Math.min(endTime, e.endTime) - Math.max(startTime, e.
startTime) : 0; | 61 var time = e.endTime ? Math.min(endTime, e.endTime) - Math.max(startTime, e.
startTime) : 0; |
| 62 var groupId = eventGroupIdCallback ? eventGroupIdCallback(e) : Symbol('uniqu
eGroupId'); | 62 var groupId = eventGroupIdCallback ? eventGroupIdCallback(e) : Symbol('uniqu
eGroupId'); |
| 63 var id = eventGroupIdCallback ? WebInspector.TimelineProfileTree._eventId(e)
: Symbol('uniqueEventId'); | 63 var id = eventGroupIdCallback ? TimelineModel.TimelineProfileTree._eventId(e
) : Symbol('uniqueEventId'); |
| 64 if (typeof groupId === 'string' && typeof id === 'string') | 64 if (typeof groupId === 'string' && typeof id === 'string') |
| 65 id += '/' + groupId; | 65 id += '/' + groupId; |
| 66 if (!parent.children) | 66 if (!parent.children) |
| 67 parent.children = /** @type {!Map<string,!WebInspector.TimelineProfileTree
.Node>} */ (new Map()); | 67 parent.children = /** @type {!Map<string,!TimelineModel.TimelineProfileTre
e.Node>} */ (new Map()); |
| 68 var node = parent.children.get(id); | 68 var node = parent.children.get(id); |
| 69 if (node) { | 69 if (node) { |
| 70 node.selfTime += time; | 70 node.selfTime += time; |
| 71 node.totalTime += time; | 71 node.totalTime += time; |
| 72 } else { | 72 } else { |
| 73 node = new WebInspector.TimelineProfileTree.Node(); | 73 node = new TimelineModel.TimelineProfileTree.Node(); |
| 74 node.totalTime = time; | 74 node.totalTime = time; |
| 75 node.selfTime = time; | 75 node.selfTime = time; |
| 76 node.parent = parent; | 76 node.parent = parent; |
| 77 node.id = id; | 77 node.id = id; |
| 78 node.event = e; | 78 node.event = e; |
| 79 node._groupId = groupId; | 79 node._groupId = groupId; |
| 80 parent.children.set(id, node); | 80 parent.children.set(id, node); |
| 81 } | 81 } |
| 82 parent.selfTime -= time; | 82 parent.selfTime -= time; |
| 83 if (parent.selfTime < 0) { | 83 if (parent.selfTime < 0) { |
| 84 console.log('Error: Negative self of ' + parent.selfTime, e); | 84 console.log('Error: Negative self of ' + parent.selfTime, e); |
| 85 parent.selfTime = 0; | 85 parent.selfTime = 0; |
| 86 } | 86 } |
| 87 if (e.endTime) | 87 if (e.endTime) |
| 88 parent = node; | 88 parent = node; |
| 89 } | 89 } |
| 90 | 90 |
| 91 /** | 91 /** |
| 92 * @param {!WebInspector.TracingModel.Event} e | 92 * @param {!SDK.TracingModel.Event} e |
| 93 */ | 93 */ |
| 94 function onEndEvent(e) { | 94 function onEndEvent(e) { |
| 95 if (!WebInspector.TimelineModel.isVisible(filters, e)) | 95 if (!TimelineModel.TimelineModel.isVisible(filters, e)) |
| 96 return; | 96 return; |
| 97 parent = parent.parent; | 97 parent = parent.parent; |
| 98 } | 98 } |
| 99 | 99 |
| 100 var instantEventCallback = eventGroupIdCallback ? undefined : onStartEvent; /
/ Ignore instant events when aggregating. | 100 var instantEventCallback = eventGroupIdCallback ? undefined : onStartEvent; /
/ Ignore instant events when aggregating. |
| 101 WebInspector.TimelineModel.forEachEvent(events, onStartEvent, onEndEvent, inst
antEventCallback, startTime, endTime); | 101 TimelineModel.TimelineModel.forEachEvent(events, onStartEvent, onEndEvent, ins
tantEventCallback, startTime, endTime); |
| 102 root.totalTime -= root.selfTime; | 102 root.totalTime -= root.selfTime; |
| 103 root.selfTime = 0; | 103 root.selfTime = 0; |
| 104 return root; | 104 return root; |
| 105 }; | 105 }; |
| 106 | 106 |
| 107 /** | 107 /** |
| 108 * @param {!WebInspector.TimelineProfileTree.Node} topDownTree | 108 * @param {!TimelineModel.TimelineProfileTree.Node} topDownTree |
| 109 * @return {!WebInspector.TimelineProfileTree.Node} | 109 * @return {!TimelineModel.TimelineProfileTree.Node} |
| 110 */ | 110 */ |
| 111 WebInspector.TimelineProfileTree.buildBottomUp = function(topDownTree) { | 111 TimelineModel.TimelineProfileTree.buildBottomUp = function(topDownTree) { |
| 112 var buRoot = new WebInspector.TimelineProfileTree.Node(); | 112 var buRoot = new TimelineModel.TimelineProfileTree.Node(); |
| 113 var aggregator = new WebInspector.TimelineAggregator(); | 113 var aggregator = new TimelineModel.TimelineAggregator(); |
| 114 buRoot.selfTime = 0; | 114 buRoot.selfTime = 0; |
| 115 buRoot.totalTime = 0; | 115 buRoot.totalTime = 0; |
| 116 /** @type {!Map<string, !WebInspector.TimelineProfileTree.Node>} */ | 116 /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Node>} */ |
| 117 buRoot.children = new Map(); | 117 buRoot.children = new Map(); |
| 118 var nodesOnStack = /** @type {!Set<string>} */ (new Set()); | 118 var nodesOnStack = /** @type {!Set<string>} */ (new Set()); |
| 119 if (topDownTree.children) | 119 if (topDownTree.children) |
| 120 topDownTree.children.forEach(processNode); | 120 topDownTree.children.forEach(processNode); |
| 121 buRoot.totalTime = topDownTree.totalTime; | 121 buRoot.totalTime = topDownTree.totalTime; |
| 122 | 122 |
| 123 /** | 123 /** |
| 124 * @param {!WebInspector.TimelineProfileTree.Node} tdNode | 124 * @param {!TimelineModel.TimelineProfileTree.Node} tdNode |
| 125 */ | 125 */ |
| 126 function processNode(tdNode) { | 126 function processNode(tdNode) { |
| 127 var buParent = typeof tdNode._groupId === 'string' ? aggregator.groupNodeFor
Id(tdNode._groupId, tdNode.event) : buRoot; | 127 var buParent = typeof tdNode._groupId === 'string' ? aggregator.groupNodeFor
Id(tdNode._groupId, tdNode.event) : buRoot; |
| 128 if (buParent !== buRoot && !buParent.parent) { | 128 if (buParent !== buRoot && !buParent.parent) { |
| 129 buRoot.children.set(buParent.id, buParent); | 129 buRoot.children.set(buParent.id, buParent); |
| 130 buParent.parent = buRoot; | 130 buParent.parent = buRoot; |
| 131 } | 131 } |
| 132 appendNode(tdNode, buParent); | 132 appendNode(tdNode, buParent); |
| 133 var hadNode = nodesOnStack.has(tdNode.id); | 133 var hadNode = nodesOnStack.has(tdNode.id); |
| 134 if (!hadNode) | 134 if (!hadNode) |
| 135 nodesOnStack.add(tdNode.id); | 135 nodesOnStack.add(tdNode.id); |
| 136 if (tdNode.children) | 136 if (tdNode.children) |
| 137 tdNode.children.forEach(processNode); | 137 tdNode.children.forEach(processNode); |
| 138 if (!hadNode) | 138 if (!hadNode) |
| 139 nodesOnStack.delete(tdNode.id); | 139 nodesOnStack.delete(tdNode.id); |
| 140 } | 140 } |
| 141 | 141 |
| 142 /** | 142 /** |
| 143 * @param {!WebInspector.TimelineProfileTree.Node} tdNode | 143 * @param {!TimelineModel.TimelineProfileTree.Node} tdNode |
| 144 * @param {!WebInspector.TimelineProfileTree.Node} buParent | 144 * @param {!TimelineModel.TimelineProfileTree.Node} buParent |
| 145 */ | 145 */ |
| 146 function appendNode(tdNode, buParent) { | 146 function appendNode(tdNode, buParent) { |
| 147 var selfTime = tdNode.selfTime; | 147 var selfTime = tdNode.selfTime; |
| 148 var totalTime = tdNode.totalTime; | 148 var totalTime = tdNode.totalTime; |
| 149 buParent.selfTime += selfTime; | 149 buParent.selfTime += selfTime; |
| 150 buParent.totalTime += selfTime; | 150 buParent.totalTime += selfTime; |
| 151 while (tdNode.parent) { | 151 while (tdNode.parent) { |
| 152 if (!buParent.children) | 152 if (!buParent.children) |
| 153 buParent.children = /** @type {!Map<string,!WebInspector.TimelineProfile
Tree.Node>} */ (new Map()); | 153 buParent.children = /** @type {!Map<string,!TimelineModel.TimelineProfil
eTree.Node>} */ (new Map()); |
| 154 var id = tdNode.id; | 154 var id = tdNode.id; |
| 155 var buNode = buParent.children.get(id); | 155 var buNode = buParent.children.get(id); |
| 156 if (!buNode) { | 156 if (!buNode) { |
| 157 buNode = new WebInspector.TimelineProfileTree.Node(); | 157 buNode = new TimelineModel.TimelineProfileTree.Node(); |
| 158 buNode.selfTime = selfTime; | 158 buNode.selfTime = selfTime; |
| 159 buNode.totalTime = totalTime; | 159 buNode.totalTime = totalTime; |
| 160 buNode.event = tdNode.event; | 160 buNode.event = tdNode.event; |
| 161 buNode.id = id; | 161 buNode.id = id; |
| 162 buNode.parent = buParent; | 162 buNode.parent = buParent; |
| 163 buParent.children.set(id, buNode); | 163 buParent.children.set(id, buNode); |
| 164 } else { | 164 } else { |
| 165 buNode.selfTime += selfTime; | 165 buNode.selfTime += selfTime; |
| 166 if (!nodesOnStack.has(id)) | 166 if (!nodesOnStack.has(id)) |
| 167 buNode.totalTime += totalTime; | 167 buNode.totalTime += totalTime; |
| 168 } | 168 } |
| 169 tdNode = tdNode.parent; | 169 tdNode = tdNode.parent; |
| 170 buParent = buNode; | 170 buParent = buNode; |
| 171 } | 171 } |
| 172 } | 172 } |
| 173 | 173 |
| 174 // Purge zero self time nodes. | 174 // Purge zero self time nodes. |
| 175 var rootChildren = buRoot.children; | 175 var rootChildren = buRoot.children; |
| 176 for (var item of rootChildren.entries()) { | 176 for (var item of rootChildren.entries()) { |
| 177 if (item[1].selfTime === 0) | 177 if (item[1].selfTime === 0) |
| 178 rootChildren.delete(/** @type {string} */ (item[0])); | 178 rootChildren.delete(/** @type {string} */ (item[0])); |
| 179 } | 179 } |
| 180 | 180 |
| 181 return buRoot; | 181 return buRoot; |
| 182 }; | 182 }; |
| 183 | 183 |
| 184 /** | 184 /** |
| 185 * @param {!WebInspector.TracingModel.Event} event | 185 * @param {!SDK.TracingModel.Event} event |
| 186 * @return {?string} | 186 * @return {?string} |
| 187 */ | 187 */ |
| 188 WebInspector.TimelineProfileTree.eventURL = function(event) { | 188 TimelineModel.TimelineProfileTree.eventURL = function(event) { |
| 189 var data = event.args['data'] || event.args['beginData']; | 189 var data = event.args['data'] || event.args['beginData']; |
| 190 if (data && data['url']) | 190 if (data && data['url']) |
| 191 return data['url']; | 191 return data['url']; |
| 192 var frame = WebInspector.TimelineProfileTree.eventStackFrame(event); | 192 var frame = TimelineModel.TimelineProfileTree.eventStackFrame(event); |
| 193 while (frame) { | 193 while (frame) { |
| 194 var url = frame['url']; | 194 var url = frame['url']; |
| 195 if (url) | 195 if (url) |
| 196 return url; | 196 return url; |
| 197 frame = frame.parent; | 197 frame = frame.parent; |
| 198 } | 198 } |
| 199 return null; | 199 return null; |
| 200 }; | 200 }; |
| 201 | 201 |
| 202 /** | 202 /** |
| 203 * @param {!WebInspector.TracingModel.Event} event | 203 * @param {!SDK.TracingModel.Event} event |
| 204 * @return {?Protocol.Runtime.CallFrame} | 204 * @return {?Protocol.Runtime.CallFrame} |
| 205 */ | 205 */ |
| 206 WebInspector.TimelineProfileTree.eventStackFrame = function(event) { | 206 TimelineModel.TimelineProfileTree.eventStackFrame = function(event) { |
| 207 if (event.name === WebInspector.TimelineModel.RecordType.JSFrame) | 207 if (event.name === TimelineModel.TimelineModel.RecordType.JSFrame) |
| 208 return /** @type {?Protocol.Runtime.CallFrame} */ (event.args['data'] || nul
l); | 208 return /** @type {?Protocol.Runtime.CallFrame} */ (event.args['data'] || nul
l); |
| 209 return WebInspector.TimelineData.forEvent(event).topFrame(); | 209 return TimelineModel.TimelineData.forEvent(event).topFrame(); |
| 210 }; | 210 }; |
| 211 | 211 |
| 212 /** | 212 /** |
| 213 * @param {!WebInspector.TracingModel.Event} event | 213 * @param {!SDK.TracingModel.Event} event |
| 214 * @return {string} | 214 * @return {string} |
| 215 */ | 215 */ |
| 216 WebInspector.TimelineProfileTree._eventId = function(event) { | 216 TimelineModel.TimelineProfileTree._eventId = function(event) { |
| 217 if (event.name !== WebInspector.TimelineModel.RecordType.JSFrame) | 217 if (event.name !== TimelineModel.TimelineModel.RecordType.JSFrame) |
| 218 return event.name; | 218 return event.name; |
| 219 const frame = event.args['data']; | 219 const frame = event.args['data']; |
| 220 const location = frame['scriptId'] || frame['url'] || ''; | 220 const location = frame['scriptId'] || frame['url'] || ''; |
| 221 const functionName = frame['functionName']; | 221 const functionName = frame['functionName']; |
| 222 const name = WebInspector.TimelineJSProfileProcessor.isNativeRuntimeFrame(fram
e) | 222 const name = TimelineModel.TimelineJSProfileProcessor.isNativeRuntimeFrame(fra
me) |
| 223 ? WebInspector.TimelineJSProfileProcessor.nativeGroup(functionName) || fun
ctionName | 223 ? TimelineModel.TimelineJSProfileProcessor.nativeGroup(functionName) || fu
nctionName |
| 224 : functionName; | 224 : functionName; |
| 225 return `f:${name}@${location}`; | 225 return `f:${name}@${location}`; |
| 226 }; | 226 }; |
| 227 | 227 |
| 228 /** | 228 /** |
| 229 * @unrestricted | 229 * @unrestricted |
| 230 */ | 230 */ |
| 231 WebInspector.TimelineAggregator = class { | 231 TimelineModel.TimelineAggregator = class { |
| 232 constructor() { | 232 constructor() { |
| 233 /** @type {!Map<string, !WebInspector.TimelineProfileTree.Node>} */ | 233 /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Node>} */ |
| 234 this._groupNodes = new Map(); | 234 this._groupNodes = new Map(); |
| 235 } | 235 } |
| 236 | 236 |
| 237 /** | 237 /** |
| 238 * @param {!WebInspector.TimelineProfileTree.Node} root | 238 * @param {!TimelineModel.TimelineProfileTree.Node} root |
| 239 * @return {!WebInspector.TimelineProfileTree.Node} | 239 * @return {!TimelineModel.TimelineProfileTree.Node} |
| 240 */ | 240 */ |
| 241 performGrouping(root) { | 241 performGrouping(root) { |
| 242 for (var node of root.children.values()) { | 242 for (var node of root.children.values()) { |
| 243 var groupNode = this.groupNodeForId(node._groupId, node.event); | 243 var groupNode = this.groupNodeForId(node._groupId, node.event); |
| 244 groupNode.parent = root; | 244 groupNode.parent = root; |
| 245 groupNode.selfTime += node.selfTime; | 245 groupNode.selfTime += node.selfTime; |
| 246 groupNode.totalTime += node.totalTime; | 246 groupNode.totalTime += node.totalTime; |
| 247 groupNode.children.set(node.id, node); | 247 groupNode.children.set(node.id, node); |
| 248 node.parent = root; | 248 node.parent = root; |
| 249 } | 249 } |
| 250 root.children = this._groupNodes; | 250 root.children = this._groupNodes; |
| 251 return root; | 251 return root; |
| 252 } | 252 } |
| 253 | 253 |
| 254 /** | 254 /** |
| 255 * @param {string} groupId | 255 * @param {string} groupId |
| 256 * @param {!WebInspector.TracingModel.Event} event | 256 * @param {!SDK.TracingModel.Event} event |
| 257 * @return {!WebInspector.TimelineProfileTree.Node} | 257 * @return {!TimelineModel.TimelineProfileTree.Node} |
| 258 */ | 258 */ |
| 259 groupNodeForId(groupId, event) { | 259 groupNodeForId(groupId, event) { |
| 260 var node = this._groupNodes.get(groupId); | 260 var node = this._groupNodes.get(groupId); |
| 261 return node || this._buildGroupNode(groupId, event); | 261 return node || this._buildGroupNode(groupId, event); |
| 262 } | 262 } |
| 263 | 263 |
| 264 /** | 264 /** |
| 265 * @param {string} id | 265 * @param {string} id |
| 266 * @param {!WebInspector.TracingModel.Event} event | 266 * @param {!SDK.TracingModel.Event} event |
| 267 * @return {!WebInspector.TimelineProfileTree.Node} | 267 * @return {!TimelineModel.TimelineProfileTree.Node} |
| 268 */ | 268 */ |
| 269 _buildGroupNode(id, event) { | 269 _buildGroupNode(id, event) { |
| 270 var groupNode = new WebInspector.TimelineProfileTree.Node(); | 270 var groupNode = new TimelineModel.TimelineProfileTree.Node(); |
| 271 groupNode.id = id; | 271 groupNode.id = id; |
| 272 groupNode.selfTime = 0; | 272 groupNode.selfTime = 0; |
| 273 groupNode.totalTime = 0; | 273 groupNode.totalTime = 0; |
| 274 groupNode.children = new Map(); | 274 groupNode.children = new Map(); |
| 275 groupNode.event = event; | 275 groupNode.event = event; |
| 276 groupNode._isGroupNode = true; | 276 groupNode._isGroupNode = true; |
| 277 this._groupNodes.set(id, groupNode); | 277 this._groupNodes.set(id, groupNode); |
| 278 return groupNode; | 278 return groupNode; |
| 279 } | 279 } |
| 280 }; | 280 }; |
| 281 | 281 |
| 282 WebInspector.TimelineAggregator._groupNodeFlag = Symbol('groupNode'); | 282 TimelineModel.TimelineAggregator._groupNodeFlag = Symbol('groupNode'); |
| OLD | NEW |