Index: runtime/observatory/lib/src/cpu_profile/cpu_profile.dart |
diff --git a/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart b/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart |
index d3e0252d10cd1d23a640242f1edc3c3573940148..75b693bbdcbc49d411ed6a777a01fff17d4cbdc3 100644 |
--- a/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart |
+++ b/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart |
@@ -4,26 +4,54 @@ |
part of cpu_profiler; |
-class CodeCallTreeNode { |
- final ProfileCode profileCode; |
+abstract class CallTreeNode { |
+ final List<CallTreeNode> children; |
final int count; |
double get percentage => _percentage; |
double _percentage = 0.0; |
- final children; |
final Set<String> attributes = new Set<String>(); |
- CodeCallTreeNode(this.profileCode, this.count, int childCount) |
- : children = new List<CodeCallTreeNode>(childCount) { |
+ |
+ // Either a ProfileCode or a ProfileFunction. |
+ Object get profileData; |
+ String get name; |
+ |
+ CallTreeNode(this.children, this.count); |
+} |
+ |
+class CodeCallTreeNode extends CallTreeNode { |
+ final ProfileCode profileCode; |
+ |
+ Object get profileData => profileCode; |
+ |
+ String get name => profileCode.code.name; |
+ |
+ final Set<String> attributes = new Set<String>(); |
+ CodeCallTreeNode(this.profileCode, int count) |
+ : super(new List<CodeCallTreeNode>(), count) { |
attributes.addAll(profileCode.attributes); |
} |
} |
-class CodeCallTree { |
+class CallTree { |
final bool inclusive; |
- final CodeCallTreeNode root; |
- CodeCallTree(this.inclusive, this.root) { |
+ final CallTreeNode root; |
+ |
+ CallTree(this.inclusive, this.root); |
+} |
+ |
+class CodeCallTree extends CallTree { |
+ CodeCallTree(bool inclusive, CodeCallTreeNode root) |
+ : super(inclusive, root) { |
_setCodePercentage(null, root); |
} |
+ CodeCallTree filtered(CallTreeNodeFilter filter) { |
+ var treeFilter = new _FilteredCodeCallTreeBuilder(filter, this); |
+ treeFilter.build(); |
+ _setCodePercentage(null, treeFilter.filtered.root); |
+ return treeFilter.filtered; |
+ } |
+ |
_setCodePercentage(CodeCallTreeNode parent, CodeCallTreeNode node) { |
assert(node != null); |
var parentPercentage = 1.0; |
@@ -67,18 +95,17 @@ class FunctionCallTreeNodeCode { |
FunctionCallTreeNodeCode(this.code, this.ticks); |
} |
-class FunctionCallTreeNode { |
+class FunctionCallTreeNode extends CallTreeNode { |
final ProfileFunction profileFunction; |
- final int count; |
- double get percentage => _percentage; |
- double _percentage = 0.0; |
- final children = new List<FunctionCallTreeNode>(); |
- final Set<String> attributes = new Set<String>(); |
final codes = new List<FunctionCallTreeNodeCode>(); |
int _totalCodeTicks = 0; |
int get totalCodesTicks => _totalCodeTicks; |
- FunctionCallTreeNode(this.profileFunction, this.count){ |
+ String get name => profileFunction.function.name; |
+ Object get profileData => profileFunction; |
+ |
+ FunctionCallTreeNode(this.profileFunction, int count) |
+ : super(new List<FunctionCallTreeNode>(), count) { |
profileFunction._addKindBasedAttributes(attributes); |
} |
@@ -140,27 +167,21 @@ class FunctionCallTreeNode { |
/// Predicate filter function. Returns true if path from root to [node] and all |
/// of [node]'s children should be added to the filtered tree. |
-typedef bool FunctionCallTreeNodeFilter(FunctionCallTreeNode node); |
+typedef bool CallTreeNodeFilter(CallTreeNode node); |
/// Build a filter version of a FunctionCallTree. |
-class _FilteredFunctionCallTreeBuilder { |
+abstract class _FilteredCallTreeBuilder { |
/// The filter. |
- final FunctionCallTreeNodeFilter filter; |
+ final CallTreeNodeFilter filter; |
/// The unfiltered tree. |
- final FunctionCallTree _unfilteredTree; |
+ final CallTree _unfilteredTree; |
/// The filtered tree (construct by [build]). |
- final FunctionCallTree filtered; |
+ final CallTree filtered; |
final List _currentPath = []; |
/// Construct a filtered tree builder using [filter] and [tree]. |
- _FilteredFunctionCallTreeBuilder(this.filter, FunctionCallTree tree) |
- : _unfilteredTree = tree, |
- filtered = |
- new FunctionCallTree( |
- tree.inclusive, |
- new FunctionCallTreeNode( |
- tree.root.profileFunction, |
- tree.root.count)); |
+ _FilteredCallTreeBuilder(this.filter, CallTree tree, this.filtered) |
+ : _unfilteredTree = tree; |
/// Build the filtered tree. |
build() { |
@@ -170,16 +191,18 @@ class _FilteredFunctionCallTreeBuilder { |
_descend(_unfilteredTree.root); |
} |
- FunctionCallTreeNode _findFunctionInChildren(FunctionCallTreeNode current, |
- FunctionCallTreeNode needle) { |
+ CallTreeNode _findInChildren(CallTreeNode current, |
+ CallTreeNode needle) { |
for (var child in current.children) { |
- if (child.profileFunction == needle.profileFunction) { |
+ if (child.profileData == needle.profileData) { |
return child; |
} |
} |
return null; |
} |
+ CallTreeNode _copyNode(CallTreeNode node); |
+ |
/// Add all nodes in [_currentPath]. |
FunctionCallTreeNode _addCurrentPath() { |
FunctionCallTreeNode current = filtered.root; |
@@ -191,10 +214,10 @@ class _FilteredFunctionCallTreeBuilder { |
// toAdd is from the unfiltered tree. |
var toAdd = _currentPath[i]; |
// See if we already have a node for toAdd in the filtered tree. |
- var child = _findFunctionInChildren(current, toAdd); |
+ var child = _findInChildren(current, toAdd); |
if (child == null) { |
// New node. |
- child = new FunctionCallTreeNode(toAdd.profileFunction, toAdd.count); |
+ child = _copyNode(toAdd); |
current.children.add(child); |
} |
current = child; |
@@ -204,13 +227,13 @@ class _FilteredFunctionCallTreeBuilder { |
} |
/// Starting at [current] append [next] and all of [next]'s sub-trees |
- _appendTree(FunctionCallTreeNode current, FunctionCallTreeNode next) { |
+ _appendTree(CallTreeNode current, CallTreeNode next) { |
if (next == null) { |
return; |
} |
- var child = _findFunctionInChildren(current, next); |
+ var child = _findInChildren(current, next); |
if (child == null) { |
- child = new FunctionCallTreeNode(next.profileFunction, next.count); |
+ child = _copyNode(next); |
current.children.add(child); |
} |
current = child; |
@@ -221,13 +244,13 @@ class _FilteredFunctionCallTreeBuilder { |
/// Add path from root to [child], [child], and all of [child]'s sub-trees |
/// to filtered tree. |
- _addTree(FunctionCallTreeNode child) { |
+ _addTree(CallTreeNode child) { |
var current = _addCurrentPath(); |
_appendTree(current, child); |
} |
/// Descend further into the tree. [current] is from the unfiltered tree. |
- _descend(FunctionCallTreeNode current) { |
+ _descend(CallTreeNode current) { |
if (current == null) { |
return; |
} |
@@ -256,14 +279,39 @@ class _FilteredFunctionCallTreeBuilder { |
} |
} |
-class FunctionCallTree { |
- final bool inclusive; |
- final FunctionCallTreeNode root; |
- FunctionCallTree(this.inclusive, this.root) { |
+class _FilteredFunctionCallTreeBuilder extends _FilteredCallTreeBuilder { |
+ _FilteredFunctionCallTreeBuilder(CallTreeNodeFilter filter, |
+ FunctionCallTree tree) |
+ : super(filter, tree, |
+ new FunctionCallTree(tree.inclusive, |
+ new FunctionCallTreeNode(tree.root.profileData, |
+ tree.root.count))); |
+ |
+ _copyNode(FunctionCallTreeNode node) { |
+ return new FunctionCallTreeNode(node.profileData, node.count); |
+ } |
+} |
+ |
+class _FilteredCodeCallTreeBuilder extends _FilteredCallTreeBuilder { |
+ _FilteredCodeCallTreeBuilder(CallTreeNodeFilter filter, |
+ CodeCallTree tree) |
+ : super(filter, tree, |
+ new CodeCallTree(tree.inclusive, |
+ new CodeCallTreeNode(tree.root.profileData, |
+ tree.root.count))); |
+ |
+ _copyNode(FunctionCallTreeNode node) { |
+ return new FunctionCallTreeNode(node.profileData, node.count); |
+ } |
+} |
+ |
+class FunctionCallTree extends CallTree { |
+ FunctionCallTree(bool inclusive, FunctionCallTreeNode root) |
+ : super(inclusive, root) { |
_setFunctionPercentage(null, root); |
} |
- FunctionCallTree filtered(FunctionCallTreeNodeFilter filter) { |
+ FunctionCallTree filtered(CallTreeNodeFilter filter) { |
var treeFilter = new _FilteredFunctionCallTreeBuilder(filter, this); |
treeFilter.build(); |
_setFunctionPercentage(null, treeFilter.filtered.root); |
@@ -732,7 +780,8 @@ class CpuProfile { |
// Child node count. |
var children = data[_dataCursor++]; |
// Create node. |
- var node = new CodeCallTreeNode(code, count, children); |
+ var node = new CodeCallTreeNode(code, count); |
+ node.children.length = children; |
return node; |
} |