| 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 class CodeCallTreeNode { | 7 class CodeCallTreeNode { |
| 8 final ProfileCode profileCode; | 8 final ProfileCode profileCode; |
| 9 final int count; | 9 final int count; |
| 10 double get percentage => _percentage; | 10 double get percentage => _percentage; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 } | 34 } |
| 35 if (inclusive) { | 35 if (inclusive) { |
| 36 node._percentage = parentPercentage * (node.count / parentCount); | 36 node._percentage = parentPercentage * (node.count / parentCount); |
| 37 } else { | 37 } else { |
| 38 node._percentage = (node.count / parentCount); | 38 node._percentage = (node.count / parentCount); |
| 39 } | 39 } |
| 40 for (var child in node.children) { | 40 for (var child in node.children) { |
| 41 _setCodePercentage(node, child); | 41 _setCodePercentage(node, child); |
| 42 } | 42 } |
| 43 } | 43 } |
| 44 |
| 45 _recordCallerAndCalleesInner(CodeCallTreeNode caller, |
| 46 CodeCallTreeNode callee) { |
| 47 if (caller != null) { |
| 48 caller.profileCode._recordCallee(callee.profileCode, callee.count); |
| 49 callee.profileCode._recordCaller(caller.profileCode, callee.count); |
| 50 } |
| 51 |
| 52 for (var child in callee.children) { |
| 53 _recordCallerAndCalleesInner(callee, child); |
| 54 } |
| 55 } |
| 56 |
| 57 _recordCallerAndCallees() { |
| 58 for (var child in root.children) { |
| 59 _recordCallerAndCalleesInner(null, child); |
| 60 } |
| 61 } |
| 44 } | 62 } |
| 45 | 63 |
| 46 class FunctionCallTreeNodeCode { | 64 class FunctionCallTreeNodeCode { |
| 47 final ProfileCode code; | 65 final ProfileCode code; |
| 48 final int ticks; | 66 final int ticks; |
| 49 FunctionCallTreeNodeCode(this.code, this.ticks); | 67 FunctionCallTreeNodeCode(this.code, this.ticks); |
| 50 } | 68 } |
| 51 | 69 |
| 52 class FunctionCallTreeNode { | 70 class FunctionCallTreeNode { |
| 53 final ProfileFunction profileFunction; | 71 final ProfileFunction profileFunction; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 } | 140 } |
| 123 if (hasUnoptimizedCode()) { | 141 if (hasUnoptimizedCode()) { |
| 124 attributes.add('unoptimized'); | 142 attributes.add('unoptimized'); |
| 125 } | 143 } |
| 126 if (isInlined()) { | 144 if (isInlined()) { |
| 127 attributes.add('inlined'); | 145 attributes.add('inlined'); |
| 128 } | 146 } |
| 129 } | 147 } |
| 130 } | 148 } |
| 131 | 149 |
| 150 /// Predicate filter function. Returns true if path from root to [node] and all |
| 151 /// of [node]'s children should be added to the filtered tree. |
| 152 typedef bool FunctionCallTreeNodeFilter(FunctionCallTreeNode node); |
| 153 |
| 154 /// Build a filter version of a FunctionCallTree. |
| 155 class _FilteredFunctionCallTreeBuilder { |
| 156 /// The filter. |
| 157 final FunctionCallTreeNodeFilter filter; |
| 158 /// The unfiltered tree. |
| 159 final FunctionCallTree _unfilteredTree; |
| 160 /// The filtered tree (construct by [build]). |
| 161 final FunctionCallTree filtered; |
| 162 final List _currentPath = []; |
| 163 |
| 164 /// Construct a filtered tree builder using [filter] and [tree]. |
| 165 _FilteredFunctionCallTreeBuilder(this.filter, FunctionCallTree tree) |
| 166 : _unfilteredTree = tree, |
| 167 filtered = |
| 168 new FunctionCallTree( |
| 169 tree.inclusive, |
| 170 new FunctionCallTreeNode( |
| 171 tree.root.profileFunction, |
| 172 tree.root.count)); |
| 173 |
| 174 /// Build the filtered tree. |
| 175 build() { |
| 176 assert(filtered != null); |
| 177 assert(filter != null); |
| 178 assert(_unfilteredTree != null); |
| 179 _descend(_unfilteredTree.root); |
| 180 } |
| 181 |
| 182 FunctionCallTreeNode _findFunctionInChildren(FunctionCallTreeNode current, |
| 183 FunctionCallTreeNode needle) { |
| 184 for (var child in current.children) { |
| 185 if (child.profileFunction == needle.profileFunction) { |
| 186 return child; |
| 187 } |
| 188 } |
| 189 return null; |
| 190 } |
| 191 |
| 192 /// Add all nodes in [_currentPath]. |
| 193 FunctionCallTreeNode _addCurrentPath() { |
| 194 FunctionCallTreeNode current = filtered.root; |
| 195 // Tree root is always the first element of the current path. |
| 196 assert(_unfilteredTree.root == _currentPath[0]); |
| 197 // Assert that unfiltered tree's root and filtered tree's root are different
. |
| 198 assert(_unfilteredTree.root != current); |
| 199 for (var i = 1; i < _currentPath.length; i++) { |
| 200 // toAdd is from the unfiltered tree. |
| 201 var toAdd = _currentPath[i]; |
| 202 // See if we already have a node for toAdd in the filtered tree. |
| 203 var child = _findFunctionInChildren(current, toAdd); |
| 204 if (child == null) { |
| 205 // New node. |
| 206 child = new FunctionCallTreeNode(toAdd.profileFunction, toAdd.count); |
| 207 current.children.add(child); |
| 208 } |
| 209 current = child; |
| 210 assert(current.count == toAdd.count); |
| 211 } |
| 212 return current; |
| 213 } |
| 214 |
| 215 /// Starting at [current] append [next] and all of [next]'s sub-trees |
| 216 _appendTree(FunctionCallTreeNode current, FunctionCallTreeNode next) { |
| 217 if (next == null) { |
| 218 return; |
| 219 } |
| 220 var child = _findFunctionInChildren(current, next); |
| 221 if (child == null) { |
| 222 child = new FunctionCallTreeNode(next.profileFunction, next.count); |
| 223 current.children.add(child); |
| 224 } |
| 225 current = child; |
| 226 for (var nextChild in next.children) { |
| 227 _appendTree(current, nextChild); |
| 228 } |
| 229 } |
| 230 |
| 231 /// Add path from root to [child], [child], and all of [child]'s sub-trees |
| 232 /// to filtered tree. |
| 233 _addTree(FunctionCallTreeNode child) { |
| 234 var current = _addCurrentPath(); |
| 235 _appendTree(current, child); |
| 236 } |
| 237 |
| 238 /// Descend further into the tree. [current] is from the unfiltered tree. |
| 239 _descend(FunctionCallTreeNode current) { |
| 240 if (current == null) { |
| 241 return; |
| 242 } |
| 243 _currentPath.add(current); |
| 244 |
| 245 if (filter(current)) { |
| 246 // Filter matched. |
| 247 if (current.children.length == 0) { |
| 248 // Have no children. Add this path. |
| 249 _addTree(null); |
| 250 } else { |
| 251 // Add all child trees. |
| 252 for (var child in current.children) { |
| 253 _addTree(child); |
| 254 } |
| 255 } |
| 256 } else { |
| 257 // Did not match, descend to each child. |
| 258 for (var child in current.children) { |
| 259 _descend(child); |
| 260 } |
| 261 } |
| 262 |
| 263 var last = _currentPath.removeLast(); |
| 264 assert(current == last); |
| 265 } |
| 266 } |
| 267 |
| 132 class FunctionCallTree { | 268 class FunctionCallTree { |
| 133 final bool inclusive; | 269 final bool inclusive; |
| 134 final FunctionCallTreeNode root; | 270 final FunctionCallTreeNode root; |
| 135 FunctionCallTree(this.inclusive, this.root) { | 271 FunctionCallTree(this.inclusive, this.root) { |
| 136 _setFunctionPercentage(null, root); | 272 _setFunctionPercentage(null, root); |
| 137 } | 273 } |
| 138 | 274 |
| 275 FunctionCallTree filtered(FunctionCallTreeNodeFilter filter) { |
| 276 var treeFilter = new _FilteredFunctionCallTreeBuilder(filter, this); |
| 277 treeFilter.build(); |
| 278 _setFunctionPercentage(null, treeFilter.filtered.root); |
| 279 return treeFilter.filtered; |
| 280 } |
| 281 |
| 139 void _setFunctionPercentage(FunctionCallTreeNode parent, | 282 void _setFunctionPercentage(FunctionCallTreeNode parent, |
| 140 FunctionCallTreeNode node) { | 283 FunctionCallTreeNode node) { |
| 141 assert(node != null); | 284 assert(node != null); |
| 142 var parentPercentage = 1.0; | 285 var parentPercentage = 1.0; |
| 143 var parentCount = node.count; | 286 var parentCount = node.count; |
| 144 if (parent != null) { | 287 if (parent != null) { |
| 145 parentPercentage = parent._percentage; | 288 parentPercentage = parent._percentage; |
| 146 parentCount = parent.count; | 289 parentCount = parent.count; |
| 147 } | 290 } |
| 148 if (inclusive) { | 291 if (inclusive) { |
| 149 node._percentage = parentPercentage * (node.count / parentCount); | 292 node._percentage = parentPercentage * (node.count / parentCount); |
| 150 } else { | 293 } else { |
| 151 node._percentage = (node.count / parentCount); | 294 node._percentage = (node.count / parentCount); |
| 152 } | 295 } |
| 153 for (var child in node.children) { | 296 for (var child in node.children) { |
| 154 _setFunctionPercentage(node, child); | 297 _setFunctionPercentage(node, child); |
| 155 } | 298 } |
| 156 } | 299 } |
| 300 |
| 301 _markFunctionCallsInner(FunctionCallTreeNode caller, |
| 302 FunctionCallTreeNode callee) { |
| 303 if (caller != null) { |
| 304 caller.profileFunction._recordCallee(callee.profileFunction, callee.count)
; |
| 305 callee.profileFunction._recordCaller(caller.profileFunction, callee.count)
; |
| 306 } |
| 307 for (var child in callee.children) { |
| 308 _markFunctionCallsInner(callee, child); |
| 309 } |
| 310 } |
| 311 |
| 312 _markFunctionCalls() { |
| 313 for (var child in root.children) { |
| 314 _markFunctionCallsInner(null, child); |
| 315 } |
| 316 } |
| 157 } | 317 } |
| 158 | 318 |
| 159 class CodeTick { | 319 class CodeTick { |
| 160 final int exclusiveTicks; | 320 final int exclusiveTicks; |
| 161 final int inclusiveTicks; | 321 final int inclusiveTicks; |
| 162 CodeTick(this.exclusiveTicks, this.inclusiveTicks); | 322 CodeTick(this.exclusiveTicks, this.inclusiveTicks); |
| 163 } | 323 } |
| 164 | 324 |
| 165 class InlineIntervalTick { | 325 class InlineIntervalTick { |
| 166 final int startAddress; | 326 final int startAddress; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 179 double normalizedExclusiveTicks = 0.0; | 339 double normalizedExclusiveTicks = 0.0; |
| 180 double normalizedInclusiveTicks = 0.0; | 340 double normalizedInclusiveTicks = 0.0; |
| 181 final addressTicks = new Map<int, CodeTick>(); | 341 final addressTicks = new Map<int, CodeTick>(); |
| 182 final intervalTicks = new Map<int, InlineIntervalTick>(); | 342 final intervalTicks = new Map<int, InlineIntervalTick>(); |
| 183 String formattedInclusiveTicks = ''; | 343 String formattedInclusiveTicks = ''; |
| 184 String formattedExclusiveTicks = ''; | 344 String formattedExclusiveTicks = ''; |
| 185 String formattedExclusivePercent = ''; | 345 String formattedExclusivePercent = ''; |
| 186 String formattedCpuTime = ''; | 346 String formattedCpuTime = ''; |
| 187 String formattedOnStackTime = ''; | 347 String formattedOnStackTime = ''; |
| 188 final Set<String> attributes = new Set<String>(); | 348 final Set<String> attributes = new Set<String>(); |
| 349 final Map<ProfileCode, int> callers = new Map<ProfileCode, int>(); |
| 350 final Map<ProfileCode, int> callees = new Map<ProfileCode, int>(); |
| 189 | 351 |
| 190 void _processTicks(List<String> profileTicks) { | 352 void _processTicks(List<String> profileTicks) { |
| 191 assert(profileTicks != null); | 353 assert(profileTicks != null); |
| 192 assert((profileTicks.length % 3) == 0); | 354 assert((profileTicks.length % 3) == 0); |
| 193 for (var i = 0; i < profileTicks.length; i += 3) { | 355 for (var i = 0; i < profileTicks.length; i += 3) { |
| 194 var address = int.parse(profileTicks[i], radix:16); | 356 var address = int.parse(profileTicks[i], radix:16); |
| 195 var exclusive = int.parse(profileTicks[i + 1]); | 357 var exclusive = int.parse(profileTicks[i + 1]); |
| 196 var inclusive = int.parse(profileTicks[i + 2]); | 358 var inclusive = int.parse(profileTicks[i + 2]); |
| 197 var tick = new CodeTick(exclusive, inclusive); | 359 var tick = new CodeTick(exclusive, inclusive); |
| 198 addressTicks[address] = tick; | 360 addressTicks[address] = tick; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 profile.approximateMillisecondsForCount(inclusiveTicks)); | 417 profile.approximateMillisecondsForCount(inclusiveTicks)); |
| 256 | 418 |
| 257 formattedInclusiveTicks = | 419 formattedInclusiveTicks = |
| 258 '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} ' | 420 '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} ' |
| 259 '($inclusiveTicks)'; | 421 '($inclusiveTicks)'; |
| 260 | 422 |
| 261 formattedExclusiveTicks = | 423 formattedExclusiveTicks = |
| 262 '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} ' | 424 '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} ' |
| 263 '($exclusiveTicks)'; | 425 '($exclusiveTicks)'; |
| 264 } | 426 } |
| 427 |
| 428 _recordCaller(ProfileCode caller, int count) { |
| 429 var r = callers[caller]; |
| 430 if (r == null) { |
| 431 r = 0; |
| 432 } |
| 433 callers[caller] = r + count; |
| 434 } |
| 435 |
| 436 _recordCallee(ProfileCode callee, int count) { |
| 437 var r = callees[callee]; |
| 438 if (r == null) { |
| 439 r = 0; |
| 440 } |
| 441 callees[callee] = r + count; |
| 442 } |
| 265 } | 443 } |
| 266 | 444 |
| 267 class ProfileFunction { | 445 class ProfileFunction { |
| 268 final CpuProfile profile; | 446 final CpuProfile profile; |
| 269 final ServiceFunction function; | 447 final ServiceFunction function; |
| 270 // List of compiled code objects containing this function. | 448 // List of compiled code objects containing this function. |
| 271 final List<ProfileCode> profileCodes = new List<ProfileCode>(); | 449 final List<ProfileCode> profileCodes = new List<ProfileCode>(); |
| 450 final Map<ProfileFunction, int> callers = new Map<ProfileFunction, int>(); |
| 451 final Map<ProfileFunction, int> callees = new Map<ProfileFunction, int>(); |
| 452 |
| 272 // Absolute ticks: | 453 // Absolute ticks: |
| 273 int exclusiveTicks = 0; | 454 int exclusiveTicks = 0; |
| 274 int inclusiveTicks = 0; | 455 int inclusiveTicks = 0; |
| 275 | 456 |
| 276 // Global percentages: | 457 // Global percentages: |
| 277 double normalizedExclusiveTicks = 0.0; | 458 double normalizedExclusiveTicks = 0.0; |
| 278 double normalizedInclusiveTicks = 0.0; | 459 double normalizedInclusiveTicks = 0.0; |
| 279 | 460 |
| 280 String formattedInclusiveTicks = ''; | 461 String formattedInclusiveTicks = ''; |
| 281 String formattedExclusiveTicks = ''; | 462 String formattedExclusiveTicks = ''; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 } else if (function.kind == FunctionKind.kNative) { | 530 } else if (function.kind == FunctionKind.kNative) { |
| 350 attribs.add('native'); | 531 attribs.add('native'); |
| 351 } else if (function.kind.isSynthetic()) { | 532 } else if (function.kind.isSynthetic()) { |
| 352 attribs.add('synthetic'); | 533 attribs.add('synthetic'); |
| 353 } else { | 534 } else { |
| 354 attribs.add('dart'); | 535 attribs.add('dart'); |
| 355 } | 536 } |
| 356 } | 537 } |
| 357 | 538 |
| 358 ProfileFunction.fromMap(this.profile, this.function, Map data) { | 539 ProfileFunction.fromMap(this.profile, this.function, Map data) { |
| 540 function.profile = this; |
| 359 for (var codeIndex in data['codes']) { | 541 for (var codeIndex in data['codes']) { |
| 360 var profileCode = profile.codes[codeIndex]; | 542 var profileCode = profile.codes[codeIndex]; |
| 361 profileCodes.add(profileCode); | 543 profileCodes.add(profileCode); |
| 362 } | 544 } |
| 363 profileCodes.sort(_sortCodes); | 545 profileCodes.sort(_sortCodes); |
| 364 | 546 |
| 365 if (hasOptimizedCode()) { | 547 if (hasOptimizedCode()) { |
| 366 attributes.add('optimized'); | 548 attributes.add('optimized'); |
| 367 } | 549 } |
| 368 if (hasUnoptimizedCode()) { | 550 if (hasUnoptimizedCode()) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 390 profile.approximateMillisecondsForCount(inclusiveTicks)); | 572 profile.approximateMillisecondsForCount(inclusiveTicks)); |
| 391 | 573 |
| 392 formattedInclusiveTicks = | 574 formattedInclusiveTicks = |
| 393 '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} ' | 575 '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} ' |
| 394 '($inclusiveTicks)'; | 576 '($inclusiveTicks)'; |
| 395 | 577 |
| 396 formattedExclusiveTicks = | 578 formattedExclusiveTicks = |
| 397 '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} ' | 579 '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} ' |
| 398 '($exclusiveTicks)'; | 580 '($exclusiveTicks)'; |
| 399 } | 581 } |
| 582 |
| 583 _recordCaller(ProfileFunction caller, int count) { |
| 584 var r = callers[caller]; |
| 585 if (r == null) { |
| 586 r = 0; |
| 587 } |
| 588 callers[caller] = r + count; |
| 589 } |
| 590 |
| 591 _recordCallee(ProfileFunction callee, int count) { |
| 592 var r = callees[callee]; |
| 593 if (r == null) { |
| 594 r = 0; |
| 595 } |
| 596 callees[callee] = r + count; |
| 597 } |
| 400 } | 598 } |
| 401 | 599 |
| 402 | 600 |
| 403 class CpuProfile { | 601 class CpuProfile { |
| 404 final double MICROSECONDS_PER_SECOND = 1000000.0; | 602 final double MICROSECONDS_PER_SECOND = 1000000.0; |
| 405 final double displayThreshold = 0.0002; // 0.02%. | 603 final double displayThreshold = 0.0002; // 0.02%. |
| 406 | 604 |
| 407 Isolate isolate; | 605 Isolate isolate; |
| 408 | 606 |
| 409 int sampleCount = 0; | 607 int sampleCount = 0; |
| 410 int samplePeriod = 0; | 608 int samplePeriod = 0; |
| 411 double sampleRate = 0.0; | 609 double sampleRate = 0.0; |
| 412 | 610 |
| 413 int stackDepth = 0; | 611 int stackDepth = 0; |
| 414 | 612 |
| 415 double timeSpan = 0.0; | 613 double timeSpan = 0.0; |
| 416 | 614 |
| 417 final Map<String, List> tries = <String, List>{}; | 615 final Map<String, List> tries = <String, List>{}; |
| 418 final List<ProfileCode> codes = new List<ProfileCode>(); | 616 final List<ProfileCode> codes = new List<ProfileCode>(); |
| 617 bool _builtCodeCalls = false; |
| 419 final List<ProfileFunction> functions = new List<ProfileFunction>(); | 618 final List<ProfileFunction> functions = new List<ProfileFunction>(); |
| 619 bool _builtFunctionCalls = false; |
| 420 | 620 |
| 421 CodeCallTree loadCodeTree(String name) { | 621 CodeCallTree loadCodeTree(String name) { |
| 422 if (name == 'inclusive') { | 622 if (name == 'inclusive') { |
| 423 return _loadCodeTree(true, tries['inclusiveCodeTrie']); | 623 return _loadCodeTree(true, tries['inclusiveCodeTrie']); |
| 424 } else { | 624 } else { |
| 425 return _loadCodeTree(false, tries['exclusiveCodeTrie']); | 625 return _loadCodeTree(false, tries['exclusiveCodeTrie']); |
| 426 } | 626 } |
| 427 } | 627 } |
| 428 | 628 |
| 429 FunctionCallTree loadFunctionTree(String name) { | 629 FunctionCallTree loadFunctionTree(String name) { |
| 430 if (name == 'inclusive') { | 630 if (name == 'inclusive') { |
| 431 return _loadFunctionTree(true, tries['inclusiveFunctionTrie']); | 631 return _loadFunctionTree(true, tries['inclusiveFunctionTrie']); |
| 432 } else { | 632 } else { |
| 433 return _loadFunctionTree(false, tries['exclusiveFunctionTrie']); | 633 return _loadFunctionTree(false, tries['exclusiveFunctionTrie']); |
| 434 } | 634 } |
| 435 } | 635 } |
| 436 | 636 |
| 437 void clear() { | 637 buildCodeCallerAndCallees() { |
| 638 if (_builtCodeCalls) { |
| 639 return; |
| 640 } |
| 641 _builtCodeCalls = true; |
| 642 var tree = loadCodeTree('inclusive'); |
| 643 tree._recordCallerAndCallees(); |
| 644 } |
| 645 |
| 646 buildFunctionCallerAndCallees() { |
| 647 if (_builtFunctionCalls) { |
| 648 return; |
| 649 } |
| 650 _builtFunctionCalls = true; |
| 651 var tree = loadFunctionTree('inclusive'); |
| 652 tree._markFunctionCalls(); |
| 653 } |
| 654 |
| 655 clear() { |
| 438 sampleCount = 0; | 656 sampleCount = 0; |
| 439 samplePeriod = 0; | 657 samplePeriod = 0; |
| 440 sampleRate = 0.0; | 658 sampleRate = 0.0; |
| 441 stackDepth = 0; | 659 stackDepth = 0; |
| 442 timeSpan = 0.0; | 660 timeSpan = 0.0; |
| 443 codes.clear(); | 661 codes.clear(); |
| 444 functions.clear(); | 662 functions.clear(); |
| 445 tries.clear(); | 663 tries.clear(); |
| 664 _builtCodeCalls = false; |
| 665 _builtFunctionCalls = false; |
| 446 } | 666 } |
| 447 | 667 |
| 448 void load(Isolate isolate, ServiceMap profile) { | 668 load(Isolate isolate, ServiceMap profile) { |
| 449 clear(); | 669 clear(); |
| 450 if ((isolate == null) || (profile == null)) { | 670 if ((isolate == null) || (profile == null)) { |
| 451 return; | 671 return; |
| 452 } | 672 } |
| 453 | 673 |
| 454 this.isolate = isolate; | 674 this.isolate = isolate; |
| 455 isolate.resetCachedProfileData(); | 675 isolate.resetCachedProfileData(); |
| 456 | 676 |
| 457 sampleCount = profile['sampleCount']; | 677 sampleCount = profile['sampleCount']; |
| 458 samplePeriod = profile['samplePeriod']; | 678 samplePeriod = profile['samplePeriod']; |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 int approximateMillisecondsForCount(count) { | 877 int approximateMillisecondsForCount(count) { |
| 658 var MICROSECONDS_PER_MILLISECOND = 1000.0; | 878 var MICROSECONDS_PER_MILLISECOND = 1000.0; |
| 659 return (count * samplePeriod) ~/ MICROSECONDS_PER_MILLISECOND; | 879 return (count * samplePeriod) ~/ MICROSECONDS_PER_MILLISECOND; |
| 660 } | 880 } |
| 661 | 881 |
| 662 double approximateSecondsForCount(count) { | 882 double approximateSecondsForCount(count) { |
| 663 var MICROSECONDS_PER_SECOND = 1000000.0; | 883 var MICROSECONDS_PER_SECOND = 1000000.0; |
| 664 return (count * samplePeriod) / MICROSECONDS_PER_SECOND; | 884 return (count * samplePeriod) / MICROSECONDS_PER_SECOND; |
| 665 } | 885 } |
| 666 } | 886 } |
| OLD | NEW |