Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(687)

Side by Side Diff: runtime/observatory/lib/src/cpu_profile/cpu_profile.dart

Issue 2204563003: Converted Observatory cpu-profile element (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Removed tmp files Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 { 7 abstract class CallTreeNode<NodeT extends M.CallTreeNode>
8 final List<CallTreeNode> children; 8 implements M.CallTreeNode {
9 final List<NodeT> children;
9 final int count; 10 final int count;
10 double get percentage => _percentage; 11 double get percentage => _percentage;
11 double _percentage = 0.0; 12 double _percentage = 0.0;
12 final Set<String> attributes = new Set<String>(); 13 final Set<String> attributes = new Set<String>();
13 14
14 // Either a ProfileCode or a ProfileFunction. 15 // Either a ProfileCode or a ProfileFunction.
15 Object get profileData; 16 Object get profileData;
16 String get name; 17 String get name;
17 18
18 CallTreeNode(this.children, this.count); 19 CallTreeNode(this.children, this.count);
19 } 20 }
20 21
21 class CodeCallTreeNode extends CallTreeNode { 22 class CodeCallTreeNode extends CallTreeNode<CodeCallTreeNode>
23 implements M.CodeCallTreeNode {
22 final ProfileCode profileCode; 24 final ProfileCode profileCode;
23 25
24 Object get profileData => profileCode; 26 Object get profileData => profileCode;
25 27
26 String get name => profileCode.code.name; 28 String get name => profileCode.code.name;
27 29
28 final Set<String> attributes = new Set<String>(); 30 final Set<String> attributes = new Set<String>();
29 CodeCallTreeNode(this.profileCode, int count) 31 CodeCallTreeNode(this.profileCode, int count)
30 : super(new List<CodeCallTreeNode>(), count) { 32 : super(new List<CodeCallTreeNode>(), count) {
31 attributes.addAll(profileCode.attributes); 33 attributes.addAll(profileCode.attributes);
32 } 34 }
33 } 35 }
34 36
35 class CallTree { 37 class CallTree<NodeT extends CallTreeNode> {
36 final bool inclusive; 38 final bool inclusive;
37 final CallTreeNode root; 39 final NodeT root;
38 40
39 CallTree(this.inclusive, this.root); 41 CallTree(this.inclusive, this.root);
40 } 42 }
41 43
42 class CodeCallTree extends CallTree { 44 class CodeCallTree extends CallTree<CodeCallTreeNode>
45 implements M.CodeCallTree {
43 CodeCallTree(bool inclusive, CodeCallTreeNode root) 46 CodeCallTree(bool inclusive, CodeCallTreeNode root)
44 : super(inclusive, root) { 47 : super(inclusive, root) {
45 _setCodePercentage(null, root); 48 _setCodePercentage(null, root);
46 } 49 }
47 50
48 CodeCallTree filtered(CallTreeNodeFilter filter) { 51 CodeCallTree filtered(CallTreeNodeFilter filter) {
49 var treeFilter = new _FilteredCodeCallTreeBuilder(filter, this); 52 var treeFilter = new _FilteredCodeCallTreeBuilder(filter, this);
50 treeFilter.build(); 53 treeFilter.build();
51 _setCodePercentage(null, treeFilter.filtered.root); 54 _setCodePercentage(null, treeFilter.filtered.root);
52 return treeFilter.filtered; 55 return treeFilter.filtered;
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 : super(filter, tree, 301 : super(filter, tree,
299 new CodeCallTree(tree.inclusive, 302 new CodeCallTree(tree.inclusive,
300 new CodeCallTreeNode(tree.root.profileData, 303 new CodeCallTreeNode(tree.root.profileData,
301 tree.root.count))); 304 tree.root.count)));
302 305
303 _copyNode(CodeCallTreeNode node) { 306 _copyNode(CodeCallTreeNode node) {
304 return new CodeCallTreeNode(node.profileData, node.count); 307 return new CodeCallTreeNode(node.profileData, node.count);
305 } 308 }
306 } 309 }
307 310
308 class FunctionCallTree extends CallTree { 311 class FunctionCallTree extends CallTree implements M.FunctionCallTree {
309 FunctionCallTree(bool inclusive, FunctionCallTreeNode root) 312 FunctionCallTree(bool inclusive, FunctionCallTreeNode root)
310 : super(inclusive, root) { 313 : super(inclusive, root) {
311 _setFunctionPercentage(null, root); 314 _setFunctionPercentage(null, root);
312 } 315 }
313 316
314 FunctionCallTree filtered(CallTreeNodeFilter filter) { 317 FunctionCallTree filtered(CallTreeNodeFilter filter) {
315 var treeFilter = new _FilteredFunctionCallTreeBuilder(filter, this); 318 var treeFilter = new _FilteredFunctionCallTreeBuilder(filter, this);
316 treeFilter.build(); 319 treeFilter.build();
317 _setFunctionPercentage(null, treeFilter.filtered.root); 320 _setFunctionPercentage(null, treeFilter.filtered.root);
318 return treeFilter.filtered; 321 return treeFilter.filtered;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 366
364 class InlineIntervalTick { 367 class InlineIntervalTick {
365 final int startAddress; 368 final int startAddress;
366 int _inclusiveTicks = 0; 369 int _inclusiveTicks = 0;
367 int get inclusiveTicks => _inclusiveTicks; 370 int get inclusiveTicks => _inclusiveTicks;
368 int _exclusiveTicks = 0; 371 int _exclusiveTicks = 0;
369 int get exclusiveTicks => _exclusiveTicks; 372 int get exclusiveTicks => _exclusiveTicks;
370 InlineIntervalTick(this.startAddress); 373 InlineIntervalTick(this.startAddress);
371 } 374 }
372 375
373 class ProfileCode { 376 class ProfileCode implements M.ProfileCode {
374 final CpuProfile profile; 377 final CpuProfile profile;
375 final Code code; 378 final Code code;
376 int exclusiveTicks; 379 int exclusiveTicks;
377 int inclusiveTicks; 380 int inclusiveTicks;
378 double normalizedExclusiveTicks = 0.0; 381 double normalizedExclusiveTicks = 0.0;
379 double normalizedInclusiveTicks = 0.0; 382 double normalizedInclusiveTicks = 0.0;
380 final addressTicks = new Map<int, CodeTick>(); 383 final addressTicks = new Map<int, CodeTick>();
381 final intervalTicks = new Map<int, InlineIntervalTick>(); 384 final intervalTicks = new Map<int, InlineIntervalTick>();
382 String formattedInclusiveTicks = ''; 385 String formattedInclusiveTicks = '';
383 String formattedExclusiveTicks = ''; 386 String formattedExclusiveTicks = '';
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 484
482 _recordCallee(ProfileCode callee, int count) { 485 _recordCallee(ProfileCode callee, int count) {
483 var r = callees[callee]; 486 var r = callees[callee];
484 if (r == null) { 487 if (r == null) {
485 r = 0; 488 r = 0;
486 } 489 }
487 callees[callee] = r + count; 490 callees[callee] = r + count;
488 } 491 }
489 } 492 }
490 493
491 class ProfileFunction { 494 class ProfileFunction implements M.ProfileFunction {
492 final CpuProfile profile; 495 final CpuProfile profile;
493 final ServiceFunction function; 496 final ServiceFunction function;
494 // List of compiled code objects containing this function. 497 // List of compiled code objects containing this function.
495 final List<ProfileCode> profileCodes = new List<ProfileCode>(); 498 final List<ProfileCode> profileCodes = new List<ProfileCode>();
496 final Map<ProfileFunction, int> callers = new Map<ProfileFunction, int>(); 499 final Map<ProfileFunction, int> callers = new Map<ProfileFunction, int>();
497 final Map<ProfileFunction, int> callees = new Map<ProfileFunction, int>(); 500 final Map<ProfileFunction, int> callees = new Map<ProfileFunction, int>();
498 501
499 // Absolute ticks: 502 // Absolute ticks:
500 int exclusiveTicks = 0; 503 int exclusiveTicks = 0;
501 int inclusiveTicks = 0; 504 int inclusiveTicks = 0;
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 var r = callees[callee]; 636 var r = callees[callee];
634 if (r == null) { 637 if (r == null) {
635 r = 0; 638 r = 0;
636 } 639 }
637 callees[callee] = r + count; 640 callees[callee] = r + count;
638 } 641 }
639 } 642 }
640 643
641 644
642 // TODO(johnmccutchan): Rename to SampleProfile 645 // TODO(johnmccutchan): Rename to SampleProfile
643 class CpuProfile { 646 class CpuProfile extends M.SampleProfile {
644 final double MICROSECONDS_PER_SECOND = 1000000.0; 647 static const double MICROSECONDS_PER_SECOND = 1000000.0;
645 final double displayThreshold = 0.0002; // 0.02%. 648 static const double MICROSECONDS_PER_MILLISECOND = 1000.0;
649 static const double displayThreshold = 0.0002; // 0.02%.
646 650
647 Isolate isolate; 651 Isolate isolate;
648 652
649 int sampleCount = 0; 653 int sampleCount = 0;
650 int samplePeriod = 0; 654 int samplePeriod = 0;
651 double sampleRate = 0.0; 655 double sampleRate = 0.0;
652 656
653 int stackDepth = 0; 657 int stackDepth = 0;
654 658
655 double timeSpan = 0.0; 659 double timeSpan = 0.0;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 sampleRate = 0.0; 704 sampleRate = 0.0;
701 stackDepth = 0; 705 stackDepth = 0;
702 timeSpan = 0.0; 706 timeSpan = 0.0;
703 codes.clear(); 707 codes.clear();
704 functions.clear(); 708 functions.clear();
705 tries.clear(); 709 tries.clear();
706 _builtCodeCalls = false; 710 _builtCodeCalls = false;
707 _builtFunctionCalls = false; 711 _builtFunctionCalls = false;
708 } 712 }
709 713
710 load(Isolate isolate, ServiceMap profile) { 714 Future load(Isolate isolate, ServiceMap profile) async {
711 clear(); 715 await loadProgress(isolate, profile).last;
712 if ((isolate == null) || (profile == null)) { 716 }
713 return;
714 }
715 717
716 this.isolate = isolate; 718 static Future sleep([Duration duration = const Duration(microseconds: 0)]) {
717 isolate.resetCachedProfileData(); 719 final Completer completer = new Completer();
720 new Timer(duration, () => completer.complete() );
721 return completer.future;
722 }
718 723
719 sampleCount = profile['sampleCount']; 724 Stream<double> loadProgress(Isolate isolate, ServiceMap profile) {
720 samplePeriod = profile['samplePeriod']; 725 var progress = new StreamController<double>.broadcast();
721 sampleRate = (MICROSECONDS_PER_SECOND / samplePeriod);
722 stackDepth = profile['stackDepth'];
723 timeSpan = profile['timeSpan'];
724 726
725 // Process code table. 727 (() async {
726 for (var codeRegion in profile['codes']) { 728 final Stopwatch watch = new Stopwatch();
727 Code code = codeRegion['code']; 729 watch.start();
728 assert(code != null); 730 int count = 0;
729 codes.add(new ProfileCode.fromMap(this, code, codeRegion)); 731 var needToUpdate = () {
730 } 732 count++;
733 if (count % 256 == 0 && watch.elapsedMilliseconds > 16) {
734 watch.reset();
735 return true;
736 }
737 return false;
738 };
739 var signal = (double p) {
740 progress.add(p);
741 return sleep();
742 };
743 try {
744 clear();
745 progress.add(0.0);
746 if ((isolate == null) || (profile == null)) {
747 return;
748 }
731 749
732 // Process function table. 750 this.isolate = isolate;
733 for (var profileFunction in profile['functions']) { 751 isolate.resetCachedProfileData();
734 ServiceFunction function = profileFunction['function'];
735 assert(function != null);
736 functions.add(
737 new ProfileFunction.fromMap(this, function, profileFunction));
738 }
739 752
740 tries['exclusiveCodeTrie'] = 753 sampleCount = profile['sampleCount'];
741 new Uint32List.fromList(profile['exclusiveCodeTrie']); 754 samplePeriod = profile['samplePeriod'];
742 tries['inclusiveCodeTrie'] = 755 sampleRate = (MICROSECONDS_PER_SECOND / samplePeriod);
743 new Uint32List.fromList(profile['inclusiveCodeTrie']); 756 stackDepth = profile['stackDepth'];
744 tries['exclusiveFunctionTrie'] = 757 timeSpan = profile['timeSpan'];
745 new Uint32List.fromList(profile['exclusiveFunctionTrie']); 758
746 tries['inclusiveFunctionTrie'] = 759 num length = profile['codes'].length +
747 new Uint32List.fromList(profile['inclusiveFunctionTrie']); 760 profile['functions'].length;
761
762 // Process code table.
763 for (var codeRegion in profile['codes']) {
764 if (needToUpdate()) { await signal(count * 100.0 / length); }
765 Code code = codeRegion['code'];
766 assert(code != null);
767 codes.add(new ProfileCode.fromMap(this, code, codeRegion));
768 }
769 // Process function table.
770 for (var profileFunction in profile['functions']) {
771 if (needToUpdate()) { await signal(count * 100 / length); }
772 ServiceFunction function = profileFunction['function'];
773 assert(function != null);
774 functions.add(
775 new ProfileFunction.fromMap(this, function, profileFunction));
776 }
777
778 tries['exclusiveCodeTrie'] =
779 new Uint32List.fromList(profile['exclusiveCodeTrie']);
780 tries['inclusiveCodeTrie'] =
781 new Uint32List.fromList(profile['inclusiveCodeTrie']);
782 tries['exclusiveFunctionTrie'] =
783 new Uint32List.fromList(profile['exclusiveFunctionTrie']);
784 tries['inclusiveFunctionTrie'] =
785 new Uint32List.fromList(profile['inclusiveFunctionTrie']);
786 } finally {
787 progress.close();
788 }
789 }());
790 return progress.stream;
748 } 791 }
749 792
750 // Data shared across calls to _read*TrieNode. 793 // Data shared across calls to _read*TrieNode.
751 int _dataCursor = 0; 794 int _dataCursor = 0;
752 795
753 // The code trie is serialized as a list of integers. Each node 796 // The code trie is serialized as a list of integers. Each node
754 // is recreated by consuming some portion of the list. The format is as 797 // is recreated by consuming some portion of the list. The format is as
755 // follows: 798 // follows:
756 // [0] index into codeTable of code object. 799 // [0] index into codeTable of code object.
757 // [1] tick count (number of times this stack frame occured). 800 // [1] tick count (number of times this stack frame occured).
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 if (node.children.length > 0) { 954 if (node.children.length > 0) {
912 nodeStack.add(node); 955 nodeStack.add(node);
913 childIndexStack.add(0); 956 childIndexStack.add(0);
914 } 957 }
915 } 958 }
916 959
917 return root; 960 return root;
918 } 961 }
919 962
920 int approximateMillisecondsForCount(count) { 963 int approximateMillisecondsForCount(count) {
921 var MICROSECONDS_PER_MILLISECOND = 1000.0;
922 return (count * samplePeriod) ~/ MICROSECONDS_PER_MILLISECOND; 964 return (count * samplePeriod) ~/ MICROSECONDS_PER_MILLISECOND;
923 } 965 }
924 966
925 double approximateSecondsForCount(count) { 967 double approximateSecondsForCount(count) {
926 var MICROSECONDS_PER_SECOND = 1000000.0;
927 return (count * samplePeriod) / MICROSECONDS_PER_SECOND; 968 return (count * samplePeriod) / MICROSECONDS_PER_SECOND;
928 } 969 }
929 } 970 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698