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 1c6d9801228b0a47cb4b21762f6c3e80252521f2..b3059914a564783ae50533d53440bdf5bf21f0d6 100644 |
--- a/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart |
+++ b/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart |
@@ -8,6 +8,8 @@ abstract class CallTreeNode<NodeT extends M.CallTreeNode> |
implements M.CallTreeNode { |
final List<NodeT> children; |
final int count; |
+ final int inclusiveNativeAllocations; |
+ final int exclusiveNativeAllocations; |
double get percentage => _percentage; |
double _percentage = 0.0; |
final Set<String> attributes = new Set<String>(); |
@@ -16,7 +18,8 @@ abstract class CallTreeNode<NodeT extends M.CallTreeNode> |
Object get profileData; |
String get name; |
- CallTreeNode(this.children, this.count); |
+ CallTreeNode(this.children, this.count, this.inclusiveNativeAllocations, |
+ this.exclusiveNativeAllocations); |
} |
class CodeCallTreeNode extends CallTreeNode<CodeCallTreeNode> |
@@ -28,8 +31,10 @@ class CodeCallTreeNode extends CallTreeNode<CodeCallTreeNode> |
String get name => profileCode.code.name; |
final Set<String> attributes = new Set<String>(); |
- CodeCallTreeNode(this.profileCode, int count) |
- : super(new List<CodeCallTreeNode>(), count) { |
+ CodeCallTreeNode(this.profileCode, int count, int inclusiveNativeAllocations, |
+ int exclusiveNativeAllocations) |
+ : super(new List<CodeCallTreeNode>(), count, inclusiveNativeAllocations, |
+ exclusiveNativeAllocations) { |
attributes.addAll(profileCode.attributes); |
} |
} |
@@ -44,13 +49,21 @@ class CallTree<NodeT extends CallTreeNode> { |
class CodeCallTree extends CallTree<CodeCallTreeNode> |
implements M.CodeCallTree { |
CodeCallTree(bool inclusive, CodeCallTreeNode root) : super(inclusive, root) { |
- _setCodePercentage(null, root); |
+ if (root.inclusiveNativeAllocations != 0) { |
+ _setCodeMemoryPercentage(null, root); |
+ } else { |
+ _setCodePercentage(null, root); |
+ } |
} |
CodeCallTree filtered(CallTreeNodeFilter filter) { |
var treeFilter = new _FilteredCodeCallTreeBuilder(filter, this); |
treeFilter.build(); |
- _setCodePercentage(null, treeFilter.filtered.root); |
+ if (treeFilter.filtered.root.inclusiveNativeAllocations != 0) { |
+ _setCodeMemoryPercentage(null, treeFilter.filtered.root); |
+ } else { |
+ _setCodePercentage(null, treeFilter.filtered.root); |
+ } |
return treeFilter.filtered; |
} |
@@ -72,6 +85,25 @@ class CodeCallTree extends CallTree<CodeCallTreeNode> |
} |
} |
+ _setCodeMemoryPercentage(CodeCallTreeNode parent, CodeCallTreeNode node) { |
+ assert(node != null); |
+ var parentPercentage = 1.0; |
+ var parentMemory = node.inclusiveNativeAllocations; |
+ if (parent != null) { |
+ parentPercentage = parent._percentage; |
+ parentMemory = parent.inclusiveNativeAllocations; |
+ } |
+ if (inclusive) { |
+ node._percentage = parentPercentage * |
+ (node.inclusiveNativeAllocations / parentMemory); |
+ } else { |
+ node._percentage = (node.inclusiveNativeAllocations / parentMemory); |
+ } |
+ for (var child in node.children) { |
+ _setCodeMemoryPercentage(node, child); |
+ } |
+ } |
+ |
_recordCallerAndCalleesInner( |
CodeCallTreeNode caller, CodeCallTreeNode callee) { |
if (caller != null) { |
@@ -106,8 +138,10 @@ class FunctionCallTreeNode extends CallTreeNode { |
String get name => M.getFunctionFullName(profileFunction.function); |
Object get profileData => profileFunction; |
- FunctionCallTreeNode(this.profileFunction, int count) |
- : super(new List<FunctionCallTreeNode>(), count) { |
+ FunctionCallTreeNode(this.profileFunction, int count, |
+ inclusiveNativeAllocations, exclusiveNativeAllocations) |
+ : super(new List<FunctionCallTreeNode>(), count, |
+ inclusiveNativeAllocations, exclusiveNativeAllocations) { |
profileFunction._addKindBasedAttributes(attributes); |
} |
@@ -290,10 +324,13 @@ class _FilteredFunctionCallTreeBuilder extends _FilteredCallTreeBuilder { |
new FunctionCallTree( |
tree.inclusive, |
new FunctionCallTreeNode( |
- tree.root.profileData, tree.root.count))); |
+ tree.root.profileData, tree.root.count, |
+ tree.root.inclusiveNativeAllocations, |
+ tree.root.exclusiveNativeAllocations))); |
_copyNode(FunctionCallTreeNode node) { |
- return new FunctionCallTreeNode(node.profileData, node.count); |
+ return new FunctionCallTreeNode(node.profileData, node.count, |
+ node.inclusiveNativeAllocations, node.exclusiveNativeAllocations); |
} |
} |
@@ -303,23 +340,34 @@ class _FilteredCodeCallTreeBuilder extends _FilteredCallTreeBuilder { |
filter, |
tree, |
new CodeCallTree(tree.inclusive, |
- new CodeCallTreeNode(tree.root.profileData, tree.root.count))); |
+ new CodeCallTreeNode(tree.root.profileData, tree.root.count, |
+ tree.root.inclusiveNativeAllocations, |
+ tree.root.exclusiveNativeAllocations))); |
_copyNode(CodeCallTreeNode node) { |
- return new CodeCallTreeNode(node.profileData, node.count); |
+ return new CodeCallTreeNode(node.profileData, node.count, |
+ node.inclusiveNativeAllocations, node.exclusiveNativeAllocations); |
} |
} |
class FunctionCallTree extends CallTree implements M.FunctionCallTree { |
FunctionCallTree(bool inclusive, FunctionCallTreeNode root) |
: super(inclusive, root) { |
- _setFunctionPercentage(null, root); |
+ if (root.inclusiveNativeAllocations != 0) { |
Cutch
2017/03/21 20:27:10
it looks like inclusiveNativeAllocations be null w
bkonyi
2017/03/22 21:25:21
Done.
|
+ _setFunctionMemoryPercentage(null, root); |
+ } else { |
+ _setFunctionPercentage(null, root); |
+ } |
} |
FunctionCallTree filtered(CallTreeNodeFilter filter) { |
var treeFilter = new _FilteredFunctionCallTreeBuilder(filter, this); |
treeFilter.build(); |
- _setFunctionPercentage(null, treeFilter.filtered.root); |
+ if (treeFilter.filtered.root.inclusiveNativeAllocations != 0) { |
Cutch
2017/03/21 20:27:10
ditto
bkonyi
2017/03/22 21:25:21
Done.
|
+ _setFunctionMemoryPercentage(null, treeFilter.filtered.root); |
+ } else { |
+ _setFunctionPercentage(null, treeFilter.filtered.root); |
+ } |
return treeFilter.filtered; |
} |
@@ -342,6 +390,25 @@ class FunctionCallTree extends CallTree implements M.FunctionCallTree { |
} |
} |
+ void _setFunctionMemoryPercentage(FunctionCallTreeNode parent, FunctionCallTreeNode node) { |
Cutch
2017/03/21 20:27:10
long line, you probably want to run dartfmt on it.
bkonyi
2017/03/22 21:25:21
Done.
|
+ assert(node != null); |
+ var parentPercentage = 1.0; |
+ var parentMemory = node.inclusiveNativeAllocations; |
+ if (parent != null) { |
+ parentPercentage = parent._percentage; |
+ parentMemory = parent.inclusiveNativeAllocations; |
+ } |
+ if (inclusive) { |
+ node._percentage = parentPercentage * |
+ (node.inclusiveNativeAllocations / parentMemory); |
+ } else { |
+ node._percentage = (node.inclusiveNativeAllocations / parentMemory); |
+ } |
+ for (var child in node.children) { |
+ _setFunctionMemoryPercentage(node, child); |
+ } |
+ } |
+ |
_markFunctionCallsInner( |
FunctionCallTreeNode caller, FunctionCallTreeNode callee) { |
if (caller != null) { |
@@ -382,6 +449,8 @@ class ProfileCode implements M.ProfileCode { |
final Code code; |
int exclusiveTicks; |
int inclusiveTicks; |
+ int exclusiveNativeAllocations; |
+ int inclusiveNativeAllocations; |
double normalizedExclusiveTicks = 0.0; |
double normalizedInclusiveTicks = 0.0; |
final addressTicks = new Map<int, CodeTick>(); |
@@ -458,6 +527,14 @@ class ProfileCode implements M.ProfileCode { |
_processTicks(ticks); |
} |
+ if (data.containsKey('exclusiveNativeAllocations') && |
+ data.containsKey('inclusiveNativeAllocations')) { |
+ exclusiveNativeAllocations = |
+ int.parse(data['exclusiveNativeAllocations']); |
+ inclusiveNativeAllocations = |
+ int.parse(data['inclusiveNativeAllocations']); |
+ } |
+ |
formattedExclusivePercent = |
Utils.formatPercent(exclusiveTicks, profile.sampleCount); |
@@ -509,6 +586,10 @@ class ProfileFunction implements M.ProfileFunction { |
double normalizedExclusiveTicks = 0.0; |
double normalizedInclusiveTicks = 0.0; |
+ // Native allocations: |
+ int exclusiveNativeAllocations = 0; |
+ int inclusiveNativeAllocations = 0; |
+ |
String formattedInclusiveTicks = ''; |
String formattedExclusiveTicks = ''; |
String formattedExclusivePercent = ''; |
@@ -606,6 +687,14 @@ class ProfileFunction implements M.ProfileFunction { |
normalizedExclusiveTicks = exclusiveTicks / profile.sampleCount; |
normalizedInclusiveTicks = inclusiveTicks / profile.sampleCount; |
+ if (data.containsKey('exclusiveNativeAllocations') && |
+ data.containsKey('inclusiveNativeAllocations')) { |
+ exclusiveNativeAllocations = |
+ int.parse(data['exclusiveNativeAllocations']); |
+ inclusiveNativeAllocations = |
+ int.parse(data['inclusiveNativeAllocations']); |
+ } |
+ |
formattedExclusivePercent = |
Utils.formatPercent(exclusiveTicks, profile.sampleCount); |
@@ -710,8 +799,8 @@ class CpuProfile extends M.SampleProfile { |
_builtFunctionCalls = false; |
} |
- Future load(Isolate isolate, ServiceMap profile) async { |
- await loadProgress(isolate, profile).last; |
+ Future load(Object owner, ServiceMap profile) async { |
+ await loadProgress(owner, profile).last; |
} |
static Future sleep([Duration duration = const Duration(microseconds: 0)]) { |
@@ -720,7 +809,7 @@ class CpuProfile extends M.SampleProfile { |
return completer.future; |
} |
- Stream<double> loadProgress(Isolate isolate, ServiceMap profile) { |
+ Stream<double> loadProgress(Object owner, ServiceMap profile) { |
var progress = new StreamController<double>.broadcast(); |
(() async { |
@@ -742,12 +831,14 @@ class CpuProfile extends M.SampleProfile { |
try { |
clear(); |
progress.add(0.0); |
- if ((isolate == null) || (profile == null)) { |
+ if (profile == null) { |
return; |
} |
- this.isolate = isolate; |
- isolate.resetCachedProfileData(); |
+ if (owner != null && owner is Isolate) { |
+ isolate = owner as Isolate; |
+ isolate.resetCachedProfileData(); |
+ } |
sampleCount = profile['sampleCount']; |
samplePeriod = profile['samplePeriod']; |
@@ -824,8 +915,13 @@ class CpuProfile extends M.SampleProfile { |
var count = data[_dataCursor++]; |
// Child node count. |
var children = data[_dataCursor++]; |
+ // Inclusive native allocations. |
+ var inclusiveNativeAllocations = data[_dataCursor++]; |
+ // Exclusive native allocations. |
+ var exclusiveNativeAllocations = data[_dataCursor++]; |
// Create node. |
- var node = new CodeCallTreeNode(code, count); |
+ var node = new CodeCallTreeNode(code, count, inclusiveNativeAllocations, |
+ exclusiveNativeAllocations); |
node.children.length = children; |
return node; |
} |
@@ -894,8 +990,13 @@ class CpuProfile extends M.SampleProfile { |
var function = functions[index]; |
// Counter. |
var count = data[_dataCursor++]; |
+ // Inclusive native allocations. |
+ var inclusiveNativeAllocations = data[_dataCursor++]; |
+ // Exclusive native allocations. |
+ var exclusiveNativeAllocations = data[_dataCursor++]; |
// Create node. |
- var node = new FunctionCallTreeNode(function, count); |
+ var node = new FunctionCallTreeNode(function, count, |
+ inclusiveNativeAllocations, exclusiveNativeAllocations); |
// Number of code index / count pairs. |
var codeCount = data[_dataCursor++]; |
node.codes.length = codeCount; |