OLD | NEW |
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 25 matching lines...) Expand all Loading... |
36 this._strings = profile.strings; | 36 this._strings = profile.strings; |
37 this._liveObjectStats = liveObjectStats; | 37 this._liveObjectStats = liveObjectStats; |
38 | 38 |
39 this._nextNodeId = 1; | 39 this._nextNodeId = 1; |
40 this._functionInfos = [] | 40 this._functionInfos = [] |
41 this._idToNode = {}; | 41 this._idToNode = {}; |
42 this._collapsedTopNodeIdToFunctionInfo = {}; | 42 this._collapsedTopNodeIdToFunctionInfo = {}; |
43 | 43 |
44 this._traceTops = null; | 44 this._traceTops = null; |
45 | 45 |
46 this._buildAllocationFunctionInfos(profile); | 46 this._buildFunctionAllocationInfos(profile); |
47 this._traceTree = this._buildInvertedAllocationTree(profile, liveObjectStats
); | 47 this._traceTree = this._buildAllocationTree(profile, liveObjectStats); |
48 } | 48 } |
49 | 49 |
50 WebInspector.AllocationProfile.prototype = { | 50 WebInspector.AllocationProfile.prototype = { |
51 _buildAllocationFunctionInfos: function(profile) | 51 _buildFunctionAllocationInfos: function(profile) |
52 { | 52 { |
53 var strings = this._strings; | 53 var strings = this._strings; |
54 | 54 |
55 var functionInfoFields = profile.snapshot.meta.trace_function_info_field
s; | 55 var functionInfoFields = profile.snapshot.meta.trace_function_info_field
s; |
56 var functionIdOffset = functionInfoFields.indexOf("function_id"); | 56 var functionIdOffset = functionInfoFields.indexOf("function_id"); |
57 var functionNameOffset = functionInfoFields.indexOf("name"); | 57 var functionNameOffset = functionInfoFields.indexOf("name"); |
58 var scriptNameOffset = functionInfoFields.indexOf("script_name"); | 58 var scriptNameOffset = functionInfoFields.indexOf("script_name"); |
59 var scriptIdOffset = functionInfoFields.indexOf("script_id"); | 59 var scriptIdOffset = functionInfoFields.indexOf("script_id"); |
60 var lineOffset = functionInfoFields.indexOf("line"); | 60 var lineOffset = functionInfoFields.indexOf("line"); |
61 var columnOffset = functionInfoFields.indexOf("column"); | 61 var columnOffset = functionInfoFields.indexOf("column"); |
62 var functionInfoFieldCount = functionInfoFields.length; | 62 var functionInfoFieldCount = functionInfoFields.length; |
63 | 63 |
64 var rawInfos = profile.trace_function_infos; | 64 var rawInfos = profile.trace_function_infos; |
65 var infoLength = rawInfos.length; | 65 var infoLength = rawInfos.length; |
66 var functionInfos = this._functionInfos = new Array(infoLength / functio
nInfoFieldCount); | 66 var functionInfos = this._functionInfos = new Array(infoLength / functio
nInfoFieldCount); |
67 var index = 0; | 67 var index = 0; |
68 for (var i = 0; i < infoLength; i += functionInfoFieldCount) { | 68 for (var i = 0; i < infoLength; i += functionInfoFieldCount) { |
69 functionInfos[index++] = new WebInspector.FunctionAllocationInfo( | 69 functionInfos[index++] = new WebInspector.FunctionAllocationInfo( |
70 strings[rawInfos[i + functionNameOffset]], | 70 strings[rawInfos[i + functionNameOffset]], |
71 strings[rawInfos[i + scriptNameOffset]], | 71 strings[rawInfos[i + scriptNameOffset]], |
72 rawInfos[i + scriptIdOffset], | 72 rawInfos[i + scriptIdOffset], |
73 rawInfos[i + lineOffset], | 73 rawInfos[i + lineOffset], |
74 rawInfos[i + columnOffset]); | 74 rawInfos[i + columnOffset]); |
75 } | 75 } |
76 }, | 76 }, |
77 | 77 |
78 _buildInvertedAllocationTree: function(profile, liveObjectStats) | 78 _buildAllocationTree: function(profile, liveObjectStats) |
79 { | 79 { |
80 var traceTreeRaw = profile.trace_tree; | 80 var traceTreeRaw = profile.trace_tree; |
81 var functionInfos = this._functionInfos; | 81 var functionInfos = this._functionInfos; |
82 | 82 |
83 var traceNodeFields = profile.snapshot.meta.trace_node_fields; | 83 var traceNodeFields = profile.snapshot.meta.trace_node_fields; |
84 var nodeIdOffset = traceNodeFields.indexOf("id"); | 84 var nodeIdOffset = traceNodeFields.indexOf("id"); |
85 var functionInfoIndexOffset = traceNodeFields.indexOf("function_info_ind
ex"); | 85 var functionInfoIndexOffset = traceNodeFields.indexOf("function_info_ind
ex"); |
86 var allocationCountOffset = traceNodeFields.indexOf("count"); | 86 var allocationCountOffset = traceNodeFields.indexOf("count"); |
87 var allocationSizeOffset = traceNodeFields.indexOf("size"); | 87 var allocationSizeOffset = traceNodeFields.indexOf("size"); |
88 var childrenOffset = traceNodeFields.indexOf("children"); | 88 var childrenOffset = traceNodeFields.indexOf("children"); |
89 var nodeFieldCount = traceNodeFields.length; | 89 var nodeFieldCount = traceNodeFields.length; |
90 | 90 |
91 function traverseNode(rawNodeArray, nodeOffset, parent) | 91 function traverseNode(rawNodeArray, nodeOffset, parent) |
92 { | 92 { |
93 var functionInfo = functionInfos[rawNodeArray[nodeOffset + functionI
nfoIndexOffset]]; | 93 var functionInfo = functionInfos[rawNodeArray[nodeOffset + functionI
nfoIndexOffset]]; |
94 var id = rawNodeArray[nodeOffset + nodeIdOffset]; | 94 var id = rawNodeArray[nodeOffset + nodeIdOffset]; |
95 var stats = liveObjectStats[id]; | 95 var stats = liveObjectStats[id]; |
96 var liveCount = stats ? stats.count : 0; | 96 var liveCount = stats ? stats.count : 0; |
97 var liveSize = stats ? stats.size : 0; | 97 var liveSize = stats ? stats.size : 0; |
98 var result = new WebInspector.AllocationTraceNode( | 98 var result = new WebInspector.TopDownAllocationNode( |
99 id, | 99 id, |
100 functionInfo, | 100 functionInfo, |
101 rawNodeArray[nodeOffset + allocationCountOffset], | 101 rawNodeArray[nodeOffset + allocationCountOffset], |
102 rawNodeArray[nodeOffset + allocationSizeOffset], | 102 rawNodeArray[nodeOffset + allocationSizeOffset], |
103 liveCount, | 103 liveCount, |
104 liveSize, | 104 liveSize, |
105 parent); | 105 parent); |
106 functionInfo.addTraceTopNode(result); | 106 functionInfo.addTraceTopNode(result); |
107 | 107 |
108 var rawChildren = rawNodeArray[nodeOffset + childrenOffset]; | 108 var rawChildren = rawNodeArray[nodeOffset + childrenOffset]; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 | 147 |
148 /** | 148 /** |
149 * @param {string} nodeId | 149 * @param {string} nodeId |
150 * @return {!WebInspector.HeapSnapshotCommon.AllocationNodeCallers} | 150 * @return {!WebInspector.HeapSnapshotCommon.AllocationNodeCallers} |
151 */ | 151 */ |
152 serializeCallers: function(nodeId) | 152 serializeCallers: function(nodeId) |
153 { | 153 { |
154 var node = this._idToNode[nodeId]; | 154 var node = this._idToNode[nodeId]; |
155 if (!node) { | 155 if (!node) { |
156 var functionInfo = this._collapsedTopNodeIdToFunctionInfo[nodeId]; | 156 var functionInfo = this._collapsedTopNodeIdToFunctionInfo[nodeId]; |
157 node = functionInfo.tracesWithThisTop(); | 157 node = functionInfo.bottomUpRoot(); |
158 delete this._collapsedTopNodeIdToFunctionInfo[nodeId]; | 158 delete this._collapsedTopNodeIdToFunctionInfo[nodeId]; |
159 this._idToNode[nodeId] = node; | 159 this._idToNode[nodeId] = node; |
160 } | 160 } |
161 | 161 |
162 var nodesWithSingleCaller = []; | 162 var nodesWithSingleCaller = []; |
163 while (node.callers().length === 1) { | 163 while (node.callers().length === 1) { |
164 node = node.callers()[0]; | 164 node = node.callers()[0]; |
165 nodesWithSingleCaller.push(this._serializeCaller(node)); | 165 nodesWithSingleCaller.push(this._serializeCaller(node)); |
166 } | 166 } |
167 | 167 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 liveCount, | 210 liveCount, |
211 liveSize, | 211 liveSize, |
212 hasChildren | 212 hasChildren |
213 ); | 213 ); |
214 } | 214 } |
215 } | 215 } |
216 | 216 |
217 | 217 |
218 /** | 218 /** |
219 * @constructor | 219 * @constructor |
| 220 * @param {number} id |
| 221 * @param {!WebInspector.FunctionAllocationInfo} functionInfo |
| 222 * @param {number} count |
| 223 * @param {number} size |
| 224 * @param {number} liveCount |
| 225 * @param {number} liveSize |
| 226 * @param {?WebInspector.TopDownAllocationNode} parent |
220 */ | 227 */ |
221 WebInspector.AllocationTraceNode = function(id, functionInfo, count, size, liveC
ount, liveSize, parent) | 228 WebInspector.TopDownAllocationNode = function(id, functionInfo, count, size, liv
eCount, liveSize, parent) |
222 { | 229 { |
223 this.id = id; | 230 this.id = id; |
224 this.functionInfo = functionInfo; | 231 this.functionInfo = functionInfo; |
225 this.allocationCount = count; | 232 this.allocationCount = count; |
226 this.allocationSize = size; | 233 this.allocationSize = size; |
227 this.liveCount = liveCount; | 234 this.liveCount = liveCount; |
228 this.liveSize = liveSize; | 235 this.liveSize = liveSize; |
229 this.parent = parent; | 236 this.parent = parent; |
230 this.children = []; | 237 this.children = []; |
231 } | 238 } |
232 | 239 |
233 | 240 |
234 /** | 241 /** |
235 * @constructor | 242 * @constructor |
236 * @param {!WebInspector.FunctionAllocationInfo} functionInfo | 243 * @param {!WebInspector.FunctionAllocationInfo} functionInfo |
237 */ | 244 */ |
238 WebInspector.AllocationBackTraceNode = function(functionInfo) | 245 WebInspector.BottomUpAllocationNode = function(functionInfo) |
239 { | 246 { |
240 this.functionInfo = functionInfo; | 247 this.functionInfo = functionInfo; |
241 this.allocationCount = 0; | 248 this.allocationCount = 0; |
242 this.allocationSize = 0; | 249 this.allocationSize = 0; |
243 this.liveCount = 0; | 250 this.liveCount = 0; |
244 this.liveSize = 0; | 251 this.liveSize = 0; |
245 this._callers = []; | 252 this._callers = []; |
246 } | 253 } |
247 | 254 |
248 | 255 |
249 WebInspector.AllocationBackTraceNode.prototype = { | 256 WebInspector.BottomUpAllocationNode.prototype = { |
250 /** | 257 /** |
251 * @param {!WebInspector.AllocationTraceNode} traceNode | 258 * @param {!WebInspector.TopDownAllocationNode} traceNode |
252 * @return {!WebInspector.AllocationTraceNode} | 259 * @return {!WebInspector.TopDownAllocationNode} |
253 */ | 260 */ |
254 addCaller: function(traceNode) | 261 addCaller: function(traceNode) |
255 { | 262 { |
256 var functionInfo = traceNode.functionInfo; | 263 var functionInfo = traceNode.functionInfo; |
257 var result; | 264 var result; |
258 for (var i = 0; i < this._callers.length; i++) { | 265 for (var i = 0; i < this._callers.length; i++) { |
259 var caller = this._callers[i]; | 266 var caller = this._callers[i]; |
260 if (caller.functionInfo === functionInfo) { | 267 if (caller.functionInfo === functionInfo) { |
261 result = caller; | 268 result = caller; |
262 break; | 269 break; |
263 } | 270 } |
264 } | 271 } |
265 if (!result) { | 272 if (!result) { |
266 result = new WebInspector.AllocationBackTraceNode(functionInfo); | 273 result = new WebInspector.BottomUpAllocationNode(functionInfo); |
267 this._callers.push(result); | 274 this._callers.push(result); |
268 } | 275 } |
269 return result; | 276 return result; |
270 }, | 277 }, |
271 | 278 |
272 /** | 279 /** |
273 * @return {!Array.<!WebInspector.AllocationBackTraceNode>} | 280 * @return {!Array.<!WebInspector.BottomUpAllocationNode>} |
274 */ | 281 */ |
275 callers: function() | 282 callers: function() |
276 { | 283 { |
277 return this._callers; | 284 return this._callers; |
278 }, | 285 }, |
279 | 286 |
280 /** | 287 /** |
281 * @return {boolean} | 288 * @return {boolean} |
282 */ | 289 */ |
283 hasCallers: function() | 290 hasCallers: function() |
284 { | 291 { |
285 return this._callers.length > 0; | 292 return this._callers.length > 0; |
286 } | 293 } |
287 } | 294 } |
288 | 295 |
289 | 296 |
290 /** | 297 /** |
291 * @constructor | 298 * @constructor |
| 299 * @param {string} functionName |
| 300 * @param {string} scriptName |
| 301 * @param {number} scriptId |
| 302 * @param {number} line |
| 303 * @param {number} column |
292 */ | 304 */ |
293 WebInspector.FunctionAllocationInfo = function(functionName, scriptName, scriptI
d, line, column) | 305 WebInspector.FunctionAllocationInfo = function(functionName, scriptName, scriptI
d, line, column) |
294 { | 306 { |
295 this.functionName = functionName; | 307 this.functionName = functionName; |
296 this.scriptName = scriptName; | 308 this.scriptName = scriptName; |
297 this.scriptId = scriptId; | 309 this.scriptId = scriptId; |
298 this.line = line; | 310 this.line = line; |
299 this.column = column; | 311 this.column = column; |
300 this.totalCount = 0; | 312 this.totalCount = 0; |
301 this.totalSize = 0; | 313 this.totalSize = 0; |
302 this.totalLiveCount = 0; | 314 this.totalLiveCount = 0; |
303 this.totalLiveSize = 0; | 315 this.totalLiveSize = 0; |
304 this._traceTops = []; | 316 this._traceTops = []; |
305 } | 317 } |
306 | 318 |
307 WebInspector.FunctionAllocationInfo.prototype = { | 319 WebInspector.FunctionAllocationInfo.prototype = { |
| 320 /** |
| 321 * @param {!WebInspector.TopDownAllocationNode} node |
| 322 */ |
308 addTraceTopNode: function(node) | 323 addTraceTopNode: function(node) |
309 { | 324 { |
310 if (node.allocationCount === 0) | 325 if (node.allocationCount === 0) |
311 return; | 326 return; |
312 this._traceTops.push(node); | 327 this._traceTops.push(node); |
313 this.totalCount += node.allocationCount; | 328 this.totalCount += node.allocationCount; |
314 this.totalSize += node.allocationSize; | 329 this.totalSize += node.allocationSize; |
315 this.totalLiveCount += node.liveCount; | 330 this.totalLiveCount += node.liveCount; |
316 this.totalLiveSize += node.liveSize; | 331 this.totalLiveSize += node.liveSize; |
317 }, | 332 }, |
318 | 333 |
319 /** | 334 /** |
320 * @return {?WebInspector.AllocationBackTraceNode} | 335 * @return {?WebInspector.BottomUpAllocationNode} |
321 */ | 336 */ |
322 tracesWithThisTop: function() | 337 bottomUpRoot: function() |
323 { | 338 { |
324 if (!this._traceTops.length) | 339 if (!this._traceTops.length) |
325 return null; | 340 return null; |
326 if (!this._backTraceTree) | 341 if (!this._bottomUpTree) |
327 this._buildAllocationTraceTree(); | 342 this._buildAllocationTraceTree(); |
328 return this._backTraceTree; | 343 return this._bottomUpTree; |
329 }, | 344 }, |
330 | 345 |
331 _buildAllocationTraceTree: function() | 346 _buildAllocationTraceTree: function() |
332 { | 347 { |
333 this._backTraceTree = new WebInspector.AllocationBackTraceNode(this._tra
ceTops[0].functionInfo); | 348 this._bottomUpTree = new WebInspector.BottomUpAllocationNode(this); |
334 | 349 |
335 for (var i = 0; i < this._traceTops.length; i++) { | 350 for (var i = 0; i < this._traceTops.length; i++) { |
336 var node = this._traceTops[i]; | 351 var node = this._traceTops[i]; |
337 var backTraceNode = this._backTraceTree; | 352 var bottomUpNode = this._bottomUpTree; |
338 var count = node.allocationCount; | 353 var count = node.allocationCount; |
339 var size = node.allocationSize; | 354 var size = node.allocationSize; |
340 var liveCount = node.liveCount; | 355 var liveCount = node.liveCount; |
341 var liveSize = node.liveSize; | 356 var liveSize = node.liveSize; |
342 while (true) { | 357 while (true) { |
343 backTraceNode.allocationCount += count; | 358 bottomUpNode.allocationCount += count; |
344 backTraceNode.allocationSize += size; | 359 bottomUpNode.allocationSize += size; |
345 backTraceNode.liveCount += liveCount; | 360 bottomUpNode.liveCount += liveCount; |
346 backTraceNode.liveSize += liveSize; | 361 bottomUpNode.liveSize += liveSize; |
347 node = node.parent; | 362 node = node.parent; |
348 if (node === null) { | 363 if (node === null) { |
349 break; | 364 break; |
350 } | 365 } |
351 backTraceNode = backTraceNode.addCaller(node); | 366 bottomUpNode = bottomUpNode.addCaller(node); |
352 } | 367 } |
353 } | 368 } |
354 } | 369 } |
355 } | 370 } |
OLD | NEW |