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

Side by Side Diff: runtime/observatory/lib/src/cpu_profile/cpu_profile.dart

Issue 1837373002: Refactor call tree search to support both Code and Function trees (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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 unified diff | Download patch
« no previous file with comments | « no previous file | runtime/observatory/lib/src/elements/cpu_profile.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | runtime/observatory/lib/src/elements/cpu_profile.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698