Index: runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart |
diff --git a/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart b/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart |
index 7617a20da4ada1bc6083171d19f10695b4699cf2..8cd41fb3110421c22cdbd3fc9c25f9a9486ae2ea 100644 |
--- a/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart |
+++ b/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart |
@@ -29,12 +29,14 @@ class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable { |
M.ProfileTreeDirection _direction; |
ProfileTreeMode _mode; |
+ M.SampleProfileType _type; |
M.IsolateRef _isolate; |
M.SampleProfile _profile; |
Iterable<M.CallTreeNodeFilter> _filters; |
M.ProfileTreeDirection get direction => _direction; |
ProfileTreeMode get mode => _mode; |
+ M.SampleProfileType get type => _type; |
M.IsolateRef get isolate => _isolate; |
M.SampleProfile get profile => _profile; |
Iterable<M.CallTreeNodeFilter> get filters => _filters; |
@@ -50,9 +52,9 @@ class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable { |
factory CpuProfileVirtualTreeElement( |
M.IsolateRef isolate, M.SampleProfile profile, |
{ProfileTreeMode mode: ProfileTreeMode.function, |
+ M.SampleProfileType type: M.SampleProfileType.cpu, |
M.ProfileTreeDirection direction: M.ProfileTreeDirection.exclusive, |
RenderingQueue queue}) { |
- assert(isolate != null); |
assert(profile != null); |
assert(mode != null); |
assert(direction != null); |
@@ -61,6 +63,7 @@ class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable { |
e._isolate = isolate; |
e._profile = profile; |
e._mode = mode; |
+ e._type = type; |
e._direction = direction; |
return e; |
} |
@@ -84,18 +87,37 @@ class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable { |
void render() { |
var tree; |
+ var create; |
var update; |
- switch (mode) { |
- case ProfileTreeMode.code: |
- tree = _profile.loadCodeTree(_direction); |
- update = _updateCodeRow; |
+ |
+ switch (type) { |
+ case M.SampleProfileType.cpu: |
+ create = _createCpuRow; |
+ if (mode == ProfileTreeMode.code) { |
+ update = _updateCpuCodeRow; |
+ tree = _profile.loadCodeTree(_direction); |
+ } else if (mode == ProfileTreeMode.function) { |
+ update = _updateCpuFunctionRow; |
+ tree = _profile.loadFunctionTree(_direction); |
+ } else { |
+ throw new Exception('Unknown ProfileTreeMode: $mode'); |
+ } |
break; |
- case ProfileTreeMode.function: |
- tree = _profile.loadFunctionTree(_direction); |
- update = _updateFunctionRow; |
+ case M.SampleProfileType.memory: |
+ create = _createMemoryRow; |
+ if (mode == ProfileTreeMode.code) { |
+ update = _updateMemoryCodeRow; |
+ tree = _profile.loadCodeTree(_direction); |
+ } else if (mode == ProfileTreeMode.function) { |
+ update = _updateMemoryFunctionRow; |
+ tree = _profile.loadFunctionTree(_direction); |
+ } else { |
+ throw new Exception('Unknown ProfileTreeMode: $mode'); |
+ } |
break; |
default: |
- throw new Exception('Unknown ProfileTreeMode: $mode'); |
+ throw new Exception('Unknown SampleProfileType: $type'); |
+ break; |
} |
if (filters != null) { |
tree = filters.fold(tree, (tree, filter) { |
@@ -106,7 +128,7 @@ class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable { |
children = [new HeadingElement.h1()..text = 'No Results']; |
return; |
} |
- _tree = new VirtualTreeElement(_createRow, update, _getChildren, |
+ _tree = new VirtualTreeElement(create, update, _getChildren, |
items: tree.root.children, queue: _r.queue); |
if (tree.root.children.length == 1) { |
_tree.expand(tree.root.children.first, autoExpandSingleChildNodes: true); |
@@ -114,7 +136,7 @@ class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable { |
children = [_tree]; |
} |
- static Element _createRow(toggle) { |
+ static Element _createCpuRow(toggle) { |
return new DivElement() |
..classes = ['tree-item'] |
..children = [ |
@@ -135,9 +157,33 @@ class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable { |
]; |
} |
+ static Element _createMemoryRow(toggle) { |
+ return new DivElement() |
+ ..classes = ['tree-item'] |
+ ..children = [ |
+ new SpanElement() |
+ ..classes = ['inclusive'] |
+ ..title = 'memory allocated from resulting calls: ', |
+ new SpanElement() |
+ ..classes = ['exclusive'] |
+ ..title = 'memory allocated during execution: ', |
+ new SpanElement()..classes = ['lines'], |
+ new ButtonElement() |
+ ..classes = ['expander'] |
+ ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)), |
+ new SpanElement() |
+ ..classes = ['percentage'] |
+ ..title = 'tree node %', |
+ new SpanElement()..classes = ['name'] |
+ ]; |
+ } |
+ |
static _getChildren(M.CallTreeNode node) => node.children; |
- void _updateFunctionRow( |
+ static const String _expandedIcon = '▼'; |
+ static const String _collapsedIcon = '►'; |
+ |
+ void _updateCpuFunctionRow( |
HtmlElement element, M.FunctionCallTreeNode item, int depth) { |
element.children[0].text = Utils |
.formatPercentNormalized(item.profileFunction.normalizedInclusiveTicks); |
@@ -145,7 +191,8 @@ class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable { |
.formatPercentNormalized(item.profileFunction.normalizedExclusiveTicks); |
_updateLines(element.children[2].children, depth); |
if (item.children.isNotEmpty) { |
- element.children[3].text = _tree.isExpanded(item) ? '▼' : '►'; |
+ element.children[3].text = _tree.isExpanded(item) ? _expandedIcon : |
+ _collapsedIcon; |
} else { |
element.children[3].text = ''; |
} |
@@ -155,14 +202,39 @@ class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable { |
..classes = ['name']; |
} |
- void _updateCodeRow(HtmlElement element, M.CodeCallTreeNode item, int depth) { |
+ void _updateMemoryFunctionRow( |
+ HtmlElement element, M.FunctionCallTreeNode item, int depth) { |
+ element.children[0].text = |
+ Utils.formatSize(item.inclusiveNativeAllocations); |
+ element.children[0].title = 'memory allocated from resulting calls: ' + |
+ '${item.inclusiveNativeAllocations}B'; |
+ element.children[1].text = |
+ Utils.formatSize(item.exclusiveNativeAllocations); |
+ element.children[1].title = 'memory allocated during execution: ' + |
+ '${item.exclusiveNativeAllocations}B'; |
+ _updateLines(element.children[2].children, depth); |
+ if (item.children.isNotEmpty) { |
+ element.children[3].text = _tree.isExpanded(item) ? _expandedIcon : |
+ _collapsedIcon; |
+ } else { |
+ element.children[3].text = ''; |
+ } |
+ element.children[4].text = Utils.formatPercentNormalized(item.percentage); |
+ element.children[5] = new FunctionRefElement( |
+ null, item.profileFunction.function, queue: _r.queue) |
+ ..classes = ['name']; |
+ } |
+ |
+ void _updateCpuCodeRow( |
+ HtmlElement element, M.CodeCallTreeNode item, int depth) { |
element.children[0].text = Utils |
.formatPercentNormalized(item.profileCode.normalizedInclusiveTicks); |
element.children[1].text = Utils |
.formatPercentNormalized(item.profileCode.normalizedExclusiveTicks); |
_updateLines(element.children[2].children, depth); |
if (item.children.isNotEmpty) { |
- element.children[3].text = _tree.isExpanded(item) ? '▼' : '►'; |
+ element.children[3].text = _tree.isExpanded(item) ? _expandedIcon : |
+ _collapsedIcon; |
} else { |
element.children[3].text = ''; |
} |
@@ -171,6 +243,28 @@ class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable { |
queue: _r.queue)..classes = ['name']; |
} |
+ void _updateMemoryCodeRow( |
+ HtmlElement element, M.CodeCallTreeNode item, int depth) { |
+ element.children[0].text = |
+ Utils.formatSize(item.inclusiveNativeAllocations); |
+ element.children[0].title = 'memory allocated from resulting calls: ' + |
+ '${item.inclusiveNativeAllocations}B'; |
+ element.children[1].text = |
+ Utils.formatSize(item.exclusiveNativeAllocations); |
+ element.children[1].title = 'memory allocated during execution: ' + |
+ '${item.exclusiveNativeAllocations}B'; |
+ _updateLines(element.children[2].children, depth); |
+ if (item.children.isNotEmpty) { |
+ element.children[3].text = _tree.isExpanded(item) ? _expandedIcon : |
+ _collapsedIcon; |
+ } else { |
+ element.children[3].text = ''; |
+ } |
+ element.children[4].text = Utils.formatPercentNormalized(item.percentage); |
+ element.children[5] = new CodeRefElement(null, item.profileCode.code, |
+ queue: _r.queue)..classes = ['name']; |
+ } |
+ |
static _updateLines(List<Element> lines, int n) { |
n = Math.max(0, n); |
while (lines.length > n) { |