| 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 /** | |
| 6 * @constructor | |
| 7 * @implements {WebInspector.Searchable} | 5 * @implements {WebInspector.Searchable} |
| 8 * @extends {WebInspector.ProfileView} | 6 * @unrestricted |
| 9 * @param {!WebInspector.SamplingHeapProfileHeader} profileHeader | 7 */ |
| 10 */ | 8 WebInspector.HeapProfileView = class extends WebInspector.ProfileView { |
| 11 WebInspector.HeapProfileView = function(profileHeader) | 9 /** |
| 12 { | 10 * @param {!WebInspector.SamplingHeapProfileHeader} profileHeader |
| 13 WebInspector.ProfileView.call(this); | 11 */ |
| 12 constructor(profileHeader) { |
| 13 super(); |
| 14 this._profileHeader = profileHeader; | 14 this._profileHeader = profileHeader; |
| 15 this.profile = new WebInspector.SamplingHeapProfileModel(profileHeader._prof
ile || profileHeader.protocolProfile()); | 15 this.profile = new WebInspector.SamplingHeapProfileModel(profileHeader._prof
ile || profileHeader.protocolProfile()); |
| 16 this.adjustedTotal = this.profile.total; | 16 this.adjustedTotal = this.profile.total; |
| 17 var views = [ | 17 var views = [ |
| 18 WebInspector.ProfileView.ViewTypes.Flame, | 18 WebInspector.ProfileView.ViewTypes.Flame, WebInspector.ProfileView.ViewTyp
es.Heavy, |
| 19 WebInspector.ProfileView.ViewTypes.Heavy, | 19 WebInspector.ProfileView.ViewTypes.Tree |
| 20 WebInspector.ProfileView.ViewTypes.Tree | |
| 21 ]; | 20 ]; |
| 22 this.initialize(new WebInspector.HeapProfileView.NodeFormatter(this), views)
; | 21 this.initialize(new WebInspector.HeapProfileView.NodeFormatter(this), views)
; |
| 23 }; | 22 } |
| 24 | 23 |
| 25 WebInspector.HeapProfileView.prototype = { | 24 /** |
| 26 /** | 25 * @override |
| 27 * @override | 26 * @param {string} columnId |
| 28 * @param {string} columnId | 27 * @return {string} |
| 29 * @return {string} | 28 */ |
| 30 */ | 29 columnHeader(columnId) { |
| 31 columnHeader: function(columnId) | 30 switch (columnId) { |
| 32 { | 31 case 'self': |
| 33 switch (columnId) { | 32 return WebInspector.UIString('Self Size (bytes)'); |
| 34 case "self": return WebInspector.UIString("Self Size (bytes)"); | 33 case 'total': |
| 35 case "total": return WebInspector.UIString("Total Size (bytes)"); | 34 return WebInspector.UIString('Total Size (bytes)'); |
| 36 } | 35 } |
| 37 return ""; | 36 return ''; |
| 38 }, | 37 } |
| 39 | 38 |
| 40 /** | 39 /** |
| 41 * @override | 40 * @override |
| 42 * @return {!WebInspector.FlameChartDataProvider} | 41 * @return {!WebInspector.FlameChartDataProvider} |
| 43 */ | 42 */ |
| 44 createFlameChartDataProvider: function() | 43 createFlameChartDataProvider() { |
| 45 { | 44 return new WebInspector.HeapFlameChartDataProvider(this.profile, this._profi
leHeader.target()); |
| 46 return new WebInspector.HeapFlameChartDataProvider(this.profile, this._p
rofileHeader.target()); | 45 } |
| 47 }, | 46 }; |
| 48 | 47 |
| 49 __proto__: WebInspector.ProfileView.prototype | 48 /** |
| 50 }; | 49 * @unrestricted |
| 51 | 50 */ |
| 52 /** | 51 WebInspector.SamplingHeapProfileType = class extends WebInspector.ProfileType { |
| 53 * @constructor | 52 constructor() { |
| 54 * @extends {WebInspector.ProfileType} | 53 super(WebInspector.SamplingHeapProfileType.TypeId, WebInspector.UIString('Re
cord Allocation Profile')); |
| 55 */ | |
| 56 WebInspector.SamplingHeapProfileType = function() | |
| 57 { | |
| 58 WebInspector.ProfileType.call(this, WebInspector.SamplingHeapProfileType.Typ
eId, WebInspector.UIString("Record Allocation Profile")); | |
| 59 this._recording = false; | 54 this._recording = false; |
| 60 WebInspector.SamplingHeapProfileType.instance = this; | 55 WebInspector.SamplingHeapProfileType.instance = this; |
| 61 }; | 56 } |
| 62 | 57 |
| 63 WebInspector.SamplingHeapProfileType.TypeId = "SamplingHeap"; | 58 /** |
| 64 | 59 * @override |
| 65 WebInspector.SamplingHeapProfileType.prototype = { | 60 * @return {string} |
| 66 /** | 61 */ |
| 67 * @override | 62 typeName() { |
| 68 * @return {string} | 63 return 'Heap'; |
| 69 */ | 64 } |
| 70 typeName: function() | 65 |
| 71 { | 66 /** |
| 72 return "Heap"; | 67 * @override |
| 73 }, | 68 * @return {string} |
| 74 | 69 */ |
| 75 /** | 70 fileExtension() { |
| 76 * @override | 71 return '.heapprofile'; |
| 77 * @return {string} | 72 } |
| 78 */ | 73 |
| 79 fileExtension: function() | 74 get buttonTooltip() { |
| 80 { | 75 return this._recording ? WebInspector.UIString('Stop heap profiling') : |
| 81 return ".heapprofile"; | 76 WebInspector.UIString('Start heap profiling'); |
| 82 }, | 77 } |
| 83 | 78 |
| 84 get buttonTooltip() | 79 /** |
| 85 { | 80 * @override |
| 86 return this._recording ? WebInspector.UIString("Stop heap profiling") :
WebInspector.UIString("Start heap profiling"); | 81 * @return {boolean} |
| 87 }, | 82 */ |
| 88 | 83 buttonClicked() { |
| 89 /** | 84 var wasRecording = this._recording; |
| 90 * @override | 85 if (wasRecording) |
| 91 * @return {boolean} | 86 this.stopRecordingProfile(); |
| 92 */ | 87 else |
| 93 buttonClicked: function() | 88 this.startRecordingProfile(); |
| 94 { | 89 return !wasRecording; |
| 95 var wasRecording = this._recording; | 90 } |
| 96 if (wasRecording) | 91 |
| 97 this.stopRecordingProfile(); | 92 get treeItemTitle() { |
| 98 else | 93 return WebInspector.UIString('ALLOCATION PROFILES'); |
| 99 this.startRecordingProfile(); | 94 } |
| 100 return !wasRecording; | 95 |
| 101 }, | 96 get description() { |
| 102 | 97 return WebInspector.UIString('Allocation profiles show memory allocations fr
om your JavaScript functions.'); |
| 103 get treeItemTitle() | 98 } |
| 104 { | 99 |
| 105 return WebInspector.UIString("ALLOCATION PROFILES"); | 100 startRecordingProfile() { |
| 106 }, | 101 var target = WebInspector.context.flavor(WebInspector.Target); |
| 107 | 102 if (this._profileBeingRecorded || !target) |
| 108 get description() | 103 return; |
| 109 { | 104 var profile = new WebInspector.SamplingHeapProfileHeader(target, this); |
| 110 return WebInspector.UIString("Allocation profiles show memory allocation
s from your JavaScript functions."); | 105 this.setProfileBeingRecorded(profile); |
| 111 }, | 106 WebInspector.targetManager.suspendAllTargets(); |
| 112 | 107 this.addProfile(profile); |
| 113 startRecordingProfile: function() | 108 profile.updateStatus(WebInspector.UIString('Recording\u2026')); |
| 114 { | 109 this._recording = true; |
| 115 var target = WebInspector.context.flavor(WebInspector.Target); | 110 target.heapProfilerModel.startSampling(); |
| 116 if (this._profileBeingRecorded || !target) | 111 } |
| 117 return; | 112 |
| 118 var profile = new WebInspector.SamplingHeapProfileHeader(target, this); | 113 stopRecordingProfile() { |
| 119 this.setProfileBeingRecorded(profile); | 114 this._recording = false; |
| 120 WebInspector.targetManager.suspendAllTargets(); | 115 if (!this._profileBeingRecorded || !this._profileBeingRecorded.target()) |
| 121 this.addProfile(profile); | 116 return; |
| 122 profile.updateStatus(WebInspector.UIString("Recording\u2026")); | 117 |
| 123 this._recording = true; | 118 var recordedProfile; |
| 124 target.heapProfilerModel.startSampling(); | 119 |
| 125 }, | 120 /** |
| 126 | 121 * @param {?HeapProfilerAgent.SamplingHeapProfile} profile |
| 127 stopRecordingProfile: function() | 122 * @this {WebInspector.SamplingHeapProfileType} |
| 128 { | 123 */ |
| 129 this._recording = false; | 124 function didStopProfiling(profile) { |
| 130 if (!this._profileBeingRecorded || !this._profileBeingRecorded.target()) | 125 if (!this._profileBeingRecorded) |
| 131 return; | 126 return; |
| 132 | 127 console.assert(profile); |
| 133 var recordedProfile; | 128 this._profileBeingRecorded.setProtocolProfile(profile); |
| 134 | 129 this._profileBeingRecorded.updateStatus(''); |
| 135 /** | 130 recordedProfile = this._profileBeingRecorded; |
| 136 * @param {?HeapProfilerAgent.SamplingHeapProfile} profile | 131 this.setProfileBeingRecorded(null); |
| 137 * @this {WebInspector.SamplingHeapProfileType} | 132 } |
| 138 */ | 133 |
| 139 function didStopProfiling(profile) | 134 /** |
| 140 { | 135 * @this {WebInspector.SamplingHeapProfileType} |
| 141 if (!this._profileBeingRecorded) | 136 */ |
| 142 return; | 137 function fireEvent() { |
| 143 console.assert(profile); | 138 this.dispatchEventToListeners(WebInspector.ProfileType.Events.ProfileCompl
ete, recordedProfile); |
| 144 this._profileBeingRecorded.setProtocolProfile(profile); | 139 } |
| 145 this._profileBeingRecorded.updateStatus(""); | 140 |
| 146 recordedProfile = this._profileBeingRecorded; | 141 this._profileBeingRecorded.target() |
| 147 this.setProfileBeingRecorded(null); | 142 .heapProfilerModel.stopSampling() |
| 148 } | 143 .then(didStopProfiling.bind(this)) |
| 149 | 144 .then(WebInspector.targetManager.resumeAllTargets.bind(WebInspector.targ
etManager)) |
| 150 /** | 145 .then(fireEvent.bind(this)); |
| 151 * @this {WebInspector.SamplingHeapProfileType} | 146 } |
| 152 */ | 147 |
| 153 function fireEvent() | 148 /** |
| 154 { | 149 * @override |
| 155 this.dispatchEventToListeners(WebInspector.ProfileType.Events.Profil
eComplete, recordedProfile); | 150 * @param {string} title |
| 156 } | 151 * @return {!WebInspector.ProfileHeader} |
| 157 | 152 */ |
| 158 this._profileBeingRecorded.target().heapProfilerModel.stopSampling() | 153 createProfileLoadedFromFile(title) { |
| 159 .then(didStopProfiling.bind(this)) | 154 return new WebInspector.SamplingHeapProfileHeader(null, this, title); |
| 160 .then(WebInspector.targetManager.resumeAllTargets.bind(WebInspector.
targetManager)) | 155 } |
| 161 .then(fireEvent.bind(this)); | 156 |
| 162 }, | 157 /** |
| 163 | 158 * @override |
| 164 /** | 159 */ |
| 165 * @override | 160 profileBeingRecordedRemoved() { |
| 166 * @param {string} title | 161 this.stopRecordingProfile(); |
| 167 * @return {!WebInspector.ProfileHeader} | 162 } |
| 168 */ | 163 }; |
| 169 createProfileLoadedFromFile: function(title) | 164 |
| 170 { | 165 WebInspector.SamplingHeapProfileType.TypeId = 'SamplingHeap'; |
| 171 return new WebInspector.SamplingHeapProfileHeader(null, this, title); | 166 |
| 172 }, | 167 /** |
| 173 | 168 * @unrestricted |
| 174 /** | 169 */ |
| 175 * @override | 170 WebInspector.SamplingHeapProfileHeader = class extends WebInspector.WritableProf
ileHeader { |
| 176 */ | 171 /** |
| 177 profileBeingRecordedRemoved: function() | 172 * @param {?WebInspector.Target} target |
| 178 { | 173 * @param {!WebInspector.SamplingHeapProfileType} type |
| 179 this.stopRecordingProfile(); | 174 * @param {string=} title |
| 180 }, | 175 */ |
| 181 | 176 constructor(target, type, title) { |
| 182 __proto__: WebInspector.ProfileType.prototype | 177 super(target, type, title || WebInspector.UIString('Profile %d', type.nextPr
ofileUid())); |
| 183 }; | 178 } |
| 184 | 179 |
| 185 /** | 180 /** |
| 186 * @constructor | 181 * @override |
| 187 * @extends {WebInspector.WritableProfileHeader} | 182 * @return {!WebInspector.ProfileView} |
| 188 * @param {?WebInspector.Target} target | 183 */ |
| 189 * @param {!WebInspector.SamplingHeapProfileType} type | 184 createView() { |
| 190 * @param {string=} title | 185 return new WebInspector.HeapProfileView(this); |
| 191 */ | 186 } |
| 192 WebInspector.SamplingHeapProfileHeader = function(target, type, title) | 187 |
| 193 { | 188 /** |
| 194 WebInspector.WritableProfileHeader.call(this, target, type, title || WebInsp
ector.UIString("Profile %d", type.nextProfileUid())); | 189 * @return {!HeapProfilerAgent.SamplingHeapProfile} |
| 195 }; | 190 */ |
| 196 | 191 protocolProfile() { |
| 197 WebInspector.SamplingHeapProfileHeader.prototype = { | 192 return this._protocolProfile; |
| 198 /** | 193 } |
| 199 * @override | 194 }; |
| 200 * @return {!WebInspector.ProfileView} | 195 |
| 201 */ | 196 /** |
| 202 createView: function() | 197 * @unrestricted |
| 203 { | 198 */ |
| 204 return new WebInspector.HeapProfileView(this); | 199 WebInspector.SamplingHeapProfileNode = class extends WebInspector.ProfileNode { |
| 205 }, | 200 /** |
| 206 | 201 * @param {!HeapProfilerAgent.SamplingHeapProfileNode} node |
| 207 /** | 202 */ |
| 208 * @return {!HeapProfilerAgent.SamplingHeapProfile} | 203 constructor(node) { |
| 209 */ | |
| 210 protocolProfile: function() | |
| 211 { | |
| 212 return this._protocolProfile; | |
| 213 }, | |
| 214 | |
| 215 __proto__: WebInspector.WritableProfileHeader.prototype | |
| 216 }; | |
| 217 | |
| 218 /** | |
| 219 * @constructor | |
| 220 * @extends {WebInspector.ProfileNode} | |
| 221 * @param {!HeapProfilerAgent.SamplingHeapProfileNode} node | |
| 222 */ | |
| 223 WebInspector.SamplingHeapProfileNode = function(node) | |
| 224 { | |
| 225 var callFrame = node.callFrame || /** @type {!RuntimeAgent.CallFrame} */ ({ | 204 var callFrame = node.callFrame || /** @type {!RuntimeAgent.CallFrame} */ ({ |
| 226 // Backward compatibility for old CpuProfileNode format. | 205 // Backward compatibility for old CpuProfileNode format. |
| 227 functionName: node["functionName"], | 206 functionName: node['functionName'], |
| 228 scriptId: node["scriptId"], | 207 scriptId: node['scriptId'], |
| 229 url: node["url"], | 208 url: node['url'], |
| 230 lineNumber: node["lineNumber"] - 1, | 209 lineNumber: node['lineNumber'] - 1, |
| 231 columnNumber: node["columnNumber"] - 1 | 210 columnNumber: node['columnNumber'] - 1 |
| 232 }); | 211 }); |
| 233 WebInspector.ProfileNode.call(this, callFrame); | 212 super(callFrame); |
| 234 this.self = node.selfSize; | 213 this.self = node.selfSize; |
| 235 }; | 214 } |
| 236 | 215 }; |
| 237 WebInspector.SamplingHeapProfileNode.prototype = { | 216 |
| 238 __proto__: WebInspector.ProfileNode.prototype | 217 /** |
| 239 }; | 218 * @unrestricted |
| 240 | 219 */ |
| 241 /** | 220 WebInspector.SamplingHeapProfileModel = class extends WebInspector.ProfileTreeMo
del { |
| 242 * @constructor | 221 /** |
| 243 * @extends {WebInspector.ProfileTreeModel} | 222 * @param {!HeapProfilerAgent.SamplingHeapProfile} profile |
| 244 * @param {!HeapProfilerAgent.SamplingHeapProfile} profile | 223 */ |
| 245 */ | 224 constructor(profile) { |
| 246 WebInspector.SamplingHeapProfileModel = function(profile) | 225 super(); |
| 247 { | |
| 248 WebInspector.ProfileTreeModel.call(this); | |
| 249 this.initialize(translateProfileTree(profile.head)); | 226 this.initialize(translateProfileTree(profile.head)); |
| 250 | 227 |
| 251 /** | 228 /** |
| 252 * @param {!HeapProfilerAgent.SamplingHeapProfileNode} root | 229 * @param {!HeapProfilerAgent.SamplingHeapProfileNode} root |
| 253 * @return {!WebInspector.SamplingHeapProfileNode} | 230 * @return {!WebInspector.SamplingHeapProfileNode} |
| 254 */ | 231 */ |
| 255 function translateProfileTree(root) | 232 function translateProfileTree(root) { |
| 256 { | 233 var resultRoot = new WebInspector.SamplingHeapProfileNode(root); |
| 257 var resultRoot = new WebInspector.SamplingHeapProfileNode(root); | 234 var targetNodeStack = [resultRoot]; |
| 258 var targetNodeStack = [resultRoot]; | 235 var sourceNodeStack = [root]; |
| 259 var sourceNodeStack = [root]; | 236 while (sourceNodeStack.length) { |
| 260 while (sourceNodeStack.length) { | 237 var sourceNode = sourceNodeStack.pop(); |
| 261 var sourceNode = sourceNodeStack.pop(); | 238 var parentNode = targetNodeStack.pop(); |
| 262 var parentNode = targetNodeStack.pop(); | 239 parentNode.children = sourceNode.children.map(child => new WebInspector.
SamplingHeapProfileNode(child)); |
| 263 parentNode.children = sourceNode.children.map(child => new WebInspec
tor.SamplingHeapProfileNode(child)); | 240 sourceNodeStack.push.apply(sourceNodeStack, sourceNode.children); |
| 264 sourceNodeStack.push.apply(sourceNodeStack, sourceNode.children); | 241 targetNodeStack.push.apply(targetNodeStack, parentNode.children); |
| 265 targetNodeStack.push.apply(targetNodeStack, parentNode.children); | 242 } |
| 266 } | 243 return resultRoot; |
| 267 return resultRoot; | 244 } |
| 268 } | 245 } |
| 269 }; | 246 }; |
| 270 | 247 |
| 271 WebInspector.SamplingHeapProfileModel.prototype = { | 248 /** |
| 272 | |
| 273 __proto__: WebInspector.ProfileTreeModel.prototype | |
| 274 }; | |
| 275 | |
| 276 /** | |
| 277 * @constructor | |
| 278 * @implements {WebInspector.ProfileDataGridNode.Formatter} | 249 * @implements {WebInspector.ProfileDataGridNode.Formatter} |
| 279 * @param {!WebInspector.ProfileView} profileView | 250 * @unrestricted |
| 280 */ | 251 */ |
| 281 WebInspector.HeapProfileView.NodeFormatter = function(profileView) | 252 WebInspector.HeapProfileView.NodeFormatter = class { |
| 282 { | 253 /** |
| 254 * @param {!WebInspector.ProfileView} profileView |
| 255 */ |
| 256 constructor(profileView) { |
| 283 this._profileView = profileView; | 257 this._profileView = profileView; |
| 284 }; | 258 } |
| 285 | 259 |
| 286 WebInspector.HeapProfileView.NodeFormatter.prototype = { | 260 /** |
| 287 /** | 261 * @override |
| 288 * @override | 262 * @param {number} value |
| 289 * @param {number} value | 263 * @return {string} |
| 290 * @return {string} | 264 */ |
| 291 */ | 265 formatValue(value) { |
| 292 formatValue: function(value) | 266 return Number.withThousandsSeparator(value); |
| 293 { | 267 } |
| 294 return Number.withThousandsSeparator(value); | 268 |
| 295 }, | 269 /** |
| 296 | 270 * @override |
| 297 /** | 271 * @param {number} value |
| 298 * @override | 272 * @param {!WebInspector.ProfileDataGridNode} node |
| 299 * @param {number} value | 273 * @return {string} |
| 300 * @param {!WebInspector.ProfileDataGridNode} node | 274 */ |
| 301 * @return {string} | 275 formatPercent(value, node) { |
| 302 */ | 276 return WebInspector.UIString('%.2f\u2009%%', value); |
| 303 formatPercent: function(value, node) | 277 } |
| 304 { | 278 |
| 305 return WebInspector.UIString("%.2f\u2009%%", value); | 279 /** |
| 306 }, | 280 * @override |
| 307 | 281 * @param {!WebInspector.ProfileDataGridNode} node |
| 308 /** | 282 * @return {?Element} |
| 309 * @override | 283 */ |
| 310 * @param {!WebInspector.ProfileDataGridNode} node | 284 linkifyNode(node) { |
| 311 * @return {?Element} | 285 return this._profileView.linkifier().maybeLinkifyConsoleCallFrame( |
| 312 */ | 286 this._profileView.target(), node.profileNode.callFrame, 'profile-node-fi
le'); |
| 313 linkifyNode: function(node) | 287 } |
| 314 { | 288 }; |
| 315 return this._profileView.linkifier().maybeLinkifyConsoleCallFrame(this._
profileView.target(), node.profileNode.callFrame, "profile-node-file"); | 289 |
| 316 } | 290 /** |
| 317 }; | 291 * @unrestricted |
| 318 | 292 */ |
| 319 /** | 293 WebInspector.HeapFlameChartDataProvider = class extends WebInspector.ProfileFlam
eChartDataProvider { |
| 320 * @constructor | 294 /** |
| 321 * @extends {WebInspector.ProfileFlameChartDataProvider} | 295 * @param {!WebInspector.ProfileTreeModel} profile |
| 322 * @param {!WebInspector.ProfileTreeModel} profile | 296 * @param {?WebInspector.Target} target |
| 323 * @param {?WebInspector.Target} target | 297 */ |
| 324 */ | 298 constructor(profile, target) { |
| 325 WebInspector.HeapFlameChartDataProvider = function(profile, target) | 299 super(target); |
| 326 { | |
| 327 WebInspector.ProfileFlameChartDataProvider.call(this, target); | |
| 328 this._profile = profile; | 300 this._profile = profile; |
| 329 }; | 301 } |
| 330 | 302 |
| 331 WebInspector.HeapFlameChartDataProvider.prototype = { | 303 /** |
| 332 /** | 304 * @override |
| 333 * @override | 305 * @return {number} |
| 306 */ |
| 307 minimumBoundary() { |
| 308 return 0; |
| 309 } |
| 310 |
| 311 /** |
| 312 * @override |
| 313 * @return {number} |
| 314 */ |
| 315 totalTime() { |
| 316 return this._profile.root.total; |
| 317 } |
| 318 |
| 319 /** |
| 320 * @override |
| 321 * @param {number} value |
| 322 * @param {number=} precision |
| 323 * @return {string} |
| 324 */ |
| 325 formatValue(value, precision) { |
| 326 return WebInspector.UIString('%s\u2009KB', Number.withThousandsSeparator(val
ue / 1e3)); |
| 327 } |
| 328 |
| 329 /** |
| 330 * @override |
| 331 * @return {!WebInspector.FlameChart.TimelineData} |
| 332 */ |
| 333 _calculateTimelineData() { |
| 334 /** |
| 335 * @param {!WebInspector.ProfileNode} node |
| 334 * @return {number} | 336 * @return {number} |
| 335 */ | 337 */ |
| 336 minimumBoundary: function() | 338 function nodesCount(node) { |
| 337 { | 339 return node.children.reduce((count, node) => count + nodesCount(node), 1); |
| 338 return 0; | 340 } |
| 339 }, | 341 var count = nodesCount(this._profile.root); |
| 340 | 342 /** @type {!Array<!WebInspector.ProfileNode>} */ |
| 341 /** | 343 var entryNodes = new Array(count); |
| 342 * @override | 344 var entryLevels = new Uint16Array(count); |
| 343 * @return {number} | 345 var entryTotalTimes = new Float32Array(count); |
| 344 */ | 346 var entryStartTimes = new Float64Array(count); |
| 345 totalTime: function() | 347 var depth = 0; |
| 346 { | 348 var maxDepth = 0; |
| 347 return this._profile.root.total; | 349 var position = 0; |
| 348 }, | 350 var index = 0; |
| 349 | 351 |
| 350 /** | 352 /** |
| 351 * @override | 353 * @param {!WebInspector.ProfileNode} node |
| 352 * @param {number} value | 354 */ |
| 353 * @param {number=} precision | 355 function addNode(node) { |
| 354 * @return {string} | 356 var start = position; |
| 355 */ | 357 entryNodes[index] = node; |
| 356 formatValue: function(value, precision) | 358 entryLevels[index] = depth; |
| 357 { | 359 entryTotalTimes[index] = node.total; |
| 358 return WebInspector.UIString("%s\u2009KB", Number.withThousandsSeparator
(value / 1e3)); | 360 entryStartTimes[index] = position; |
| 359 }, | 361 ++index; |
| 360 | 362 ++depth; |
| 361 /** | 363 node.children.forEach(addNode); |
| 362 * @override | 364 --depth; |
| 363 * @return {!WebInspector.FlameChart.TimelineData} | 365 maxDepth = Math.max(maxDepth, depth); |
| 364 */ | 366 position = start + node.total; |
| 365 _calculateTimelineData: function() | 367 } |
| 366 { | 368 addNode(this._profile.root); |
| 367 /** | 369 |
| 368 * @param {!WebInspector.ProfileNode} node | 370 this._maxStackDepth = maxDepth + 1; |
| 369 * @return {number} | 371 this._entryNodes = entryNodes; |
| 370 */ | 372 this._timelineData = new WebInspector.FlameChart.TimelineData(entryLevels, e
ntryTotalTimes, entryStartTimes, null); |
| 371 function nodesCount(node) | 373 |
| 372 { | 374 return this._timelineData; |
| 373 return node.children.reduce((count, node) => count + nodesCount(node
), 1); | 375 } |
| 374 } | 376 |
| 375 var count = nodesCount(this._profile.root); | 377 /** |
| 376 /** @type {!Array<!WebInspector.ProfileNode>} */ | 378 * @override |
| 377 var entryNodes = new Array(count); | 379 * @param {number} entryIndex |
| 378 var entryLevels = new Uint16Array(count); | 380 * @return {?Element} |
| 379 var entryTotalTimes = new Float32Array(count); | 381 */ |
| 380 var entryStartTimes = new Float64Array(count); | 382 prepareHighlightedEntryInfo(entryIndex) { |
| 381 var depth = 0; | 383 var node = this._entryNodes[entryIndex]; |
| 382 var maxDepth = 0; | 384 if (!node) |
| 383 var position = 0; | 385 return null; |
| 384 var index = 0; | 386 var entryInfo = []; |
| 385 | 387 /** |
| 386 /** | 388 * @param {string} title |
| 387 * @param {!WebInspector.ProfileNode} node | 389 * @param {string} value |
| 388 */ | 390 */ |
| 389 function addNode(node) | 391 function pushEntryInfoRow(title, value) { |
| 390 { | 392 entryInfo.push({title: title, value: value}); |
| 391 var start = position; | 393 } |
| 392 entryNodes[index] = node; | 394 pushEntryInfoRow(WebInspector.UIString('Name'), WebInspector.beautifyFunctio
nName(node.functionName)); |
| 393 entryLevels[index] = depth; | 395 pushEntryInfoRow(WebInspector.UIString('Self size'), Number.bytesToString(no
de.self)); |
| 394 entryTotalTimes[index] = node.total; | 396 pushEntryInfoRow(WebInspector.UIString('Total size'), Number.bytesToString(n
ode.total)); |
| 395 entryStartTimes[index] = position; | 397 var linkifier = new WebInspector.Linkifier(); |
| 396 ++index; | 398 var link = linkifier.maybeLinkifyConsoleCallFrame(this._target, node.callFra
me); |
| 397 ++depth; | 399 if (link) |
| 398 node.children.forEach(addNode); | 400 pushEntryInfoRow(WebInspector.UIString('URL'), link.textContent); |
| 399 --depth; | 401 linkifier.dispose(); |
| 400 maxDepth = Math.max(maxDepth, depth); | 402 return WebInspector.ProfileView.buildPopoverTable(entryInfo); |
| 401 position = start + node.total; | 403 } |
| 402 } | 404 }; |
| 403 addNode(this._profile.root); | |
| 404 | |
| 405 this._maxStackDepth = maxDepth + 1; | |
| 406 this._entryNodes = entryNodes; | |
| 407 this._timelineData = new WebInspector.FlameChart.TimelineData(entryLevel
s, entryTotalTimes, entryStartTimes, null); | |
| 408 | |
| 409 return this._timelineData; | |
| 410 }, | |
| 411 | |
| 412 /** | |
| 413 * @override | |
| 414 * @param {number} entryIndex | |
| 415 * @return {?Element} | |
| 416 */ | |
| 417 prepareHighlightedEntryInfo: function(entryIndex) | |
| 418 { | |
| 419 var node = this._entryNodes[entryIndex]; | |
| 420 if (!node) | |
| 421 return null; | |
| 422 var entryInfo = []; | |
| 423 /** | |
| 424 * @param {string} title | |
| 425 * @param {string} value | |
| 426 */ | |
| 427 function pushEntryInfoRow(title, value) | |
| 428 { | |
| 429 entryInfo.push({ title: title, value: value }); | |
| 430 } | |
| 431 pushEntryInfoRow(WebInspector.UIString("Name"), WebInspector.beautifyFun
ctionName(node.functionName)); | |
| 432 pushEntryInfoRow(WebInspector.UIString("Self size"), Number.bytesToStrin
g(node.self)); | |
| 433 pushEntryInfoRow(WebInspector.UIString("Total size"), Number.bytesToStri
ng(node.total)); | |
| 434 var linkifier = new WebInspector.Linkifier(); | |
| 435 var link = linkifier.maybeLinkifyConsoleCallFrame(this._target, node.cal
lFrame); | |
| 436 if (link) | |
| 437 pushEntryInfoRow(WebInspector.UIString("URL"), link.textContent); | |
| 438 linkifier.dispose(); | |
| 439 return WebInspector.ProfileView.buildPopoverTable(entryInfo); | |
| 440 }, | |
| 441 | |
| 442 __proto__: WebInspector.ProfileFlameChartDataProvider.prototype | |
| 443 }; | |
| OLD | NEW |