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

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

Issue 1833453004: Dramatically increase the performance of Observatory's profile UI (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 library cpu_profile_element; 5 library cpu_profile_element;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:html'; 8 import 'dart:html';
9 import 'observatory_element.dart'; 9 import 'observatory_element.dart';
10 import 'package:observatory/service.dart'; 10 import 'package:observatory/service.dart';
11 import 'package:observatory/app.dart'; 11 import 'package:observatory/app.dart';
12 import 'package:observatory/cpu_profile.dart'; 12 import 'package:observatory/cpu_profile.dart';
13 import 'package:observatory/elements.dart'; 13 import 'package:observatory/elements.dart';
14 import 'package:polymer/polymer.dart'; 14 import 'package:polymer/polymer.dart';
15 15
16 List<String> sorted(Set<String> attributes) { 16 List<String> sorted(Set<String> attributes) {
17 var list = attributes.toList(); 17 var list = attributes.toList();
18 list.sort(); 18 list.sort();
19 return list; 19 return list;
20 } 20 }
21 21
22 abstract class ProfileTreeRow<T> extends TableTreeRow { 22 abstract class ProfileTreeRow<T> extends TableTreeRow {
rmacnak 2016/03/24 23:20:36 I assume you're just keeping the old ones for refe
Cutch 2016/03/25 03:04:08 Acknowledged.
23 final CpuProfile profile; 23 final CpuProfile profile;
24 final T node; 24 final T node;
25 final String selfPercent; 25 final String selfPercent;
26 final String percent; 26 final String percent;
27 bool _infoBoxShown = false; 27 bool _infoBoxShown = false;
28 HtmlElement infoBox; 28 HtmlElement infoBox;
29 HtmlElement infoButton; 29 HtmlElement infoButton;
30 30
31 ProfileTreeRow(TableTree tree, TableTreeRow parent, 31 ProfileTreeRow(TableTree tree, TableTreeRow parent,
32 this.profile, this.node, double selfPercent, double percent) 32 this.profile, this.node, double selfPercent, double percent)
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 } 562 }
563 563
564 Function onTreeConfigChange; 564 Function onTreeConfigChange;
565 @observable bool show = true; 565 @observable bool show = true;
566 @observable bool showModeSelector = true; 566 @observable bool showModeSelector = true;
567 @observable bool showDirectionSelector = true; 567 @observable bool showDirectionSelector = true;
568 @observable String modeSelector = 'Function'; 568 @observable String modeSelector = 'Function';
569 @observable String directionSelector = 'Up'; 569 @observable String directionSelector = 'Up';
570 } 570 }
571 571
572 class FunctionCallTreeNodeRow extends VirtualTreeRow {
573 final CpuProfile profile;
574 final FunctionCallTreeNode node;
575 final String selfPercent;
576 final String totalPercent;
577 final String percent;
578
579 FunctionCallTreeNodeRow(VirtualTree tree,
580 int depth,
581 this.profile,
582 FunctionCallTreeNode node)
583 : node = node,
584 selfPercent = Utils.formatPercentNormalized(node.profileFunction.normali zedExclusiveTicks),
585 totalPercent = Utils.formatPercentNormalized(node.profileFunction.normal izedInclusiveTicks),
586 percent = Utils.formatPercentNormalized(node.percentage),
587 super(tree, depth) {
588 }
589
590 void onRender(DivElement rowDiv) {
591 rowDiv.children.add(makeIndenter());
592 rowDiv.children.add(makeColorBar());
593 rowDiv.children.add(makeExpander());
594 rowDiv.children.add(
595 makeText(percent, toolTip: 'tree node %'));
596 rowDiv.children.add(makeGap());
597 rowDiv.children.add(
598 makeText(selfPercent, toolTip: 'global % executing'));
599 rowDiv.children.add(makeGap());
600 rowDiv.children.add(
601 makeText(totalPercent, toolTip: 'global % on stack'));
602 rowDiv.children.add(makeGap());
603 var functionRef = new Element.tag('function-ref');
604 functionRef.ref = node.profileFunction.function;
605 rowDiv.children.add(functionRef);
606 }
607
608 bool hasChildren() => node.children.length > 0;
609
610 void onShow() {
611 if (children.length > 0) {
612 return;
613 }
614 for (var childNode in node.children) {
615 var row = new FunctionCallTreeNodeRow(tree, depth + 1, profile, childNode) ;
616 children.add(row);
617 }
618 }
619 }
620
621
622 class CodeCallTreeNodeRow extends VirtualTreeRow {
623 final CpuProfile profile;
624 final CodeCallTreeNode node;
625 final String selfPercent;
626 final String totalPercent;
627 final String percent;
628
629 CodeCallTreeNodeRow(VirtualTree tree,
630 int depth,
631 this.profile,
632 CodeCallTreeNode node)
633 : node = node,
634 selfPercent = Utils.formatPercentNormalized(node.profileCode.normalizedE xclusiveTicks),
635 totalPercent = Utils.formatPercentNormalized(node.profileCode.normalized InclusiveTicks),
636 percent = Utils.formatPercentNormalized(node.percentage),
637 super(tree, depth) {
638 }
639
640 void onRender(DivElement rowDiv) {
641 rowDiv.children.add(makeIndenter());
642 rowDiv.children.add(makeColorBar());
643 rowDiv.children.add(makeExpander());
644 rowDiv.children.add(
645 makeText(percent, toolTip: 'tree node %'));
646 rowDiv.children.add(makeGap());
647 rowDiv.children.add(
648 makeText(selfPercent, toolTip: 'global % executing'));
649 rowDiv.children.add(makeGap());
650 rowDiv.children.add(
651 makeText(totalPercent, toolTip: 'global % on stack'));
652 rowDiv.children.add(makeGap());
653 var codeRef = new Element.tag('code-ref');
654 codeRef.ref = node.profileCode.code;
655 rowDiv.children.add(codeRef);
656 }
657
658 bool hasChildren() => node.children.length > 0;
659
660 void onShow() {
661 if (children.length > 0) {
662 return;
663 }
664 for (var childNode in node.children) {
665 var row = new CodeCallTreeNodeRow(tree, depth + 1, profile, childNode);
666 children.add(row);
667 }
668 }
669 }
670
572 /// Displays a CpuProfile 671 /// Displays a CpuProfile
573 @CustomTag('cpu-profile') 672 @CustomTag('cpu-profile')
574 class CpuProfileElement extends ObservatoryElement { 673 class CpuProfileElement extends ObservatoryElement {
575 CpuProfileElement.created() : super.created() { 674 CpuProfileElement.created() : super.created() {
576 _updateTask = new Task(update); 675 _updateTask = new Task(update);
577 _renderTask = new Task(render); 676 _renderTask = new Task(render);
578 } 677 }
579 678
580 attached() { 679 attached() {
581 super.attached(); 680 super.attached();
582 sampleBufferControlElement = 681 sampleBufferControlElement =
583 shadowRoot.querySelector('#sampleBufferControl'); 682 shadowRoot.querySelector('#sampleBufferControl');
584 assert(sampleBufferControlElement != null); 683 assert(sampleBufferControlElement != null);
585 sampleBufferControlElement.onSampleBufferUpdate = onSampleBufferChange; 684 sampleBufferControlElement.onSampleBufferUpdate = onSampleBufferChange;
586 stackTraceTreeConfigElement = 685 stackTraceTreeConfigElement =
587 shadowRoot.querySelector('#stackTraceTreeConfig'); 686 shadowRoot.querySelector('#stackTraceTreeConfig');
588 assert(stackTraceTreeConfigElement != null); 687 assert(stackTraceTreeConfigElement != null);
589 stackTraceTreeConfigElement.onTreeConfigChange = onTreeConfigChange; 688 stackTraceTreeConfigElement.onTreeConfigChange = onTreeConfigChange;
590 cpuProfileTreeElement = shadowRoot.querySelector('#cpuProfileTree'); 689 cpuProfileVirtualTreeElement = shadowRoot.querySelector('#cpuProfileVirtualT ree');
591 assert(cpuProfileTreeElement != null); 690 assert(cpuProfileVirtualTreeElement != null);
592 cpuProfileTreeElement.profile = sampleBufferControlElement.profile; 691 cpuProfileVirtualTreeElement.profile = sampleBufferControlElement.profile;
593 _updateTask.queue(); 692 _updateTask.queue();
594 } 693 }
595 694
596 isolateChanged(oldValue) { 695 isolateChanged(oldValue) {
597 _updateTask.queue(); 696 _updateTask.queue();
598 } 697 }
599 698
600 update() { 699 update() {
601 if (sampleBufferControlElement != null) { 700 if (sampleBufferControlElement != null) {
602 sampleBufferControlElement.reload(isolate); 701 sampleBufferControlElement.reload(isolate);
603 } 702 }
604 } 703 }
605 704
606 onSampleBufferChange(CpuProfile sampleBuffer) { 705 onSampleBufferChange(CpuProfile sampleBuffer) {
607 _renderTask.queue(); 706 _renderTask.queue();
608 } 707 }
609 708
610 onTreeConfigChange(String modeSelector, String directionSelector) { 709 onTreeConfigChange(String modeSelector, String directionSelector) {
611 ProfileTreeDirection direction = ProfileTreeDirection.Exclusive; 710 ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
612 if (directionSelector != 'Up') { 711 if (directionSelector != 'Up') {
613 direction = ProfileTreeDirection.Inclusive; 712 direction = ProfileTreeDirection.Inclusive;
614 } 713 }
615 ProfileTreeMode mode = ProfileTreeMode.Function; 714 ProfileTreeMode mode = ProfileTreeMode.Function;
616 if (modeSelector == 'Code') { 715 if (modeSelector == 'Code') {
617 mode = ProfileTreeMode.Code; 716 mode = ProfileTreeMode.Code;
618 } 717 }
619 cpuProfileTreeElement.direction = direction; 718 cpuProfileVirtualTreeElement.direction = direction;
620 cpuProfileTreeElement.mode = mode; 719 cpuProfileVirtualTreeElement.mode = mode;
621 _renderTask.queue(); 720 _renderTask.queue();
622 } 721 }
623 722
624 Future clearCpuProfile() async { 723 Future clearCpuProfile() async {
625 await isolate.invokeRpc('_clearCpuProfile', { }); 724 await isolate.invokeRpc('_clearCpuProfile', { });
626 _updateTask.queue(); 725 _updateTask.queue();
627 return new Future.value(null); 726 return new Future.value(null);
628 } 727 }
629 728
630 Future refresh() { 729 Future refresh() {
631 _updateTask.queue(); 730 _updateTask.queue();
632 return new Future.value(null); 731 return new Future.value(null);
633 } 732 }
634 733
635 render() { 734 render() {
636 cpuProfileTreeElement.render(); 735 cpuProfileVirtualTreeElement.render();
637 } 736 }
638 737
639 @published Isolate isolate; 738 @published Isolate isolate;
640 739
641 Task _updateTask; 740 Task _updateTask;
642 Task _renderTask; 741 Task _renderTask;
643 SampleBufferControlElement sampleBufferControlElement; 742 SampleBufferControlElement sampleBufferControlElement;
644 StackTraceTreeConfigElement stackTraceTreeConfigElement; 743 StackTraceTreeConfigElement stackTraceTreeConfigElement;
645 CpuProfileTreeElement cpuProfileTreeElement; 744 CpuProfileVirtualTreeElement cpuProfileVirtualTreeElement;
646 } 745 }
647 746
648 class NameSortedTable extends SortedTable { 747 class NameSortedTable extends SortedTable {
649 NameSortedTable(columns) : super(columns); 748 NameSortedTable(columns) : super(columns);
650 @override 749 @override
651 dynamic getSortKeyFor(int row, int col) { 750 dynamic getSortKeyFor(int row, int col) {
652 if (col == FUNCTION_COLUMN) { 751 if (col == FUNCTION_COLUMN) {
653 // Use name as sort key. 752 // Use name as sort key.
654 return rows[row].values[col].name; 753 return rows[row].values[col].name;
655 } 754 }
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
1133 enum ProfileTreeDirection { 1232 enum ProfileTreeDirection {
1134 Exclusive, 1233 Exclusive,
1135 Inclusive 1234 Inclusive
1136 } 1235 }
1137 1236
1138 enum ProfileTreeMode { 1237 enum ProfileTreeMode {
1139 Code, 1238 Code,
1140 Function, 1239 Function,
1141 } 1240 }
1142 1241
1242 @CustomTag('cpu-profile-virtual-tree')
1243 class CpuProfileVirtualTreeElement extends ObservatoryElement {
1244 ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
1245 ProfileTreeMode mode = ProfileTreeMode.Function;
1246 CpuProfile profile;
1247 VirtualTree virtualTree;
1248 FunctionCallTreeNodeFilter functionFilter;
1249 @observable bool show = true;
1250
1251 CpuProfileVirtualTreeElement.created() : super.created();
1252
1253 void render() {
1254 _updateView();
1255 }
1256
1257 showChanged(oldValue) {
1258 var treeTable = shadowRoot.querySelector('#treeTable');
1259 assert(treeTable != null);
1260 treeTable.style.display = show ? 'table' : 'none';
1261 }
1262
1263 void _updateView() {
1264 virtualTree?.clear();
1265 virtualTree?.uninstall();
1266 virtualTree = null;
1267 bool exclusive = direction == ProfileTreeDirection.Exclusive;
1268 if (mode == ProfileTreeMode.Code) {
1269 _buildCodeTree(exclusive);
1270 } else {
1271 assert(mode == ProfileTreeMode.Function);
1272 _buildFunctionTree(exclusive);
1273 }
1274 virtualTree?.refresh();
1275 }
1276
1277 void _buildFunctionTree(bool exclusive) {
1278 var treeBody = shadowRoot.querySelector('#tree');
1279 assert(treeBody != null);
1280 virtualTree = new VirtualTree(32, treeBody);
1281 if (profile == null) {
1282 return;
1283 }
1284 var tree = profile.loadFunctionTree(exclusive ? 'exclusive' : 'inclusive');
1285 if (tree == null) {
1286 return;
1287 }
1288 if (functionFilter != null) {
1289 tree = tree.filtered(functionFilter);
1290 }
1291 for (var child in tree.root.children) {
1292 virtualTree.rows.add(
1293 new FunctionCallTreeNodeRow(virtualTree, 0, profile, child));
1294 }
1295 }
1296
1297 void _buildCodeTree(bool exclusive) {
1298 var treeBody = shadowRoot.querySelector('#tree');
1299 assert(treeBody != null);
1300 virtualTree = new VirtualTree(32, treeBody);
1301 if (profile == null) {
1302 return;
1303 }
1304 var tree = profile.loadCodeTree(exclusive ? 'exclusive' : 'inclusive');
1305 if (tree == null) {
1306 return;
1307 }
1308 for (var child in tree.root.children) {
1309 virtualTree.rows.add(
1310 new CodeCallTreeNodeRow(virtualTree, 0, profile, child));
1311 }
1312 }
1313 }
1314
1143 @CustomTag('cpu-profile-tree') 1315 @CustomTag('cpu-profile-tree')
1144 class CpuProfileTreeElement extends ObservatoryElement { 1316 class CpuProfileTreeElement extends ObservatoryElement {
1145 ProfileTreeDirection direction = ProfileTreeDirection.Exclusive; 1317 ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
1146 ProfileTreeMode mode = ProfileTreeMode.Function; 1318 ProfileTreeMode mode = ProfileTreeMode.Function;
1147 CpuProfile profile; 1319 CpuProfile profile;
1148 TableTree codeTree; 1320 TableTree codeTree;
1149 TableTree functionTree; 1321 TableTree functionTree;
1150 FunctionCallTreeNodeFilter functionFilter; 1322 FunctionCallTreeNodeFilter functionFilter;
1151 @observable bool show = true; 1323 @observable bool show = true;
1152 1324
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1211 return; 1383 return;
1212 } 1384 }
1213 var tree = profile.loadCodeTree(exclusive ? 'exclusive' : 'inclusive'); 1385 var tree = profile.loadCodeTree(exclusive ? 'exclusive' : 'inclusive');
1214 if (tree == null) { 1386 if (tree == null) {
1215 return; 1387 return;
1216 } 1388 }
1217 var rootRow = new CodeProfileTreeRow(codeTree, null, profile, tree.root); 1389 var rootRow = new CodeProfileTreeRow(codeTree, null, profile, tree.root);
1218 codeTree.initialize(rootRow); 1390 codeTree.initialize(rootRow);
1219 } 1391 }
1220 } 1392 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698