OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 part of cpu_profiler; | 5 part of cpu_profiler; |
6 | 6 |
7 class CodeCallTreeNode { | 7 abstract class CallTreeNode { |
8 final ProfileCode profileCode; | 8 final List<CallTreeNode> children; |
9 final int count; | 9 final int count; |
10 double get percentage => _percentage; | 10 double get percentage => _percentage; |
11 double _percentage = 0.0; | 11 double _percentage = 0.0; |
12 final children; | |
13 final Set<String> attributes = new Set<String>(); | 12 final Set<String> attributes = new Set<String>(); |
14 CodeCallTreeNode(this.profileCode, this.count, int childCount) | 13 |
15 : children = new List<CodeCallTreeNode>(childCount) { | 14 // Either a ProfileCode or a ProfileFunction. |
| 15 Object get profileData; |
| 16 String get name; |
| 17 |
| 18 CallTreeNode(this.children, this.count); |
| 19 } |
| 20 |
| 21 class CodeCallTreeNode extends CallTreeNode { |
| 22 final ProfileCode profileCode; |
| 23 |
| 24 Object get profileData => profileCode; |
| 25 |
| 26 String get name => profileCode.code.name; |
| 27 |
| 28 final Set<String> attributes = new Set<String>(); |
| 29 CodeCallTreeNode(this.profileCode, int count) |
| 30 : super(new List<CodeCallTreeNode>(), count) { |
16 attributes.addAll(profileCode.attributes); | 31 attributes.addAll(profileCode.attributes); |
17 } | 32 } |
18 } | 33 } |
19 | 34 |
20 class CodeCallTree { | 35 class CallTree { |
21 final bool inclusive; | 36 final bool inclusive; |
22 final CodeCallTreeNode root; | 37 final CallTreeNode root; |
23 CodeCallTree(this.inclusive, this.root) { | 38 |
| 39 CallTree(this.inclusive, this.root); |
| 40 } |
| 41 |
| 42 class CodeCallTree extends CallTree { |
| 43 CodeCallTree(bool inclusive, CodeCallTreeNode root) |
| 44 : super(inclusive, root) { |
24 _setCodePercentage(null, root); | 45 _setCodePercentage(null, root); |
25 } | 46 } |
26 | 47 |
| 48 CodeCallTree filtered(CallTreeNodeFilter filter) { |
| 49 var treeFilter = new _FilteredCodeCallTreeBuilder(filter, this); |
| 50 treeFilter.build(); |
| 51 _setCodePercentage(null, treeFilter.filtered.root); |
| 52 return treeFilter.filtered; |
| 53 } |
| 54 |
27 _setCodePercentage(CodeCallTreeNode parent, CodeCallTreeNode node) { | 55 _setCodePercentage(CodeCallTreeNode parent, CodeCallTreeNode node) { |
28 assert(node != null); | 56 assert(node != null); |
29 var parentPercentage = 1.0; | 57 var parentPercentage = 1.0; |
30 var parentCount = node.count; | 58 var parentCount = node.count; |
31 if (parent != null) { | 59 if (parent != null) { |
32 parentPercentage = parent._percentage; | 60 parentPercentage = parent._percentage; |
33 parentCount = parent.count; | 61 parentCount = parent.count; |
34 } | 62 } |
35 if (inclusive) { | 63 if (inclusive) { |
36 node._percentage = parentPercentage * (node.count / parentCount); | 64 node._percentage = parentPercentage * (node.count / parentCount); |
(...skipping 23 matching lines...) Expand all Loading... |
60 } | 88 } |
61 } | 89 } |
62 } | 90 } |
63 | 91 |
64 class FunctionCallTreeNodeCode { | 92 class FunctionCallTreeNodeCode { |
65 final ProfileCode code; | 93 final ProfileCode code; |
66 final int ticks; | 94 final int ticks; |
67 FunctionCallTreeNodeCode(this.code, this.ticks); | 95 FunctionCallTreeNodeCode(this.code, this.ticks); |
68 } | 96 } |
69 | 97 |
70 class FunctionCallTreeNode { | 98 class FunctionCallTreeNode extends CallTreeNode { |
71 final ProfileFunction profileFunction; | 99 final ProfileFunction profileFunction; |
72 final int count; | |
73 double get percentage => _percentage; | |
74 double _percentage = 0.0; | |
75 final children = new List<FunctionCallTreeNode>(); | |
76 final Set<String> attributes = new Set<String>(); | |
77 final codes = new List<FunctionCallTreeNodeCode>(); | 100 final codes = new List<FunctionCallTreeNodeCode>(); |
78 int _totalCodeTicks = 0; | 101 int _totalCodeTicks = 0; |
79 int get totalCodesTicks => _totalCodeTicks; | 102 int get totalCodesTicks => _totalCodeTicks; |
80 | 103 |
81 FunctionCallTreeNode(this.profileFunction, this.count){ | 104 String get name => profileFunction.function.name; |
| 105 Object get profileData => profileFunction; |
| 106 |
| 107 FunctionCallTreeNode(this.profileFunction, int count) |
| 108 : super(new List<FunctionCallTreeNode>(), count) { |
82 profileFunction._addKindBasedAttributes(attributes); | 109 profileFunction._addKindBasedAttributes(attributes); |
83 } | 110 } |
84 | 111 |
85 // Does this function have an optimized version of itself? | 112 // Does this function have an optimized version of itself? |
86 bool hasOptimizedCode() { | 113 bool hasOptimizedCode() { |
87 for (var nodeCode in codes) { | 114 for (var nodeCode in codes) { |
88 var profileCode = nodeCode.code; | 115 var profileCode = nodeCode.code; |
89 if (!profileCode.code.isDartCode) { | 116 if (!profileCode.code.isDartCode) { |
90 continue; | 117 continue; |
91 } | 118 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 } | 160 } |
134 return false; | 161 return false; |
135 } | 162 } |
136 | 163 |
137 setCodeAttributes() { | 164 setCodeAttributes() { |
138 } | 165 } |
139 } | 166 } |
140 | 167 |
141 /// Predicate filter function. Returns true if path from root to [node] and all | 168 /// Predicate filter function. Returns true if path from root to [node] and all |
142 /// of [node]'s children should be added to the filtered tree. | 169 /// of [node]'s children should be added to the filtered tree. |
143 typedef bool FunctionCallTreeNodeFilter(FunctionCallTreeNode node); | 170 typedef bool CallTreeNodeFilter(CallTreeNode node); |
144 | 171 |
145 /// Build a filter version of a FunctionCallTree. | 172 /// Build a filter version of a FunctionCallTree. |
146 class _FilteredFunctionCallTreeBuilder { | 173 abstract class _FilteredCallTreeBuilder { |
147 /// The filter. | 174 /// The filter. |
148 final FunctionCallTreeNodeFilter filter; | 175 final CallTreeNodeFilter filter; |
149 /// The unfiltered tree. | 176 /// The unfiltered tree. |
150 final FunctionCallTree _unfilteredTree; | 177 final CallTree _unfilteredTree; |
151 /// The filtered tree (construct by [build]). | 178 /// The filtered tree (construct by [build]). |
152 final FunctionCallTree filtered; | 179 final CallTree filtered; |
153 final List _currentPath = []; | 180 final List _currentPath = []; |
154 | 181 |
155 /// Construct a filtered tree builder using [filter] and [tree]. | 182 /// Construct a filtered tree builder using [filter] and [tree]. |
156 _FilteredFunctionCallTreeBuilder(this.filter, FunctionCallTree tree) | 183 _FilteredCallTreeBuilder(this.filter, CallTree tree, this.filtered) |
157 : _unfilteredTree = tree, | 184 : _unfilteredTree = tree; |
158 filtered = | |
159 new FunctionCallTree( | |
160 tree.inclusive, | |
161 new FunctionCallTreeNode( | |
162 tree.root.profileFunction, | |
163 tree.root.count)); | |
164 | 185 |
165 /// Build the filtered tree. | 186 /// Build the filtered tree. |
166 build() { | 187 build() { |
167 assert(filtered != null); | 188 assert(filtered != null); |
168 assert(filter != null); | 189 assert(filter != null); |
169 assert(_unfilteredTree != null); | 190 assert(_unfilteredTree != null); |
170 _descend(_unfilteredTree.root); | 191 _descend(_unfilteredTree.root); |
171 } | 192 } |
172 | 193 |
173 FunctionCallTreeNode _findFunctionInChildren(FunctionCallTreeNode current, | 194 CallTreeNode _findInChildren(CallTreeNode current, |
174 FunctionCallTreeNode needle) { | 195 CallTreeNode needle) { |
175 for (var child in current.children) { | 196 for (var child in current.children) { |
176 if (child.profileFunction == needle.profileFunction) { | 197 if (child.profileData == needle.profileData) { |
177 return child; | 198 return child; |
178 } | 199 } |
179 } | 200 } |
180 return null; | 201 return null; |
181 } | 202 } |
182 | 203 |
| 204 CallTreeNode _copyNode(CallTreeNode node); |
| 205 |
183 /// Add all nodes in [_currentPath]. | 206 /// Add all nodes in [_currentPath]. |
184 FunctionCallTreeNode _addCurrentPath() { | 207 FunctionCallTreeNode _addCurrentPath() { |
185 FunctionCallTreeNode current = filtered.root; | 208 FunctionCallTreeNode current = filtered.root; |
186 // Tree root is always the first element of the current path. | 209 // Tree root is always the first element of the current path. |
187 assert(_unfilteredTree.root == _currentPath[0]); | 210 assert(_unfilteredTree.root == _currentPath[0]); |
188 // Assert that unfiltered tree's root and filtered tree's root are different
. | 211 // Assert that unfiltered tree's root and filtered tree's root are different
. |
189 assert(_unfilteredTree.root != current); | 212 assert(_unfilteredTree.root != current); |
190 for (var i = 1; i < _currentPath.length; i++) { | 213 for (var i = 1; i < _currentPath.length; i++) { |
191 // toAdd is from the unfiltered tree. | 214 // toAdd is from the unfiltered tree. |
192 var toAdd = _currentPath[i]; | 215 var toAdd = _currentPath[i]; |
193 // See if we already have a node for toAdd in the filtered tree. | 216 // See if we already have a node for toAdd in the filtered tree. |
194 var child = _findFunctionInChildren(current, toAdd); | 217 var child = _findInChildren(current, toAdd); |
195 if (child == null) { | 218 if (child == null) { |
196 // New node. | 219 // New node. |
197 child = new FunctionCallTreeNode(toAdd.profileFunction, toAdd.count); | 220 child = _copyNode(toAdd); |
198 current.children.add(child); | 221 current.children.add(child); |
199 } | 222 } |
200 current = child; | 223 current = child; |
201 assert(current.count == toAdd.count); | 224 assert(current.count == toAdd.count); |
202 } | 225 } |
203 return current; | 226 return current; |
204 } | 227 } |
205 | 228 |
206 /// Starting at [current] append [next] and all of [next]'s sub-trees | 229 /// Starting at [current] append [next] and all of [next]'s sub-trees |
207 _appendTree(FunctionCallTreeNode current, FunctionCallTreeNode next) { | 230 _appendTree(CallTreeNode current, CallTreeNode next) { |
208 if (next == null) { | 231 if (next == null) { |
209 return; | 232 return; |
210 } | 233 } |
211 var child = _findFunctionInChildren(current, next); | 234 var child = _findInChildren(current, next); |
212 if (child == null) { | 235 if (child == null) { |
213 child = new FunctionCallTreeNode(next.profileFunction, next.count); | 236 child = _copyNode(next); |
214 current.children.add(child); | 237 current.children.add(child); |
215 } | 238 } |
216 current = child; | 239 current = child; |
217 for (var nextChild in next.children) { | 240 for (var nextChild in next.children) { |
218 _appendTree(current, nextChild); | 241 _appendTree(current, nextChild); |
219 } | 242 } |
220 } | 243 } |
221 | 244 |
222 /// Add path from root to [child], [child], and all of [child]'s sub-trees | 245 /// Add path from root to [child], [child], and all of [child]'s sub-trees |
223 /// to filtered tree. | 246 /// to filtered tree. |
224 _addTree(FunctionCallTreeNode child) { | 247 _addTree(CallTreeNode child) { |
225 var current = _addCurrentPath(); | 248 var current = _addCurrentPath(); |
226 _appendTree(current, child); | 249 _appendTree(current, child); |
227 } | 250 } |
228 | 251 |
229 /// Descend further into the tree. [current] is from the unfiltered tree. | 252 /// Descend further into the tree. [current] is from the unfiltered tree. |
230 _descend(FunctionCallTreeNode current) { | 253 _descend(CallTreeNode current) { |
231 if (current == null) { | 254 if (current == null) { |
232 return; | 255 return; |
233 } | 256 } |
234 _currentPath.add(current); | 257 _currentPath.add(current); |
235 | 258 |
236 if (filter(current)) { | 259 if (filter(current)) { |
237 // Filter matched. | 260 // Filter matched. |
238 if (current.children.length == 0) { | 261 if (current.children.length == 0) { |
239 // Have no children. Add this path. | 262 // Have no children. Add this path. |
240 _addTree(null); | 263 _addTree(null); |
241 } else { | 264 } else { |
242 // Add all child trees. | 265 // Add all child trees. |
243 for (var child in current.children) { | 266 for (var child in current.children) { |
244 _addTree(child); | 267 _addTree(child); |
245 } | 268 } |
246 } | 269 } |
247 } else { | 270 } else { |
248 // Did not match, descend to each child. | 271 // Did not match, descend to each child. |
249 for (var child in current.children) { | 272 for (var child in current.children) { |
250 _descend(child); | 273 _descend(child); |
251 } | 274 } |
252 } | 275 } |
253 | 276 |
254 var last = _currentPath.removeLast(); | 277 var last = _currentPath.removeLast(); |
255 assert(current == last); | 278 assert(current == last); |
256 } | 279 } |
257 } | 280 } |
258 | 281 |
259 class FunctionCallTree { | 282 class _FilteredFunctionCallTreeBuilder extends _FilteredCallTreeBuilder { |
260 final bool inclusive; | 283 _FilteredFunctionCallTreeBuilder(CallTreeNodeFilter filter, |
261 final FunctionCallTreeNode root; | 284 FunctionCallTree tree) |
262 FunctionCallTree(this.inclusive, this.root) { | 285 : super(filter, tree, |
| 286 new FunctionCallTree(tree.inclusive, |
| 287 new FunctionCallTreeNode(tree.root.profileData, |
| 288 tree.root.count))); |
| 289 |
| 290 _copyNode(FunctionCallTreeNode node) { |
| 291 return new FunctionCallTreeNode(node.profileData, node.count); |
| 292 } |
| 293 } |
| 294 |
| 295 class _FilteredCodeCallTreeBuilder extends _FilteredCallTreeBuilder { |
| 296 _FilteredCodeCallTreeBuilder(CallTreeNodeFilter filter, |
| 297 CodeCallTree tree) |
| 298 : super(filter, tree, |
| 299 new CodeCallTree(tree.inclusive, |
| 300 new CodeCallTreeNode(tree.root.profileData, |
| 301 tree.root.count))); |
| 302 |
| 303 _copyNode(FunctionCallTreeNode node) { |
| 304 return new FunctionCallTreeNode(node.profileData, node.count); |
| 305 } |
| 306 } |
| 307 |
| 308 class FunctionCallTree extends CallTree { |
| 309 FunctionCallTree(bool inclusive, FunctionCallTreeNode root) |
| 310 : super(inclusive, root) { |
263 _setFunctionPercentage(null, root); | 311 _setFunctionPercentage(null, root); |
264 } | 312 } |
265 | 313 |
266 FunctionCallTree filtered(FunctionCallTreeNodeFilter filter) { | 314 FunctionCallTree filtered(CallTreeNodeFilter filter) { |
267 var treeFilter = new _FilteredFunctionCallTreeBuilder(filter, this); | 315 var treeFilter = new _FilteredFunctionCallTreeBuilder(filter, this); |
268 treeFilter.build(); | 316 treeFilter.build(); |
269 _setFunctionPercentage(null, treeFilter.filtered.root); | 317 _setFunctionPercentage(null, treeFilter.filtered.root); |
270 return treeFilter.filtered; | 318 return treeFilter.filtered; |
271 } | 319 } |
272 | 320 |
273 void _setFunctionPercentage(FunctionCallTreeNode parent, | 321 void _setFunctionPercentage(FunctionCallTreeNode parent, |
274 FunctionCallTreeNode node) { | 322 FunctionCallTreeNode node) { |
275 assert(node != null); | 323 assert(node != null); |
276 var parentPercentage = 1.0; | 324 var parentPercentage = 1.0; |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 | 773 |
726 CodeCallTreeNode _readCodeTrieNode(List<int> data) { | 774 CodeCallTreeNode _readCodeTrieNode(List<int> data) { |
727 // Lookup code object. | 775 // Lookup code object. |
728 var codeIndex = data[_dataCursor++]; | 776 var codeIndex = data[_dataCursor++]; |
729 var code = codes[codeIndex]; | 777 var code = codes[codeIndex]; |
730 // Node tick counter. | 778 // Node tick counter. |
731 var count = data[_dataCursor++]; | 779 var count = data[_dataCursor++]; |
732 // Child node count. | 780 // Child node count. |
733 var children = data[_dataCursor++]; | 781 var children = data[_dataCursor++]; |
734 // Create node. | 782 // Create node. |
735 var node = new CodeCallTreeNode(code, count, children); | 783 var node = new CodeCallTreeNode(code, count); |
| 784 node.children.length = children; |
736 return node; | 785 return node; |
737 } | 786 } |
738 | 787 |
739 CodeCallTreeNode _readCodeTrie(List<int> data) { | 788 CodeCallTreeNode _readCodeTrie(List<int> data) { |
740 final nodeStack = new List<CodeCallTreeNode>(); | 789 final nodeStack = new List<CodeCallTreeNode>(); |
741 final childIndexStack = new List<int>(); | 790 final childIndexStack = new List<int>(); |
742 | 791 |
743 _dataCursor = 0; | 792 _dataCursor = 0; |
744 // Read root. | 793 // Read root. |
745 var root = _readCodeTrieNode(data); | 794 var root = _readCodeTrieNode(data); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
871 int approximateMillisecondsForCount(count) { | 920 int approximateMillisecondsForCount(count) { |
872 var MICROSECONDS_PER_MILLISECOND = 1000.0; | 921 var MICROSECONDS_PER_MILLISECOND = 1000.0; |
873 return (count * samplePeriod) ~/ MICROSECONDS_PER_MILLISECOND; | 922 return (count * samplePeriod) ~/ MICROSECONDS_PER_MILLISECOND; |
874 } | 923 } |
875 | 924 |
876 double approximateSecondsForCount(count) { | 925 double approximateSecondsForCount(count) { |
877 var MICROSECONDS_PER_SECOND = 1000000.0; | 926 var MICROSECONDS_PER_SECOND = 1000000.0; |
878 return (count * samplePeriod) / MICROSECONDS_PER_SECOND; | 927 return (count * samplePeriod) / MICROSECONDS_PER_SECOND; |
879 } | 928 } |
880 } | 929 } |
OLD | NEW |