| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of cpu_profiler; | 5 part of cpu_profiler; |
| 6 | 6 |
| 7 abstract class CallTreeNode<NodeT extends M.CallTreeNode> | 7 abstract class CallTreeNode<NodeT extends M.CallTreeNode> |
| 8 implements M.CallTreeNode { | 8 implements M.CallTreeNode { |
| 9 final List<NodeT> children; | 9 final List<NodeT> children; |
| 10 final int count; | 10 final int count; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 | 36 |
| 37 class CallTree<NodeT extends CallTreeNode> { | 37 class CallTree<NodeT extends CallTreeNode> { |
| 38 final bool inclusive; | 38 final bool inclusive; |
| 39 final NodeT root; | 39 final NodeT root; |
| 40 | 40 |
| 41 CallTree(this.inclusive, this.root); | 41 CallTree(this.inclusive, this.root); |
| 42 } | 42 } |
| 43 | 43 |
| 44 class CodeCallTree extends CallTree<CodeCallTreeNode> | 44 class CodeCallTree extends CallTree<CodeCallTreeNode> |
| 45 implements M.CodeCallTree { | 45 implements M.CodeCallTree { |
| 46 CodeCallTree(bool inclusive, CodeCallTreeNode root) | 46 CodeCallTree(bool inclusive, CodeCallTreeNode root) : super(inclusive, root) { |
| 47 : super(inclusive, root) { | |
| 48 _setCodePercentage(null, root); | 47 _setCodePercentage(null, root); |
| 49 } | 48 } |
| 50 | 49 |
| 51 CodeCallTree filtered(CallTreeNodeFilter filter) { | 50 CodeCallTree filtered(CallTreeNodeFilter filter) { |
| 52 var treeFilter = new _FilteredCodeCallTreeBuilder(filter, this); | 51 var treeFilter = new _FilteredCodeCallTreeBuilder(filter, this); |
| 53 treeFilter.build(); | 52 treeFilter.build(); |
| 54 _setCodePercentage(null, treeFilter.filtered.root); | 53 _setCodePercentage(null, treeFilter.filtered.root); |
| 55 return treeFilter.filtered; | 54 return treeFilter.filtered; |
| 56 } | 55 } |
| 57 | 56 |
| 58 _setCodePercentage(CodeCallTreeNode parent, CodeCallTreeNode node) { | 57 _setCodePercentage(CodeCallTreeNode parent, CodeCallTreeNode node) { |
| 59 assert(node != null); | 58 assert(node != null); |
| 60 var parentPercentage = 1.0; | 59 var parentPercentage = 1.0; |
| 61 var parentCount = node.count; | 60 var parentCount = node.count; |
| 62 if (parent != null) { | 61 if (parent != null) { |
| 63 parentPercentage = parent._percentage; | 62 parentPercentage = parent._percentage; |
| 64 parentCount = parent.count; | 63 parentCount = parent.count; |
| 65 } | 64 } |
| 66 if (inclusive) { | 65 if (inclusive) { |
| 67 node._percentage = parentPercentage * (node.count / parentCount); | 66 node._percentage = parentPercentage * (node.count / parentCount); |
| 68 } else { | 67 } else { |
| 69 node._percentage = (node.count / parentCount); | 68 node._percentage = (node.count / parentCount); |
| 70 } | 69 } |
| 71 for (var child in node.children) { | 70 for (var child in node.children) { |
| 72 _setCodePercentage(node, child); | 71 _setCodePercentage(node, child); |
| 73 } | 72 } |
| 74 } | 73 } |
| 75 | 74 |
| 76 _recordCallerAndCalleesInner(CodeCallTreeNode caller, | 75 _recordCallerAndCalleesInner( |
| 77 CodeCallTreeNode callee) { | 76 CodeCallTreeNode caller, CodeCallTreeNode callee) { |
| 78 if (caller != null) { | 77 if (caller != null) { |
| 79 caller.profileCode._recordCallee(callee.profileCode, callee.count); | 78 caller.profileCode._recordCallee(callee.profileCode, callee.count); |
| 80 callee.profileCode._recordCaller(caller.profileCode, caller.count); | 79 callee.profileCode._recordCaller(caller.profileCode, caller.count); |
| 81 } | 80 } |
| 82 | 81 |
| 83 for (var child in callee.children) { | 82 for (var child in callee.children) { |
| 84 _recordCallerAndCalleesInner(callee, child); | 83 _recordCallerAndCalleesInner(callee, child); |
| 85 } | 84 } |
| 86 } | 85 } |
| 87 | 86 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 continue; | 156 continue; |
| 158 } | 157 } |
| 159 // If the code's function isn't this function. | 158 // If the code's function isn't this function. |
| 160 if (profileCode.code.function != profileFunction.function) { | 159 if (profileCode.code.function != profileFunction.function) { |
| 161 return true; | 160 return true; |
| 162 } | 161 } |
| 163 } | 162 } |
| 164 return false; | 163 return false; |
| 165 } | 164 } |
| 166 | 165 |
| 167 setCodeAttributes() { | 166 setCodeAttributes() {} |
| 168 } | |
| 169 } | 167 } |
| 170 | 168 |
| 171 /// Predicate filter function. Returns true if path from root to [node] and all | 169 /// Predicate filter function. Returns true if path from root to [node] and all |
| 172 /// of [node]'s children should be added to the filtered tree. | 170 /// of [node]'s children should be added to the filtered tree. |
| 173 typedef bool CallTreeNodeFilter(CallTreeNode node); | 171 typedef bool CallTreeNodeFilter(CallTreeNode node); |
| 174 | 172 |
| 175 /// Build a filter version of a FunctionCallTree. | 173 /// Build a filter version of a FunctionCallTree. |
| 176 abstract class _FilteredCallTreeBuilder { | 174 abstract class _FilteredCallTreeBuilder { |
| 177 /// The filter. | 175 /// The filter. |
| 178 final CallTreeNodeFilter filter; | 176 final CallTreeNodeFilter filter; |
| 177 |
| 179 /// The unfiltered tree. | 178 /// The unfiltered tree. |
| 180 final CallTree _unfilteredTree; | 179 final CallTree _unfilteredTree; |
| 180 |
| 181 /// The filtered tree (construct by [build]). | 181 /// The filtered tree (construct by [build]). |
| 182 final CallTree filtered; | 182 final CallTree filtered; |
| 183 final List _currentPath = []; | 183 final List _currentPath = []; |
| 184 | 184 |
| 185 /// Construct a filtered tree builder using [filter] and [tree]. | 185 /// Construct a filtered tree builder using [filter] and [tree]. |
| 186 _FilteredCallTreeBuilder(this.filter, CallTree tree, this.filtered) | 186 _FilteredCallTreeBuilder(this.filter, CallTree tree, this.filtered) |
| 187 : _unfilteredTree = tree; | 187 : _unfilteredTree = tree; |
| 188 | 188 |
| 189 /// Build the filtered tree. | 189 /// Build the filtered tree. |
| 190 build() { | 190 build() { |
| 191 assert(filtered != null); | 191 assert(filtered != null); |
| 192 assert(filter != null); | 192 assert(filter != null); |
| 193 assert(_unfilteredTree != null); | 193 assert(_unfilteredTree != null); |
| 194 _descend(_unfilteredTree.root); | 194 _descend(_unfilteredTree.root); |
| 195 } | 195 } |
| 196 | 196 |
| 197 CallTreeNode _findInChildren(CallTreeNode current, | 197 CallTreeNode _findInChildren(CallTreeNode current, CallTreeNode needle) { |
| 198 CallTreeNode needle) { | |
| 199 for (var child in current.children) { | 198 for (var child in current.children) { |
| 200 if (child.profileData == needle.profileData) { | 199 if (child.profileData == needle.profileData) { |
| 201 return child; | 200 return child; |
| 202 } | 201 } |
| 203 } | 202 } |
| 204 return null; | 203 return null; |
| 205 } | 204 } |
| 206 | 205 |
| 207 CallTreeNode _copyNode(CallTreeNode node); | 206 CallTreeNode _copyNode(CallTreeNode node); |
| 208 | 207 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 _descend(child); | 275 _descend(child); |
| 277 } | 276 } |
| 278 } | 277 } |
| 279 | 278 |
| 280 var last = _currentPath.removeLast(); | 279 var last = _currentPath.removeLast(); |
| 281 assert(current == last); | 280 assert(current == last); |
| 282 } | 281 } |
| 283 } | 282 } |
| 284 | 283 |
| 285 class _FilteredFunctionCallTreeBuilder extends _FilteredCallTreeBuilder { | 284 class _FilteredFunctionCallTreeBuilder extends _FilteredCallTreeBuilder { |
| 286 _FilteredFunctionCallTreeBuilder(CallTreeNodeFilter filter, | 285 _FilteredFunctionCallTreeBuilder( |
| 287 FunctionCallTree tree) | 286 CallTreeNodeFilter filter, FunctionCallTree tree) |
| 288 : super(filter, tree, | 287 : super( |
| 289 new FunctionCallTree(tree.inclusive, | 288 filter, |
| 290 new FunctionCallTreeNode(tree.root.profileData, | 289 tree, |
| 291 tree.root.count))); | 290 new FunctionCallTree( |
| 291 tree.inclusive, |
| 292 new FunctionCallTreeNode( |
| 293 tree.root.profileData, tree.root.count))); |
| 292 | 294 |
| 293 _copyNode(FunctionCallTreeNode node) { | 295 _copyNode(FunctionCallTreeNode node) { |
| 294 return new FunctionCallTreeNode(node.profileData, node.count); | 296 return new FunctionCallTreeNode(node.profileData, node.count); |
| 295 } | 297 } |
| 296 } | 298 } |
| 297 | 299 |
| 298 class _FilteredCodeCallTreeBuilder extends _FilteredCallTreeBuilder { | 300 class _FilteredCodeCallTreeBuilder extends _FilteredCallTreeBuilder { |
| 299 _FilteredCodeCallTreeBuilder(CallTreeNodeFilter filter, | 301 _FilteredCodeCallTreeBuilder(CallTreeNodeFilter filter, CodeCallTree tree) |
| 300 CodeCallTree tree) | 302 : super( |
| 301 : super(filter, tree, | 303 filter, |
| 304 tree, |
| 302 new CodeCallTree(tree.inclusive, | 305 new CodeCallTree(tree.inclusive, |
| 303 new CodeCallTreeNode(tree.root.profileData, | 306 new CodeCallTreeNode(tree.root.profileData, tree.root.count))); |
| 304 tree.root.count))); | |
| 305 | 307 |
| 306 _copyNode(CodeCallTreeNode node) { | 308 _copyNode(CodeCallTreeNode node) { |
| 307 return new CodeCallTreeNode(node.profileData, node.count); | 309 return new CodeCallTreeNode(node.profileData, node.count); |
| 308 } | 310 } |
| 309 } | 311 } |
| 310 | 312 |
| 311 class FunctionCallTree extends CallTree implements M.FunctionCallTree { | 313 class FunctionCallTree extends CallTree implements M.FunctionCallTree { |
| 312 FunctionCallTree(bool inclusive, FunctionCallTreeNode root) | 314 FunctionCallTree(bool inclusive, FunctionCallTreeNode root) |
| 313 : super(inclusive, root) { | 315 : super(inclusive, root) { |
| 314 _setFunctionPercentage(null, root); | 316 _setFunctionPercentage(null, root); |
| 315 } | 317 } |
| 316 | 318 |
| 317 FunctionCallTree filtered(CallTreeNodeFilter filter) { | 319 FunctionCallTree filtered(CallTreeNodeFilter filter) { |
| 318 var treeFilter = new _FilteredFunctionCallTreeBuilder(filter, this); | 320 var treeFilter = new _FilteredFunctionCallTreeBuilder(filter, this); |
| 319 treeFilter.build(); | 321 treeFilter.build(); |
| 320 _setFunctionPercentage(null, treeFilter.filtered.root); | 322 _setFunctionPercentage(null, treeFilter.filtered.root); |
| 321 return treeFilter.filtered; | 323 return treeFilter.filtered; |
| 322 } | 324 } |
| 323 | 325 |
| 324 void _setFunctionPercentage(FunctionCallTreeNode parent, | 326 void _setFunctionPercentage( |
| 325 FunctionCallTreeNode node) { | 327 FunctionCallTreeNode parent, FunctionCallTreeNode node) { |
| 326 assert(node != null); | 328 assert(node != null); |
| 327 var parentPercentage = 1.0; | 329 var parentPercentage = 1.0; |
| 328 var parentCount = node.count; | 330 var parentCount = node.count; |
| 329 if (parent != null) { | 331 if (parent != null) { |
| 330 parentPercentage = parent._percentage; | 332 parentPercentage = parent._percentage; |
| 331 parentCount = parent.count; | 333 parentCount = parent.count; |
| 332 } | 334 } |
| 333 if (inclusive) { | 335 if (inclusive) { |
| 334 node._percentage = parentPercentage * (node.count / parentCount); | 336 node._percentage = parentPercentage * (node.count / parentCount); |
| 335 } else { | 337 } else { |
| 336 node._percentage = (node.count / parentCount); | 338 node._percentage = (node.count / parentCount); |
| 337 } | 339 } |
| 338 for (var child in node.children) { | 340 for (var child in node.children) { |
| 339 _setFunctionPercentage(node, child); | 341 _setFunctionPercentage(node, child); |
| 340 } | 342 } |
| 341 } | 343 } |
| 342 | 344 |
| 343 _markFunctionCallsInner(FunctionCallTreeNode caller, | 345 _markFunctionCallsInner( |
| 344 FunctionCallTreeNode callee) { | 346 FunctionCallTreeNode caller, FunctionCallTreeNode callee) { |
| 345 if (caller != null) { | 347 if (caller != null) { |
| 346 caller.profileFunction._recordCallee(callee.profileFunction, callee.count)
; | 348 caller.profileFunction |
| 347 callee.profileFunction._recordCaller(caller.profileFunction, caller.count)
; | 349 ._recordCallee(callee.profileFunction, callee.count); |
| 350 callee.profileFunction |
| 351 ._recordCaller(caller.profileFunction, caller.count); |
| 348 } | 352 } |
| 349 for (var child in callee.children) { | 353 for (var child in callee.children) { |
| 350 _markFunctionCallsInner(callee, child); | 354 _markFunctionCallsInner(callee, child); |
| 351 } | 355 } |
| 352 } | 356 } |
| 353 | 357 |
| 354 _markFunctionCalls() { | 358 _markFunctionCalls() { |
| 355 for (var child in root.children) { | 359 for (var child in root.children) { |
| 356 _markFunctionCallsInner(null, child); | 360 _markFunctionCallsInner(null, child); |
| 357 } | 361 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 388 String formattedCpuTime = ''; | 392 String formattedCpuTime = ''; |
| 389 String formattedOnStackTime = ''; | 393 String formattedOnStackTime = ''; |
| 390 final Set<String> attributes = new Set<String>(); | 394 final Set<String> attributes = new Set<String>(); |
| 391 final Map<ProfileCode, int> callers = new Map<ProfileCode, int>(); | 395 final Map<ProfileCode, int> callers = new Map<ProfileCode, int>(); |
| 392 final Map<ProfileCode, int> callees = new Map<ProfileCode, int>(); | 396 final Map<ProfileCode, int> callees = new Map<ProfileCode, int>(); |
| 393 | 397 |
| 394 void _processTicks(List<String> profileTicks) { | 398 void _processTicks(List<String> profileTicks) { |
| 395 assert(profileTicks != null); | 399 assert(profileTicks != null); |
| 396 assert((profileTicks.length % 3) == 0); | 400 assert((profileTicks.length % 3) == 0); |
| 397 for (var i = 0; i < profileTicks.length; i += 3) { | 401 for (var i = 0; i < profileTicks.length; i += 3) { |
| 398 var address = int.parse(profileTicks[i], radix:16); | 402 var address = int.parse(profileTicks[i], radix: 16); |
| 399 var exclusive = int.parse(profileTicks[i + 1]); | 403 var exclusive = int.parse(profileTicks[i + 1]); |
| 400 var inclusive = int.parse(profileTicks[i + 2]); | 404 var inclusive = int.parse(profileTicks[i + 2]); |
| 401 var tick = new CodeTick(exclusive, inclusive); | 405 var tick = new CodeTick(exclusive, inclusive); |
| 402 addressTicks[address] = tick; | 406 addressTicks[address] = tick; |
| 403 | 407 |
| 404 var interval = code.findInterval(address); | 408 var interval = code.findInterval(address); |
| 405 if (interval != null) { | 409 if (interval != null) { |
| 406 var intervalTick = intervalTicks[interval.start]; | 410 var intervalTick = intervalTicks[interval.start]; |
| 407 if (intervalTick == null) { | 411 if (intervalTick == null) { |
| 408 // Insert into map. | 412 // Insert into map. |
| 409 intervalTick = new InlineIntervalTick(interval.start); | 413 intervalTick = new InlineIntervalTick(interval.start); |
| 410 intervalTicks[interval.start] = intervalTick; | 414 intervalTicks[interval.start] = intervalTick; |
| 411 } | 415 } |
| 412 intervalTick._inclusiveTicks += inclusive; | 416 intervalTick._inclusiveTicks += inclusive; |
| 413 intervalTick._exclusiveTicks += exclusive; | 417 intervalTick._exclusiveTicks += exclusive; |
| 414 } | 418 } |
| 415 } | 419 } |
| 416 } | 420 } |
| 417 | 421 |
| 418 ProfileCode.fromMap(this.profile, this.code, Map data) { | 422 ProfileCode.fromMap(this.profile, this.code, Map data) { |
| 419 assert(profile != null); | 423 assert(profile != null); |
| 420 assert(code != null); | 424 assert(code != null); |
| 421 | 425 |
| 422 code.profile = this; | 426 code.profile = this; |
| 423 | 427 |
| 424 if (code.kind == M.CodeKind.stub) { | 428 if (code.kind == M.CodeKind.stub) { |
| 425 attributes.add('stub'); | 429 attributes.add('stub'); |
| 426 } else if (code.kind == M.CodeKind.dart) { | 430 } else if (code.kind == M.CodeKind.dart) { |
| 427 if (code.isNative) { | 431 if (code.isNative) { |
| 428 attributes.add('ffi'); // Not to be confused with a C function. | 432 attributes.add('ffi'); // Not to be confused with a C function. |
| 429 } else { | 433 } else { |
| 430 attributes.add('dart'); | 434 attributes.add('dart'); |
| 431 } | 435 } |
| 432 if (code.hasIntrinsic) { | 436 if (code.hasIntrinsic) { |
| 433 attributes.add('intrinsic'); | 437 attributes.add('intrinsic'); |
| 434 } | 438 } |
| 435 if (code.isOptimized) { | 439 if (code.isOptimized) { |
| 436 attributes.add('optimized'); | 440 attributes.add('optimized'); |
| 437 } else { | 441 } else { |
| 438 attributes.add('unoptimized'); | 442 attributes.add('unoptimized'); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 450 normalizedInclusiveTicks = inclusiveTicks / profile.sampleCount; | 454 normalizedInclusiveTicks = inclusiveTicks / profile.sampleCount; |
| 451 | 455 |
| 452 var ticks = data['ticks']; | 456 var ticks = data['ticks']; |
| 453 if (ticks != null) { | 457 if (ticks != null) { |
| 454 _processTicks(ticks); | 458 _processTicks(ticks); |
| 455 } | 459 } |
| 456 | 460 |
| 457 formattedExclusivePercent = | 461 formattedExclusivePercent = |
| 458 Utils.formatPercent(exclusiveTicks, profile.sampleCount); | 462 Utils.formatPercent(exclusiveTicks, profile.sampleCount); |
| 459 | 463 |
| 460 formattedCpuTime = | 464 formattedCpuTime = Utils.formatTimeMilliseconds( |
| 461 Utils.formatTimeMilliseconds( | 465 profile.approximateMillisecondsForCount(exclusiveTicks)); |
| 462 profile.approximateMillisecondsForCount(exclusiveTicks)); | |
| 463 | 466 |
| 464 formattedOnStackTime = | 467 formattedOnStackTime = Utils.formatTimeMilliseconds( |
| 465 Utils.formatTimeMilliseconds( | 468 profile.approximateMillisecondsForCount(inclusiveTicks)); |
| 466 profile.approximateMillisecondsForCount(inclusiveTicks)); | |
| 467 | 469 |
| 468 formattedInclusiveTicks = | 470 formattedInclusiveTicks = |
| 469 '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} ' | 471 '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} ' |
| 470 '($inclusiveTicks)'; | 472 '($inclusiveTicks)'; |
| 471 | 473 |
| 472 formattedExclusiveTicks = | 474 formattedExclusiveTicks = |
| 473 '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} ' | 475 '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} ' |
| 474 '($exclusiveTicks)'; | 476 '($exclusiveTicks)'; |
| 475 } | 477 } |
| 476 | 478 |
| 477 _recordCaller(ProfileCode caller, int count) { | 479 _recordCaller(ProfileCode caller, int count) { |
| 478 var r = callers[caller]; | 480 var r = callers[caller]; |
| 479 if (r == null) { | 481 if (r == null) { |
| 480 r = 0; | 482 r = 0; |
| 481 } | 483 } |
| 482 callers[caller] = r + count; | 484 callers[caller] = r + count; |
| 483 } | 485 } |
| 484 | 486 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 void _addKindBasedAttributes(Set<String> attribs) { | 575 void _addKindBasedAttributes(Set<String> attribs) { |
| 574 if (function.kind == M.FunctionKind.tag) { | 576 if (function.kind == M.FunctionKind.tag) { |
| 575 attribs.add('tag'); | 577 attribs.add('tag'); |
| 576 } else if (function.kind == M.FunctionKind.stub) { | 578 } else if (function.kind == M.FunctionKind.stub) { |
| 577 attribs.add('stub'); | 579 attribs.add('stub'); |
| 578 } else if (function.kind == M.FunctionKind.native) { | 580 } else if (function.kind == M.FunctionKind.native) { |
| 579 attribs.add('native'); | 581 attribs.add('native'); |
| 580 } else if (M.isSyntheticFunction(function.kind)) { | 582 } else if (M.isSyntheticFunction(function.kind)) { |
| 581 attribs.add('synthetic'); | 583 attribs.add('synthetic'); |
| 582 } else if (function.isNative) { | 584 } else if (function.isNative) { |
| 583 attribs.add('ffi'); // Not to be confused with a C function. | 585 attribs.add('ffi'); // Not to be confused with a C function. |
| 584 } else { | 586 } else { |
| 585 attribs.add('dart'); | 587 attribs.add('dart'); |
| 586 } | 588 } |
| 587 if (function.hasIntrinsic == true) { | 589 if (function.hasIntrinsic == true) { |
| 588 attribs.add('intrinsic'); | 590 attribs.add('intrinsic'); |
| 589 } | 591 } |
| 590 } | 592 } |
| 591 | 593 |
| 592 ProfileFunction.fromMap(this.profile, this.function, Map data) { | 594 ProfileFunction.fromMap(this.profile, this.function, Map data) { |
| 593 function.profile = this; | 595 function.profile = this; |
| 594 for (var codeIndex in data['codes']) { | 596 for (var codeIndex in data['codes']) { |
| 595 var profileCode = profile.codes[codeIndex]; | 597 var profileCode = profile.codes[codeIndex]; |
| 596 profileCodes.add(profileCode); | 598 profileCodes.add(profileCode); |
| 597 } | 599 } |
| 598 profileCodes.sort(_sortCodes); | 600 profileCodes.sort(_sortCodes); |
| 599 | 601 |
| 600 _addKindBasedAttributes(attributes); | 602 _addKindBasedAttributes(attributes); |
| 601 exclusiveTicks = int.parse(data['exclusiveTicks']); | 603 exclusiveTicks = int.parse(data['exclusiveTicks']); |
| 602 inclusiveTicks = int.parse(data['inclusiveTicks']); | 604 inclusiveTicks = int.parse(data['inclusiveTicks']); |
| 603 | 605 |
| 604 normalizedExclusiveTicks = exclusiveTicks / profile.sampleCount; | 606 normalizedExclusiveTicks = exclusiveTicks / profile.sampleCount; |
| 605 normalizedInclusiveTicks = inclusiveTicks / profile.sampleCount; | 607 normalizedInclusiveTicks = inclusiveTicks / profile.sampleCount; |
| 606 | 608 |
| 607 formattedExclusivePercent = | 609 formattedExclusivePercent = |
| 608 Utils.formatPercent(exclusiveTicks, profile.sampleCount); | 610 Utils.formatPercent(exclusiveTicks, profile.sampleCount); |
| 609 | 611 |
| 610 formattedCpuTime = | 612 formattedCpuTime = Utils.formatTimeMilliseconds( |
| 611 Utils.formatTimeMilliseconds( | 613 profile.approximateMillisecondsForCount(exclusiveTicks)); |
| 612 profile.approximateMillisecondsForCount(exclusiveTicks)); | |
| 613 | 614 |
| 614 formattedOnStackTime = | 615 formattedOnStackTime = Utils.formatTimeMilliseconds( |
| 615 Utils.formatTimeMilliseconds( | 616 profile.approximateMillisecondsForCount(inclusiveTicks)); |
| 616 profile.approximateMillisecondsForCount(inclusiveTicks)); | |
| 617 | 617 |
| 618 formattedInclusiveTicks = | 618 formattedInclusiveTicks = |
| 619 '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} ' | 619 '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} ' |
| 620 '($inclusiveTicks)'; | 620 '($inclusiveTicks)'; |
| 621 | 621 |
| 622 formattedExclusiveTicks = | 622 formattedExclusiveTicks = |
| 623 '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} ' | 623 '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} ' |
| 624 '($exclusiveTicks)'; | 624 '($exclusiveTicks)'; |
| 625 } | 625 } |
| 626 | 626 |
| 627 _recordCaller(ProfileFunction caller, int count) { | 627 _recordCaller(ProfileFunction caller, int count) { |
| 628 var r = callers[caller]; | 628 var r = callers[caller]; |
| 629 if (r == null) { | 629 if (r == null) { |
| 630 r = 0; | 630 r = 0; |
| 631 } | 631 } |
| 632 callers[caller] = r + count; | 632 callers[caller] = r + count; |
| 633 } | 633 } |
| 634 | 634 |
| 635 _recordCallee(ProfileFunction callee, int count) { | 635 _recordCallee(ProfileFunction callee, int count) { |
| 636 var r = callees[callee]; | 636 var r = callees[callee]; |
| 637 if (r == null) { | 637 if (r == null) { |
| 638 r = 0; | 638 r = 0; |
| 639 } | 639 } |
| 640 callees[callee] = r + count; | 640 callees[callee] = r + count; |
| 641 } | 641 } |
| 642 } | 642 } |
| 643 | 643 |
| 644 | |
| 645 // TODO(johnmccutchan): Rename to SampleProfile | 644 // TODO(johnmccutchan): Rename to SampleProfile |
| 646 class CpuProfile extends M.SampleProfile { | 645 class CpuProfile extends M.SampleProfile { |
| 647 | |
| 648 Isolate isolate; | 646 Isolate isolate; |
| 649 | 647 |
| 650 int sampleCount = 0; | 648 int sampleCount = 0; |
| 651 int samplePeriod = 0; | 649 int samplePeriod = 0; |
| 652 double sampleRate = 0.0; | 650 double sampleRate = 0.0; |
| 653 | 651 |
| 654 int stackDepth = 0; | 652 int stackDepth = 0; |
| 655 | 653 |
| 656 double timeSpan = 0.0; | 654 double timeSpan = 0.0; |
| 657 | 655 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 711 _builtCodeCalls = false; | 709 _builtCodeCalls = false; |
| 712 _builtFunctionCalls = false; | 710 _builtFunctionCalls = false; |
| 713 } | 711 } |
| 714 | 712 |
| 715 Future load(Isolate isolate, ServiceMap profile) async { | 713 Future load(Isolate isolate, ServiceMap profile) async { |
| 716 await loadProgress(isolate, profile).last; | 714 await loadProgress(isolate, profile).last; |
| 717 } | 715 } |
| 718 | 716 |
| 719 static Future sleep([Duration duration = const Duration(microseconds: 0)]) { | 717 static Future sleep([Duration duration = const Duration(microseconds: 0)]) { |
| 720 final Completer completer = new Completer(); | 718 final Completer completer = new Completer(); |
| 721 new Timer(duration, () => completer.complete() ); | 719 new Timer(duration, () => completer.complete()); |
| 722 return completer.future; | 720 return completer.future; |
| 723 } | 721 } |
| 724 | 722 |
| 725 Stream<double> loadProgress(Isolate isolate, ServiceMap profile) { | 723 Stream<double> loadProgress(Isolate isolate, ServiceMap profile) { |
| 726 var progress = new StreamController<double>.broadcast(); | 724 var progress = new StreamController<double>.broadcast(); |
| 727 | 725 |
| 728 (() async { | 726 (() async { |
| 729 final Stopwatch watch = new Stopwatch(); | 727 final Stopwatch watch = new Stopwatch(); |
| 730 watch.start(); | 728 watch.start(); |
| 731 int count = 0; | 729 int count = 0; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 750 | 748 |
| 751 this.isolate = isolate; | 749 this.isolate = isolate; |
| 752 isolate.resetCachedProfileData(); | 750 isolate.resetCachedProfileData(); |
| 753 | 751 |
| 754 sampleCount = profile['sampleCount']; | 752 sampleCount = profile['sampleCount']; |
| 755 samplePeriod = profile['samplePeriod']; | 753 samplePeriod = profile['samplePeriod']; |
| 756 sampleRate = (Duration.MICROSECONDS_PER_SECOND / samplePeriod); | 754 sampleRate = (Duration.MICROSECONDS_PER_SECOND / samplePeriod); |
| 757 stackDepth = profile['stackDepth']; | 755 stackDepth = profile['stackDepth']; |
| 758 timeSpan = profile['timeSpan']; | 756 timeSpan = profile['timeSpan']; |
| 759 | 757 |
| 760 num length = profile['codes'].length + | 758 num length = profile['codes'].length + profile['functions'].length; |
| 761 profile['functions'].length; | |
| 762 | 759 |
| 763 // Process code table. | 760 // Process code table. |
| 764 for (var codeRegion in profile['codes']) { | 761 for (var codeRegion in profile['codes']) { |
| 765 if (needToUpdate()) { | 762 if (needToUpdate()) { |
| 766 await signal(count * 100.0 / length); | 763 await signal(count * 100.0 / length); |
| 767 } | 764 } |
| 768 Code code = codeRegion['code']; | 765 Code code = codeRegion['code']; |
| 769 assert(code != null); | 766 assert(code != null); |
| 770 codes.add(new ProfileCode.fromMap(this, code, codeRegion)); | 767 codes.add(new ProfileCode.fromMap(this, code, codeRegion)); |
| 771 } | 768 } |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 966 } | 963 } |
| 967 | 964 |
| 968 int approximateMillisecondsForCount(count) { | 965 int approximateMillisecondsForCount(count) { |
| 969 return (count * samplePeriod) ~/ Duration.MICROSECONDS_PER_MILLISECOND; | 966 return (count * samplePeriod) ~/ Duration.MICROSECONDS_PER_MILLISECOND; |
| 970 } | 967 } |
| 971 | 968 |
| 972 double approximateSecondsForCount(count) { | 969 double approximateSecondsForCount(count) { |
| 973 return (count * samplePeriod) / Duration.MICROSECONDS_PER_SECOND; | 970 return (count * samplePeriod) / Duration.MICROSECONDS_PER_SECOND; |
| 974 } | 971 } |
| 975 } | 972 } |
| OLD | NEW |