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

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, 9 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';
(...skipping 551 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(
592 makeText(totalPercent, toolTip: 'global % on stack'));
593 rowDiv.children.add(makeGap());
594 rowDiv.children.add(
595 makeText(selfPercent, toolTip: 'global % executing'));
596 rowDiv.children.add(makeGap());
597 rowDiv.children.add(makeIndenter(colored: false));
598 rowDiv.children.add(makeColorBar());
599 rowDiv.children.add(makeGap(ems: 1.0));
600 rowDiv.children.add(makeExpander());
601 rowDiv.children.add(
602 makeText(percent, toolTip: 'tree node %', flexBasis: null));
603 rowDiv.children.add(makeGap(ems: 0.5));
604 functionRef.ref = node.profileFunction.function;
605 rowDiv.children.add(functionRef);
606 }
607
608 var functionRef = new Element.tag('function-ref');
609
610 int get childCount => node.children.length;
611
612 void onShow() {
613 if (children.length > 0) {
614 return;
615 }
616 for (var childNode in node.children) {
617 var row = new FunctionCallTreeNodeRow(tree, depth + 1, profile, childNode) ;
618 children.add(row);
619 }
620 }
621 }
622
623
624 class CodeCallTreeNodeRow extends VirtualTreeRow {
625 final CpuProfile profile;
626 final CodeCallTreeNode node;
627 final String selfPercent;
628 final String totalPercent;
629 final String percent;
630
631 CodeCallTreeNodeRow(VirtualTree tree,
632 int depth,
633 this.profile,
634 CodeCallTreeNode node)
635 : node = node,
636 selfPercent = Utils.formatPercentNormalized(node.profileCode.normalizedE xclusiveTicks),
637 totalPercent = Utils.formatPercentNormalized(node.profileCode.normalized InclusiveTicks),
638 percent = Utils.formatPercentNormalized(node.percentage),
639 super(tree, depth) {
640 }
641
642 void onRender(DivElement rowDiv) {
643 rowDiv.children.add(
644 makeText(totalPercent, toolTip: 'global % on stack'));
645 rowDiv.children.add(makeGap());
646 rowDiv.children.add(
647 makeText(selfPercent, toolTip: 'global % executing'));
648 rowDiv.children.add(makeGap());
649 rowDiv.children.add(makeIndenter(colored: false));
650 rowDiv.children.add(makeColorBar());
651 rowDiv.children.add(makeGap(ems: 1.0));
652 rowDiv.children.add(makeExpander());
653 rowDiv.children.add(
654 makeText(percent, toolTip: 'tree node %', flexBasis: null));
655 rowDiv.children.add(makeGap(ems: 0.5));
656 codeRef.ref = node.profileCode.code;
657 rowDiv.children.add(codeRef);
658 }
659
660 var codeRef = new Element.tag('code-ref');
661
662 int get childCount => node.children.length;
663
664 void onShow() {
665 if (children.length > 0) {
666 return;
667 }
668 for (var childNode in node.children) {
669 var row = new CodeCallTreeNodeRow(tree, depth + 1, profile, childNode);
670 children.add(row);
671 }
672 }
673 }
674
572 /// Displays a CpuProfile 675 /// Displays a CpuProfile
573 @CustomTag('cpu-profile') 676 @CustomTag('cpu-profile')
574 class CpuProfileElement extends ObservatoryElement { 677 class CpuProfileElement extends ObservatoryElement {
575 CpuProfileElement.created() : super.created() { 678 CpuProfileElement.created() : super.created() {
576 _updateTask = new Task(update); 679 _updateTask = new Task(update);
577 _renderTask = new Task(render); 680 _renderTask = new Task(render);
578 } 681 }
579 682
580 attached() { 683 attached() {
581 super.attached(); 684 super.attached();
582 sampleBufferControlElement = 685 sampleBufferControlElement =
583 shadowRoot.querySelector('#sampleBufferControl'); 686 shadowRoot.querySelector('#sampleBufferControl');
584 assert(sampleBufferControlElement != null); 687 assert(sampleBufferControlElement != null);
585 sampleBufferControlElement.onSampleBufferUpdate = onSampleBufferChange; 688 sampleBufferControlElement.onSampleBufferUpdate = onSampleBufferChange;
586 stackTraceTreeConfigElement = 689 stackTraceTreeConfigElement =
587 shadowRoot.querySelector('#stackTraceTreeConfig'); 690 shadowRoot.querySelector('#stackTraceTreeConfig');
588 assert(stackTraceTreeConfigElement != null); 691 assert(stackTraceTreeConfigElement != null);
589 stackTraceTreeConfigElement.onTreeConfigChange = onTreeConfigChange; 692 stackTraceTreeConfigElement.onTreeConfigChange = onTreeConfigChange;
590 cpuProfileTreeElement = shadowRoot.querySelector('#cpuProfileTree'); 693 cpuProfileVirtualTreeElement = shadowRoot.querySelector('#cpuProfileVirtualT ree');
591 assert(cpuProfileTreeElement != null); 694 assert(cpuProfileVirtualTreeElement != null);
592 cpuProfileTreeElement.profile = sampleBufferControlElement.profile; 695 cpuProfileVirtualTreeElement.profile = sampleBufferControlElement.profile;
696 _resizeSubscription = window.onResize.listen((_) => _updateSize());
593 _updateTask.queue(); 697 _updateTask.queue();
698 _updateSize();
699 }
700
701 detached() {
702 super.detached();
703 if (_resizeSubscription != null) {
704 _resizeSubscription.cancel();
705 }
706 }
707
708 _updateSize() {
709 var applySize = (e) {
710 Rectangle rect = e.getBoundingClientRect();
711 final totalHeight = window.innerHeight;
712 final top = rect.top;
713 final bottomMargin = 200;
714 final mainHeight = totalHeight - top - bottomMargin;
715 e.style.setProperty('height', '${mainHeight}px');
716 };
717 HtmlElement e2 = $['cpuProfileVirtualTree'];
718 applySize(e2);
594 } 719 }
595 720
596 isolateChanged(oldValue) { 721 isolateChanged(oldValue) {
597 _updateTask.queue(); 722 _updateTask.queue();
598 } 723 }
599 724
600 update() { 725 update() {
601 if (sampleBufferControlElement != null) { 726 if (sampleBufferControlElement != null) {
602 sampleBufferControlElement.reload(isolate); 727 sampleBufferControlElement.reload(isolate);
603 } 728 }
604 } 729 }
605 730
606 onSampleBufferChange(CpuProfile sampleBuffer) { 731 onSampleBufferChange(CpuProfile sampleBuffer) {
607 _renderTask.queue(); 732 _renderTask.queue();
608 } 733 }
609 734
610 onTreeConfigChange(String modeSelector, String directionSelector) { 735 onTreeConfigChange(String modeSelector, String directionSelector) {
611 ProfileTreeDirection direction = ProfileTreeDirection.Exclusive; 736 ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
612 if (directionSelector != 'Up') { 737 if (directionSelector != 'Up') {
613 direction = ProfileTreeDirection.Inclusive; 738 direction = ProfileTreeDirection.Inclusive;
614 } 739 }
615 ProfileTreeMode mode = ProfileTreeMode.Function; 740 ProfileTreeMode mode = ProfileTreeMode.Function;
616 if (modeSelector == 'Code') { 741 if (modeSelector == 'Code') {
617 mode = ProfileTreeMode.Code; 742 mode = ProfileTreeMode.Code;
618 } 743 }
619 cpuProfileTreeElement.direction = direction; 744 cpuProfileVirtualTreeElement.direction = direction;
620 cpuProfileTreeElement.mode = mode; 745 cpuProfileVirtualTreeElement.mode = mode;
621 _renderTask.queue(); 746 _renderTask.queue();
622 } 747 }
623 748
624 Future clearCpuProfile() async { 749 Future clearCpuProfile() async {
625 await isolate.invokeRpc('_clearCpuProfile', { }); 750 await isolate.invokeRpc('_clearCpuProfile', { });
626 _updateTask.queue(); 751 _updateTask.queue();
627 return new Future.value(null); 752 return new Future.value(null);
628 } 753 }
629 754
630 Future refresh() { 755 Future refresh() {
631 _updateTask.queue(); 756 _updateTask.queue();
632 return new Future.value(null); 757 return new Future.value(null);
633 } 758 }
634 759
635 render() { 760 render() {
636 cpuProfileTreeElement.render(); 761 cpuProfileVirtualTreeElement.render();
637 } 762 }
638 763
639 @published Isolate isolate; 764 @published Isolate isolate;
640 765
766 StreamSubscription _resizeSubscription;
641 Task _updateTask; 767 Task _updateTask;
642 Task _renderTask; 768 Task _renderTask;
643 SampleBufferControlElement sampleBufferControlElement; 769 SampleBufferControlElement sampleBufferControlElement;
644 StackTraceTreeConfigElement stackTraceTreeConfigElement; 770 StackTraceTreeConfigElement stackTraceTreeConfigElement;
645 CpuProfileTreeElement cpuProfileTreeElement; 771 CpuProfileVirtualTreeElement cpuProfileVirtualTreeElement;
646 } 772 }
647 773
648 class NameSortedTable extends SortedTable { 774 class NameSortedTable extends SortedTable {
649 NameSortedTable(columns) : super(columns); 775 NameSortedTable(columns) : super(columns);
650 @override 776 @override
651 dynamic getSortKeyFor(int row, int col) { 777 dynamic getSortKeyFor(int row, int col) {
652 if (col == FUNCTION_COLUMN) { 778 if (col == FUNCTION_COLUMN) {
653 // Use name as sort key. 779 // Use name as sort key.
654 return rows[row].values[col].name; 780 return rows[row].values[col].name;
655 } 781 }
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
1133 enum ProfileTreeDirection { 1259 enum ProfileTreeDirection {
1134 Exclusive, 1260 Exclusive,
1135 Inclusive 1261 Inclusive
1136 } 1262 }
1137 1263
1138 enum ProfileTreeMode { 1264 enum ProfileTreeMode {
1139 Code, 1265 Code,
1140 Function, 1266 Function,
1141 } 1267 }
1142 1268
1269 @CustomTag('cpu-profile-virtual-tree')
1270 class CpuProfileVirtualTreeElement extends ObservatoryElement {
1271 ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
1272 ProfileTreeMode mode = ProfileTreeMode.Function;
1273 CpuProfile profile;
1274 VirtualTree virtualTree;
1275 FunctionCallTreeNodeFilter functionFilter;
1276 @observable bool show = true;
1277
1278 CpuProfileVirtualTreeElement.created() : super.created();
1279
1280 void render() {
1281 _updateView();
1282 }
1283
1284 showChanged(oldValue) {
1285 var treeTable = shadowRoot.querySelector('#treeTable');
1286 assert(treeTable != null);
1287 treeTable.style.display = show ? 'table' : 'none';
1288 }
1289
1290 void _updateView() {
1291 virtualTree?.clear();
1292 virtualTree?.uninstall();
1293 virtualTree = null;
1294 bool exclusive = direction == ProfileTreeDirection.Exclusive;
1295 if (mode == ProfileTreeMode.Code) {
1296 _buildCodeTree(exclusive);
1297 } else {
1298 assert(mode == ProfileTreeMode.Function);
1299 _buildFunctionTree(exclusive);
1300 }
1301 virtualTree?.refresh();
1302 }
1303
1304 void _buildFunctionTree(bool exclusive) {
1305 var treeBody = shadowRoot.querySelector('#tree');
1306 assert(treeBody != null);
1307 virtualTree = new VirtualTree(32, treeBody);
1308 if (profile == null) {
1309 return;
1310 }
1311 var tree = profile.loadFunctionTree(exclusive ? 'exclusive' : 'inclusive');
1312 if (tree == null) {
1313 return;
1314 }
1315 if (functionFilter != null) {
1316 tree = tree.filtered(functionFilter);
1317 }
1318 for (var child in tree.root.children) {
1319 virtualTree.rows.add(
1320 new FunctionCallTreeNodeRow(virtualTree, 0, profile, child));
1321 }
1322 if (virtualTree.rows.length == 1) {
1323 virtualTree.rows[0].expanded = true;
1324 }
1325 }
1326
1327 void _buildCodeTree(bool exclusive) {
1328 var treeBody = shadowRoot.querySelector('#tree');
1329 assert(treeBody != null);
1330 virtualTree = new VirtualTree(32, treeBody);
1331 if (profile == null) {
1332 return;
1333 }
1334 var tree = profile.loadCodeTree(exclusive ? 'exclusive' : 'inclusive');
1335 if (tree == null) {
1336 return;
1337 }
1338 for (var child in tree.root.children) {
1339 virtualTree.rows.add(
1340 new CodeCallTreeNodeRow(virtualTree, 0, profile, child));
1341 }
1342 if (virtualTree.rows.length == 1) {
1343 virtualTree.rows[0].expanded = true;
1344 }
1345 }
1346 }
1347
1143 @CustomTag('cpu-profile-tree') 1348 @CustomTag('cpu-profile-tree')
1144 class CpuProfileTreeElement extends ObservatoryElement { 1349 class CpuProfileTreeElement extends ObservatoryElement {
1145 ProfileTreeDirection direction = ProfileTreeDirection.Exclusive; 1350 ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
1146 ProfileTreeMode mode = ProfileTreeMode.Function; 1351 ProfileTreeMode mode = ProfileTreeMode.Function;
1147 CpuProfile profile; 1352 CpuProfile profile;
1148 TableTree codeTree; 1353 TableTree codeTree;
1149 TableTree functionTree; 1354 TableTree functionTree;
1150 FunctionCallTreeNodeFilter functionFilter; 1355 FunctionCallTreeNodeFilter functionFilter;
1151 @observable bool show = true; 1356 @observable bool show = true;
1152 1357
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1211 return; 1416 return;
1212 } 1417 }
1213 var tree = profile.loadCodeTree(exclusive ? 'exclusive' : 'inclusive'); 1418 var tree = profile.loadCodeTree(exclusive ? 'exclusive' : 'inclusive');
1214 if (tree == null) { 1419 if (tree == null) {
1215 return; 1420 return;
1216 } 1421 }
1217 var rootRow = new CodeProfileTreeRow(codeTree, null, profile, tree.root); 1422 var rootRow = new CodeProfileTreeRow(codeTree, null, profile, tree.root);
1218 codeTree.initialize(rootRow); 1423 codeTree.initialize(rootRow);
1219 } 1424 }
1220 } 1425 }
OLDNEW
« no previous file with comments | « runtime/observatory/lib/src/app/view_model.dart ('k') | runtime/observatory/lib/src/elements/cpu_profile.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698