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

Unified Diff: runtime/observatory/lib/src/elements/cpu_profile.dart

Issue 965593002: Improved profiler view and inclusive profile tree (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 10 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 side-by-side diff with in-line comments
Download patch
Index: runtime/observatory/lib/src/elements/cpu_profile.dart
diff --git a/runtime/observatory/lib/src/elements/cpu_profile.dart b/runtime/observatory/lib/src/elements/cpu_profile.dart
index d82b1f784849d9558bd629823a32c47e552efb99..892c1ce044f0c3280c0f8749def688c8b2af2223 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile.dart
+++ b/runtime/observatory/lib/src/elements/cpu_profile.dart
@@ -14,68 +14,36 @@ import 'package:observatory/cpu_profile.dart';
import 'package:observatory/elements.dart';
import 'package:polymer/polymer.dart';
-class ProfileCodeTrieNodeTreeRow extends TableTreeRow {
- final CpuProfile profile;
- @reflectable final CodeTrieNode root;
- @reflectable final CodeTrieNode node;
- @reflectable Code get code => node.profileCode.code;
-
- @reflectable String tipKind = '';
- @reflectable String tipParent = '';
- @reflectable String tipExclusive = '';
- @reflectable String tipTicks = '';
- @reflectable String tipTime = '';
-
- ProfileCodeTrieNodeTreeRow(this.profile, this.root, this.node,
- TableTree tree,
- ProfileCodeTrieNodeTreeRow parent)
- : super(tree, parent) {
- assert(root != null);
- assert(node != null);
- tipTicks = '${node.count}';
- var seconds = profile.approximateSecondsForCount(node.count);
- tipTime = Utils.formatTimePrecise(seconds);
- if (code.kind == CodeKind.Tag) {
- tipKind = 'Tag (category)';
- if (parent == null) {
- tipParent = Utils.formatPercent(node.count, root.count);
- } else {
- tipParent = Utils.formatPercent(node.count, parent.node.count);
- }
- tipExclusive = Utils.formatPercent(node.count, root.count);
- } else {
- if ((code.kind == CodeKind.Collected) ||
- (code.kind == CodeKind.Reused)) {
- tipKind = 'Garbage Collected Code';
- } else {
- tipKind = '${code.kind} (Function)';
- }
- if (parent == null) {
- tipParent = Utils.formatPercent(node.count, root.count);
- } else {
- tipParent = Utils.formatPercent(node.count, parent.node.count);
- }
- tipExclusive =
- Utils.formatPercent(node.profileCode.exclusiveTicks, root.count);
- }
- }
-
- bool shouldDisplayChild(CodeTrieNode childNode, double threshold) {
- return ((childNode.count / node.count) > threshold) ||
- ((childNode.profileCode.exclusiveTicks / root.count) > threshold);
- }
+List<String> sorted(Set<String> attributes) {
+ var list = attributes.toList();
+ list.sort();
+ return list;
+}
- void _buildTooltip(DivElement memberList, Map<String, String> items) {
+abstract class ProfileTreeRow<T> extends TableTreeRow {
+ final CpuProfile profile;
+ final T node;
+ final String selfPercent;
+ final String percent;
+ bool _infoBoxShown = false;
+ HtmlElement infoBox;
+ HtmlElement infoButton;
+
+ ProfileTreeRow(TableTree tree, TableTreeRow parent,
+ this.profile, this.node, double selfPercent, double percent)
+ : super(tree, parent),
+ selfPercent = Utils.formatPercentNormalized(selfPercent),
+ percent = Utils.formatPercentNormalized(percent);
+
+ static _addToMemberList(DivElement memberList, Map<String, String> items) {
items.forEach((k, v) {
var item = new DivElement();
item.classes.add('memberItem');
var name = new DivElement();
name.classes.add('memberName');
- name.classes.add('white');
name.text = k;
var value = new DivElement();
value.classes.add('memberValue');
- value.classes.add('white');
value.text = v;
item.children.add(name);
item.children.add(value);
@@ -83,209 +51,385 @@ class ProfileCodeTrieNodeTreeRow extends TableTreeRow {
});
}
+ makeInfoBox() {
+ if (infoBox != null) {
+ return;
+ }
+ infoBox = new DivElement();
+ infoBox.classes.add('infoBox');
+ infoBox.classes.add('shadow');
+ infoBox.style.display = 'none';
+ infoBox.onClick.listen((e) => e.stopPropagation());
+ }
+
+ makeInfoButton() {
+ infoButton = new SpanElement();
+ infoButton.style.marginLeft = 'auto';
+ infoButton.style.marginRight = '1em';
+ infoButton.children.add(new Element.tag('icon-info-outline'));
+ infoButton.onClick.listen((event) {
+ event.stopPropagation();
+ toggleInfoBox();
+ });
+ }
+
+ static const attributes = const {
+ 'optimized' : const ['O', null, 'Optimized'],
+ 'unoptimized' : const ['U', null, 'Unoptimized'],
+ 'inlined' : const ['I', null, 'Inlined'],
+ 'dart' : const ['D', null, 'Dart'],
+ 'tag' : const ['T', null, 'Tag'],
+ 'native' : const ['N', null, 'Native'],
+ 'stub': const ['S', null, 'Stub'],
+ 'synthetic' : const ['?', null, 'Synthetic'],
+ };
+
+ HtmlElement newAttributeBox(String attribute) {
+ List attributeDetails = attributes[attribute];
+ if (attributeDetails == null) {
+ print('could not find attribute $attribute');
+ return null;
+ }
+ var element = new SpanElement();
+ element.style.border = 'solid 2px #ECECEC';
+ element.style.height = '100%';
+ element.style.display = 'inline-block';
+ element.style.textAlign = 'center';
+ element.style.minWidth = '1.5em';
+ element.style.fontWeight = 'bold';
+ if (attributeDetails[1] != null) {
+ element.style.backgroundColor = attributeDetails[1];
+ }
+ element.text = attributeDetails[0];
+ element.title = attributeDetails[2];
+ return element;
+ }
+
+ onHide() {
+ super.onHide();
+ infoBox = null;
+ infoButton = null;
+ }
+
+ showInfoBox() {
+ if ((infoButton == null) || (infoBox == null)) {
+ return;
+ }
+ _infoBoxShown = true;
+ infoBox.style.display = 'block';
+ infoButton.children.clear();
+ infoButton.children.add(new Element.tag('icon-info'));
+ }
+
+ hideInfoBox() {
+ _infoBoxShown = false;
+ if ((infoButton == null) || (infoBox == null)) {
+ return;
+ }
+ infoBox.style.display = 'none';
+ infoButton.children.clear();
+ infoButton.children.add(new Element.tag('icon-info-outline'));
+ }
+
+ toggleInfoBox() {
+ if (_infoBoxShown) {
+ hideInfoBox();
+ } else {
+ showInfoBox();
+ }
+ }
+
+ hideAllInfoBoxes() {
+ final List<ProfileTreeRow> rows = tree.rows;
+ for (var row in rows) {
+ row.hideInfoBox();
+ }
+ }
+
+ onClick(MouseEvent e) {
+ e.stopPropagation();
+ if (e.altKey) {
+ bool show = !_infoBoxShown;
+ hideAllInfoBoxes();
+ if (show) {
+ showInfoBox();
+ }
+ return;
+ }
+ super.onClick(e);
+ }
+
+ HtmlElement newCodeRef(ProfileCode code) {
+ var codeRef = new Element.tag('code-ref');
+ codeRef.ref = code.code;
+ return codeRef;
+ }
+
+ HtmlElement newFunctionRef(ProfileFunction function) {
+ var ref = new Element.tag('function-ref');
+ ref.ref = function.function;
+ return ref;
+ }
+
+ HtmlElement hr() {
+ var element = new HRElement();
+ return element;
+ }
+
+ HtmlElement div(String text) {
+ var element = new DivElement();
+ element.text = text;
+ return element;
+ }
+
+ HtmlElement br() {
+ return new BRElement();
+ }
+
+ HtmlElement span(String text) {
+ var element = new SpanElement();
+ element.style.minWidth = '1em';
+ element.text = text;
+ return element;
+ }
+}
+
+class CodeProfileTreeRow extends ProfileTreeRow<CodeCallTreeNode> {
+ CodeProfileTreeRow(TableTree tree, CodeProfileTreeRow parent,
+ CpuProfile profile, CodeCallTreeNode node)
+ : super(tree, parent, profile, node,
+ node.profileCode.normalizedExclusiveTicks,
+ node.percentage) {
+ // fill out attributes.
+ }
+
+ bool hasChildren() => node.children.length > 0;
+
void onShow() {
super.onShow();
+
if (children.length == 0) {
- var threshold = profile.displayThreshold;
for (var childNode in node.children) {
- if (!shouldDisplayChild(childNode, threshold)) {
- continue;
- }
- var row =
- new ProfileCodeTrieNodeTreeRow(profile, root, childNode, tree, this);
+ var row = new CodeProfileTreeRow(tree, this, profile, childNode);
children.add(row);
}
}
- var methodCell = tableColumns[0];
- // Enable expansion by clicking anywhere on the method column.
- methodCell.onClick.listen(onClick);
+ // Fill in method column.
+ var methodColumn = flexColumns[0];
+ methodColumn.style.justifyContent = 'flex-start';
+ methodColumn.style.position = 'relative';
- // Grab the flex-row Div inside the methodCell.
- methodCell = methodCell.children[0];
-
- // Insert the parent percentage
- var parentPercent = new DivElement();
- parentPercent.text = tipParent;
- methodCell.children.add(parentPercent);
+ // Percent.
+ var percentNode = new DivElement();
+ percentNode.text = percent;
+ percentNode.style.minWidth = '5em';
+ percentNode.style.textAlign = 'right';
+ percentNode.title = 'Self: $selfPercent';
+ methodColumn.children.add(percentNode);
+ // Gap.
var gap = new SpanElement();
gap.style.minWidth = '1em';
- methodCell.children.add(gap);
+ methodColumn.children.add(gap);
- var codeRef = new Element.tag('code-ref');
- codeRef.ref = code;
- methodCell.children.add(codeRef);
-
- var selfCell = tableColumns[1];
- selfCell.style.position = 'relative';
- selfCell.text = tipExclusive;
-
- var tooltipDiv = new DivElement();
- tooltipDiv.classes.add('tooltip');
-
- var memberListDiv = new DivElement();
- memberListDiv.classes.add('memberList');
- tooltipDiv.children.add(memberListDiv);
- _buildTooltip(memberListDiv, {
- 'Kind' : tipKind,
- 'Percent of Parent' : tipParent,
- 'Sample Count' : tipTicks,
- 'Approximate Execution Time': tipTime,
- });
- selfCell.children.add(tooltipDiv);
- }
+ // Code link.
+ var codeRef = newCodeRef(node.profileCode);
+ codeRef.style.alignSelf = 'center';
+ methodColumn.children.add(codeRef);
- bool hasChildren() {
- return node.children.length > 0;
- }
-}
+ gap = new SpanElement();
+ gap.style.minWidth = '1em';
+ methodColumn.children.add(gap);
-class ProfileFunctionTrieNodeTreeRow extends TableTreeRow {
- final CpuProfile profile;
- @reflectable final FunctionTrieNode root;
- @reflectable final FunctionTrieNode node;
- ProfileFunction get profileFunction => node.profileFunction;
- @reflectable ServiceFunction get function => node.profileFunction.function;
- @reflectable String tipKind = '';
- @reflectable String tipParent = '';
- @reflectable String tipExclusive = '';
- @reflectable String tipTime = '';
- @reflectable String tipTicks = '';
-
- String tipOptimized = '';
-
- ProfileFunctionTrieNodeTreeRow(this.profile, this.root, this.node,
- TableTree tree,
- ProfileFunctionTrieNodeTreeRow parent)
- : super(tree, parent) {
- assert(root != null);
- assert(node != null);
- tipTicks = '${node.count}';
- var seconds = profile.approximateSecondsForCount(node.count);
- tipTime = Utils.formatTimePrecise(seconds);
- if (parent == null) {
- tipParent = Utils.formatPercent(node.count, root.count);
- } else {
- tipParent = Utils.formatPercent(node.count, parent.node.count);
- }
- if (function.kind == FunctionKind.kTag) {
- tipExclusive = Utils.formatPercent(node.count, root.count);
- } else {
- tipExclusive =
- Utils.formatPercent(node.profileFunction.exclusiveTicks, root.count);
+ for (var attribute in sorted(node.attributes)) {
+ methodColumn.children.add(newAttributeBox(attribute));
}
- if (function.kind == FunctionKind.kTag) {
- tipKind = 'Tag (category)';
- } else if (function.kind == FunctionKind.kCollected) {
- tipKind = 'Garbage Collected Code';
- } else {
- tipKind = '${function.kind} (Function)';
+ makeInfoBox();
+ methodColumn.children.add(infoBox);
+
+ infoBox.children.add(span('Code '));
+ infoBox.children.add(newCodeRef(node.profileCode));
+ infoBox.children.add(span(' '));
+ for (var attribute in sorted(node.profileCode.attributes)) {
+ infoBox.children.add(newAttributeBox(attribute));
}
- }
+ infoBox.children.add(br());
+ infoBox.children.add(br());
+ var memberList = new DivElement();
+ memberList.classes.add('memberList');
+ infoBox.children.add(br());
+ infoBox.children.add(memberList);
+ ProfileTreeRow._addToMemberList(memberList, {
+ 'Exclusive ticks' : node.profileCode.formattedExclusiveTicks,
+ 'Cpu time' : node.profileCode.formattedCpuTime,
+ 'Inclusive ticks' : node.profileCode.formattedInclusiveTicks,
+ 'Call stack time' : node.profileCode.formattedOnStackTime,
+ });
- bool hasChildren() {
- return node.children.length > 0;
+ makeInfoButton();
+ methodColumn.children.add(infoButton);
+
+ // Fill in self column.
+ var selfColumn = flexColumns[1];
+ selfColumn.style.position = 'relative';
+ selfColumn.style.alignItems = 'center';
+ selfColumn.text = selfPercent;
}
+}
- void _buildTooltip(DivElement memberList, Map<String, String> items) {
- items.forEach((k, v) {
- var item = new DivElement();
- item.classes.add('memberItem');
- var name = new DivElement();
- name.classes.add('memberName');
- name.classes.add('white');
- name.text = k;
- var value = new DivElement();
- value.classes.add('memberValue');
- value.classes.add('white');
- value.text = v;
- item.children.add(name);
- item.children.add(value);
- memberList.children.add(item);
- });
+class FunctionProfileTreeRow extends ProfileTreeRow<FunctionCallTreeNode> {
+ FunctionProfileTreeRow(TableTree tree, FunctionProfileTreeRow parent,
+ CpuProfile profile, FunctionCallTreeNode node)
+ : super(tree, parent, profile, node,
+ node.profileFunction.normalizedExclusiveTicks,
+ node.percentage) {
+ // fill out attributes.
}
- void onShow() {
+ bool hasChildren() => node.children.length > 0;
+
+ onShow() {
super.onShow();
if (children.length == 0) {
for (var childNode in node.children) {
- var row = new ProfileFunctionTrieNodeTreeRow(profile,
- root,
- childNode, tree, this);
+ var row = new FunctionProfileTreeRow(tree, this, profile, childNode);
children.add(row);
}
}
- var selfCell = tableColumns[1];
- selfCell.style.position = 'relative';
- selfCell.text = tipExclusive;
+ var methodColumn = flexColumns[0];
+ methodColumn.style.justifyContent = 'flex-start';
- var methodCell = tableColumns[0];
- // Enable expansion by clicking anywhere on the method column.
- methodCell.onClick.listen(onClick);
+ var codeAndFunctionColumn = new DivElement();
+ codeAndFunctionColumn.classes.add('flex-column');
+ codeAndFunctionColumn.style.justifyContent = 'center';
+ codeAndFunctionColumn.style.width = '100%';
+ methodColumn.children.add(codeAndFunctionColumn);
- // Grab the flex-row Div inside the methodCell.
- methodCell = methodCell.children[0];
+ var functionRow = new DivElement();
+ functionRow.classes.add('flex-row');
+ functionRow.style.position = 'relative';
+ functionRow.style.justifyContent = 'flex-start';
+ codeAndFunctionColumn.children.add(functionRow);
// Insert the parent percentage
- var parentPercent = new DivElement();
- parentPercent.text = tipParent;
- methodCell.children.add(parentPercent);
-
+ var parentPercent = new SpanElement();
+ parentPercent.text = percent;
+ parentPercent.style.minWidth = '4em';
+ parentPercent.style.alignSelf = 'center';
+ parentPercent.style.textAlign = 'right';
+ parentPercent.title = 'Self: $selfPercent';
+ functionRow.children.add(parentPercent);
+
+ // Gap.
var gap = new SpanElement();
gap.style.minWidth = '1em';
- methodCell.children.add(gap);
-
- var functionAndCodeContainer = new DivElement();
- methodCell.children.add(functionAndCodeContainer);
+ gap.text = ' ';
+ functionRow.children.add(gap);
var functionRef = new Element.tag('function-ref');
- functionRef.ref = function;
- functionAndCodeContainer.children.add(functionRef);
+ functionRef.ref = node.profileFunction.function;
+ functionRef.style.alignSelf = 'center';
+ functionRow.children.add(functionRef);
- var codeRow = new DivElement();
- codeRow.style.paddingTop = '1em';
- functionAndCodeContainer.children.add(codeRow);
- if (!function.kind.isSynthetic()) {
+ gap = new SpanElement();
+ gap.style.minWidth = '1em';
+ gap.text = ' ';
+ functionRow.children.add(gap);
+ for (var attribute in sorted(node.attributes)) {
+ functionRow.children.add(newAttributeBox(attribute));
+ }
+
+ makeInfoBox();
+ functionRow.children.add(infoBox);
+
+ if (node.profileFunction.function.kind.hasDartCode()) {
+ infoBox.children.add(div('Hot code for current node'));
+ infoBox.children.add(br());
var totalTicks = node.totalCodesTicks;
var numCodes = node.codes.length;
- var label = new SpanElement();
- label.text = 'Compiled into:\n';
- codeRow.children.add(label);
- var curlyBlock = new Element.tag('curly-block');
- codeRow.children.add(curlyBlock);
for (var i = 0; i < numCodes; i++) {
var codeRowSpan = new DivElement();
codeRowSpan.style.paddingLeft = '1em';
- curlyBlock.children.add(codeRowSpan);
+ infoBox.children.add(codeRowSpan);
var nodeCode = node.codes[i];
var ticks = nodeCode.ticks;
var percentage = Utils.formatPercent(ticks, totalTicks);
var percentageSpan = new SpanElement();
- percentageSpan.text = '($percentage) ';
+ percentageSpan.style.display = 'inline-block';
+ percentageSpan.text = '$percentage';
+ percentageSpan.style.minWidth = '5em';
+ percentageSpan.style.textAlign = 'right';
codeRowSpan.children.add(percentageSpan);
var codeRef = new Element.tag('code-ref');
codeRef.ref = nodeCode.code.code;
+ codeRef.style.marginLeft = '1em';
+ codeRef.style.marginRight = 'auto';
+ codeRef.style.width = '100%';
codeRowSpan.children.add(codeRef);
}
+ infoBox.children.add(hr());
}
-
- var tooltipDiv = new DivElement();
- tooltipDiv.classes.add('tooltip');
-
- var memberListDiv = new DivElement();
- memberListDiv.classes.add('memberList');
- tooltipDiv.children.add(memberListDiv);
- _buildTooltip(memberListDiv, {
- 'Kind' : tipKind,
- 'Percent of Parent' : tipParent,
- 'Sample Count' : tipTicks,
- 'Approximate Execution Time': tipTime,
+ infoBox.children.add(span('Function '));
+ infoBox.children.add(newFunctionRef(node.profileFunction));
+ infoBox.children.add(span(' '));
+ for (var attribute in sorted(node.profileFunction.attributes)) {
+ infoBox.children.add(newAttributeBox(attribute));
+ }
+ var memberList = new DivElement();
+ memberList.classes.add('memberList');
+ infoBox.children.add(br());
+ infoBox.children.add(br());
+ infoBox.children.add(memberList);
+ infoBox.children.add(br());
+ ProfileTreeRow._addToMemberList(memberList, {
+ 'Exclusive ticks' : node.profileFunction.formattedExclusiveTicks,
+ 'Cpu time' : node.profileFunction.formattedCpuTime,
+ 'Inclusive ticks' : node.profileFunction.formattedInclusiveTicks,
+ 'Call stack time' : node.profileFunction.formattedOnStackTime,
});
- selfCell.children.add(tooltipDiv);
+
+ if (node.profileFunction.function.kind.hasDartCode()) {
+ infoBox.children.add(div('Hot code containing function'));
+ infoBox.children.add(br());
+ var totalTicks = profile.sampleCount;
+ var codes = node.profileFunction.profileCodes;
+ var numCodes = codes.length;
+ for (var i = 0; i < numCodes; i++) {
+ var codeRowSpan = new DivElement();
+ codeRowSpan.style.paddingLeft = '1em';
+ infoBox.children.add(codeRowSpan);
+ var profileCode = codes[i];
+ var code = profileCode.code;
+ var ticks = profileCode.inclusiveTicks;
+ var percentage = Utils.formatPercent(ticks, totalTicks);
+ var percentageSpan = new SpanElement();
+ percentageSpan.style.display = 'inline-block';
+ percentageSpan.text = '$percentage';
+ percentageSpan.style.minWidth = '5em';
+ percentageSpan.style.textAlign = 'right';
+ percentageSpan.title = 'Inclusive ticks';
+ codeRowSpan.children.add(percentageSpan);
+ var codeRef = new Element.tag('code-ref');
+ codeRef.ref = code;
+ codeRef.style.marginLeft = '1em';
+ codeRef.style.marginRight = 'auto';
+ codeRef.style.width = '100%';
+ codeRowSpan.children.add(codeRef);
+ }
+ }
+
+ makeInfoButton();
+ methodColumn.children.add(infoButton);
+
+ // Fill in self column.
+ var selfColumn = flexColumns[1];
+ selfColumn.style.position = 'relative';
+ selfColumn.style.alignItems = 'center';
+ selfColumn.text = selfPercent;
}
}
@@ -299,11 +443,18 @@ class CpuProfileElement extends ObservatoryElement {
@observable String refreshTime = '';
@observable String sampleRate = '';
@observable String stackDepth = '';
- @observable String displayCutoff = '';
@observable String timeSpan = '';
-
+ @observable String fetchTime = '';
+ @observable String loadTime = '';
@observable String tagSelector = 'UserVM';
@observable String modeSelector = 'Function';
+ @observable String directionSelector = 'Up';
+
+ @observable String state = 'Requested';
+ @observable var exception;
+ @observable var stackTrace;
+
+ final Stopwatch _sw = new Stopwatch();
final CpuProfile profile = new CpuProfile();
@@ -326,6 +477,10 @@ class CpuProfileElement extends ObservatoryElement {
_updateView();
}
+ void directionSelectorChanged(oldValue) {
+ _updateView();
+ }
+
void clear(var done) {
_clearCpuProfile().whenComplete(done);
}
@@ -345,16 +500,55 @@ class CpuProfileElement extends ObservatoryElement {
_getCpuProfile().whenComplete(done);
}
- Future _getCpuProfile() {
+ _onFetchStarted() {
+ _sw.reset();
+ _sw.start();
+ state = 'Requested';
+ }
+
+ _onFetchFinished() {
+ _sw.stop();
+ fetchTime = formatTimeMilliseconds(_sw.elapsedMilliseconds);
+ }
+
+ _onLoadStarted() {
+ _sw.reset();
+ _sw.start();
+ state = 'Loading';
+ }
+
+ _onLoadFinished() {
+ _sw.stop();
+ loadTime = formatTimeMilliseconds(_sw.elapsedMilliseconds);
+ state = 'Loaded';
+ }
+
+ Future _getCpuProfile() async {
profile.clear();
+ if (functionTree != null) {
+ functionTree.clear();
+ }
+ if (codeTree != null) {
+ codeTree.clear();
+ }
if (isolate == null) {
return new Future.value(null);
}
- return isolate.invokeRpc('getCpuProfile', { 'tags': tagSelector })
- .then((ServiceMap response) {
- profile.load(isolate, response);
- _updateView();
- });
+ _onFetchStarted();
+ var response =
+ await isolate.invokeRpc('getCpuProfile', { 'tags': tagSelector });
+ _onFetchFinished();
+ _onLoadStarted();
+ await window.animationFrame;
+ try {
+ profile.load(isolate, response);
+ _onLoadFinished();
+ _updateView();
+ } catch (e, st) {
+ state = 'Exception';
+ exception = e;
+ stackTrace = st;
+ }
}
void _updateView() {
@@ -363,69 +557,49 @@ class CpuProfileElement extends ObservatoryElement {
stackDepth = profile.stackDepth.toString();
sampleRate = profile.sampleRate.toStringAsFixed(0);
timeSpan = formatTime(profile.timeSpan);
- displayCutoff = '${(profile.displayThreshold * 100.0).toString()}%';
if (functionTree != null) {
functionTree.clear();
}
if (codeTree != null) {
codeTree.clear();
}
+ bool exclusive = directionSelector == 'Up';
if (modeSelector == 'Code') {
- _buildCodeTree();
+ _buildCodeTree(exclusive);
} else {
- _buildFunctionTree();
+ _buildFunctionTree(exclusive);
}
}
TableTree codeTree;
TableTree functionTree;
- void _buildFunctionTree() {
+ void _buildFunctionTree(bool exclusive) {
if (functionTree == null) {
var tableBody = shadowRoot.querySelector('#treeBody');
assert(tableBody != null);
functionTree = new TableTree(tableBody, 2);
}
- var root = profile.functionTrieRoot;
- if (root == null) {
+ var tree = profile.functionTrees[exclusive ? 'exclusive' : 'inclusive'];
+ if (tree == null) {
return;
}
- try {
- functionTree.initialize(
- new ProfileFunctionTrieNodeTreeRow(profile,
- root, root, functionTree, null));
- } catch (e, stackTrace) {
- print(e);
- print(stackTrace);
- Logger.root.warning('_buildFunctionTree', e, stackTrace);
- }
- // Check if we only have one node at the root and expand it.
- if (functionTree.rows.length == 1) {
- functionTree.toggle(functionTree.rows[0]);
- }
+ var rootRow =
+ new FunctionProfileTreeRow(functionTree, null, profile, tree.root);
+ functionTree.initialize(rootRow);
}
- void _buildCodeTree() {
+ void _buildCodeTree(bool exclusive) {
if (codeTree == null) {
var tableBody = shadowRoot.querySelector('#treeBody');
assert(tableBody != null);
codeTree = new TableTree(tableBody, 2);
}
- var root = profile.codeTrieRoot;
- if (root == null) {
+ var tree = profile.codeTrees[exclusive ? 'exclusive' : 'inclusive'];
+ if (tree == null) {
return;
}
- try {
- codeTree.initialize(
- new ProfileCodeTrieNodeTreeRow(profile, root, root, codeTree, null));
- } catch (e, stackTrace) {
- print(e);
- print(stackTrace);
- Logger.root.warning('_buildCodeTree', e, stackTrace);
- }
- // Check if we only have one node at the root and expand it.
- if (codeTree.rows.length == 1) {
- codeTree.toggle(codeTree.rows[0]);
- }
+ var rootRow = new CodeProfileTreeRow(codeTree, null, profile, tree.root);
+ codeTree.initialize(rootRow);
}
}
« no previous file with comments | « runtime/observatory/lib/src/elements/class_tree.html ('k') | runtime/observatory/lib/src/elements/cpu_profile.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698