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

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

Issue 965593002: Improved profiler view and inclusive profile tree (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 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 | Annotate | Revision Log
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 CodeTrieNode { 7 class CodeCallTreeNode {
8 final ProfileCode profileCode; 8 final ProfileCode profileCode;
9 final int count; 9 final int count;
10 final children = new List<CodeTrieNode>(); 10 double get percentage => _percentage;
11 CodeTrieNode(this.profileCode, this.count); 11 double _percentage = 0.0;
12 final children = new List<CodeCallTreeNode>();
13 final Set<String> attributes = new Set<String>();
14 CodeCallTreeNode(this.profileCode, this.count) {
15 attributes.addAll(profileCode.attributes);
16 }
12 } 17 }
13 18
14 class FunctionTrieNodeCode { 19 class CodeCallTree {
20 final bool inclusive;
21 final CodeCallTreeNode root;
22 CodeCallTree(this.inclusive, this.root) {
23 _setCodePercentage(null, root);
24 }
25
26 _setCodePercentage(CodeCallTreeNode parent, CodeCallTreeNode node) {
27 assert(node != null);
28 var parentPercentage = 1.0;
29 var parentCount = node.count;
30 if (parent != null) {
31 parentPercentage = parent._percentage;
32 parentCount = parent.count;
33 }
34 if (inclusive) {
35 node._percentage = parentPercentage * (node.count / parentCount);
36 } else {
37 node._percentage = (node.count / parentCount);
38 }
39 for (var child in node.children) {
40 _setCodePercentage(node, child);
41 }
42 }
43 }
44
45 class FunctionCallTreeNodeCode {
15 final ProfileCode code; 46 final ProfileCode code;
16 final int ticks; 47 final int ticks;
17 FunctionTrieNodeCode(this.code, this.ticks); 48 FunctionCallTreeNodeCode(this.code, this.ticks);
18 } 49 }
19 50
20 class FunctionTrieNode { 51 class FunctionCallTreeNode {
21 final ProfileFunction profileFunction; 52 final ProfileFunction profileFunction;
22 final int count; 53 final int count;
23 final children = new List<FunctionTrieNode>(); 54 double get percentage => _percentage;
24 final codes = new List<FunctionTrieNodeCode>(); 55 double _percentage = 0.0;
56 final children = new List<FunctionCallTreeNode>();
57 final Set<String> attributes = new Set<String>();
58 final codes = new List<FunctionCallTreeNodeCode>();
25 int _totalCodeTicks = 0; 59 int _totalCodeTicks = 0;
26 int get totalCodesTicks => _totalCodeTicks; 60 int get totalCodesTicks => _totalCodeTicks;
27 FunctionTrieNode(this.profileFunction, this.count); 61
62 // Does this function have an optimized version of itself?
63 bool hasOptimizedCode() {
64 for (var nodeCode in codes) {
65 var profileCode = nodeCode.code;
66 if (!profileCode.code.isDartCode) {
67 continue;
68 }
69 if (profileCode.code.function != profileFunction.function) {
70 continue;
71 }
72 if (profileCode.code.isOptimized) {
73 return true;
74 }
75 }
76 return false;
77 }
78
79 // Does this function have an unoptimized version of itself?
80 bool hasUnoptimizedCode() {
81 for (var nodeCode in codes) {
82 var profileCode = nodeCode.code;
83 if (!profileCode.code.isDartCode) {
84 continue;
85 }
86 if (profileCode.code.kind == CodeKind.Stub) {
87 continue;
88 }
89 if (!profileCode.code.isOptimized) {
90 return true;
91 }
92 }
93 return false;
94 }
95
96 // Has this function been inlined in another function?
97 bool isInlined() {
98 for (var nodeCode in codes) {
99 var profileCode = nodeCode.code;
100 if (!profileCode.code.isDartCode) {
101 continue;
102 }
103 if (profileCode.code.kind == CodeKind.Stub) {
104 continue;
105 }
106 // If the code's function isn't this function.
107 if (profileCode.code.function != profileFunction.function) {
108 return true;
109 }
110 }
111 return false;
112 }
113
114 setCodeAttributes() {
115 if (hasOptimizedCode()) {
116 attributes.add('optimized');
117 }
118 if (hasUnoptimizedCode()) {
119 attributes.add('unoptimized');
120 }
121 if (isInlined()) {
122 attributes.add('inlined');
123 }
124 }
125
126 FunctionCallTreeNode(this.profileFunction, this.count) {
127 profileFunction._addKindBasedAttributes(attributes);
128 }
129 }
130
131 class FunctionCallTree {
132 final bool inclusive;
133 final FunctionCallTreeNode root;
134 FunctionCallTree(this.inclusive, this.root) {
135 _setFunctionPercentage(null, root);
136 }
137
138 void _setFunctionPercentage(FunctionCallTreeNode parent,
139 FunctionCallTreeNode node) {
140 assert(node != null);
141 var parentPercentage = 1.0;
142 var parentCount = node.count;
143 if (parent != null) {
144 parentPercentage = parent._percentage;
145 parentCount = parent.count;
146 }
147 if (inclusive) {
148 node._percentage = parentPercentage * (node.count / parentCount);
149 } else {
150 node._percentage = (node.count / parentCount);
151 }
152 for (var child in node.children) {
153 _setFunctionPercentage(node, child);
154 }
155 }
28 } 156 }
29 157
30 class CodeTick { 158 class CodeTick {
31 final int exclusiveTicks; 159 final int exclusiveTicks;
32 final int inclusiveTicks; 160 final int inclusiveTicks;
33 CodeTick(this.exclusiveTicks, this.inclusiveTicks); 161 CodeTick(this.exclusiveTicks, this.inclusiveTicks);
34 } 162 }
35 163
36 class InlineIntervalTick { 164 class InlineIntervalTick {
37 final int startAddress; 165 final int startAddress;
38 int _inclusiveTicks = 0; 166 int _inclusiveTicks = 0;
39 int get inclusiveTicks => _inclusiveTicks; 167 int get inclusiveTicks => _inclusiveTicks;
40 int _exclusiveTicks = 0; 168 int _exclusiveTicks = 0;
41 int get exclusiveTicks => _exclusiveTicks; 169 int get exclusiveTicks => _exclusiveTicks;
42 InlineIntervalTick(this.startAddress); 170 InlineIntervalTick(this.startAddress);
43 } 171 }
44 172
45 class ProfileCode { 173 class ProfileCode {
46 final CpuProfile profile; 174 final CpuProfile profile;
47 final Code code; 175 final Code code;
48 int exclusiveTicks; 176 int exclusiveTicks;
49 int inclusiveTicks; 177 int inclusiveTicks;
178 double normalizedExclusiveTicks = 0.0;
179 double normalizedInclusiveTicks = 0.0;
50 final addressTicks = new Map<int, CodeTick>(); 180 final addressTicks = new Map<int, CodeTick>();
51 final intervalTicks = new Map<int, InlineIntervalTick>(); 181 final intervalTicks = new Map<int, InlineIntervalTick>();
52 String formattedInclusiveTicks = ''; 182 String formattedInclusiveTicks = '';
53 String formattedExclusiveTicks = ''; 183 String formattedExclusiveTicks = '';
184 String formattedExclusivePercent = '';
185 String formattedCpuTime = '';
186 String formattedOnStackTime = '';
187 final Set<String> attributes = new Set<String>();
54 188
55 void _processTicks(List<String> profileTicks) { 189 void _processTicks(List<String> profileTicks) {
56 assert(profileTicks != null); 190 assert(profileTicks != null);
57 assert((profileTicks.length % 3) == 0); 191 assert((profileTicks.length % 3) == 0);
58 for (var i = 0; i < profileTicks.length; i += 3) { 192 for (var i = 0; i < profileTicks.length; i += 3) {
59 var address = int.parse(profileTicks[i], radix:16); 193 var address = int.parse(profileTicks[i], radix:16);
60 var exclusive = int.parse(profileTicks[i + 1]); 194 var exclusive = int.parse(profileTicks[i + 1]);
61 var inclusive = int.parse(profileTicks[i + 2]); 195 var inclusive = int.parse(profileTicks[i + 2]);
62 var tick = new CodeTick(exclusive, inclusive); 196 var tick = new CodeTick(exclusive, inclusive);
63 addressTicks[address] = tick; 197 addressTicks[address] = tick;
(...skipping 11 matching lines...) Expand all
75 } 209 }
76 } 210 }
77 } 211 }
78 212
79 ProfileCode.fromMap(this.profile, this.code, Map data) { 213 ProfileCode.fromMap(this.profile, this.code, Map data) {
80 assert(profile != null); 214 assert(profile != null);
81 assert(code != null); 215 assert(code != null);
82 216
83 code.profile = this; 217 code.profile = this;
84 218
219 if (code.isDartCode) {
220 if (code.isOptimized) {
221 attributes.add('optimized');
222 } else {
223 attributes.add('unoptimized');
224 }
225 }
226 if (code.isDartCode) {
227 attributes.add('dart');
228 } else if (code.kind == CodeKind.Tag) {
229 attributes.add('tag');
230 } else if (code.kind == CodeKind.Native) {
231 attributes.add('native');
232 }
85 inclusiveTicks = int.parse(data['inclusiveTicks']); 233 inclusiveTicks = int.parse(data['inclusiveTicks']);
86 exclusiveTicks = int.parse(data['exclusiveTicks']); 234 exclusiveTicks = int.parse(data['exclusiveTicks']);
235
236 normalizedExclusiveTicks = exclusiveTicks / profile.sampleCount;
237
238 normalizedInclusiveTicks = inclusiveTicks / profile.sampleCount;
239
87 var ticks = data['ticks']; 240 var ticks = data['ticks'];
88 if (ticks != null) { 241 if (ticks != null) {
89 _processTicks(ticks); 242 _processTicks(ticks);
90 } 243 }
91 244
245 formattedExclusivePercent =
246 Utils.formatPercent(exclusiveTicks, profile.sampleCount);
247
248 formattedCpuTime =
249 Utils.formatTimeMilliseconds(
250 profile.approximateMillisecondsForCount(exclusiveTicks));
251
252 formattedOnStackTime =
253 Utils.formatTimeMilliseconds(
254 profile.approximateMillisecondsForCount(inclusiveTicks));
255
92 formattedInclusiveTicks = 256 formattedInclusiveTicks =
93 '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} ' 257 '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} '
94 '($inclusiveTicks)'; 258 '($inclusiveTicks)';
95 259
96 formattedExclusiveTicks = 260 formattedExclusiveTicks =
97 '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} ' 261 '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} '
98 '($exclusiveTicks)'; 262 '($exclusiveTicks)';
99 } 263 }
100 } 264 }
101 265
102 class ProfileFunction { 266 class ProfileFunction {
103 final CpuProfile profile; 267 final CpuProfile profile;
104 final ServiceFunction function; 268 final ServiceFunction function;
105 // List of compiled code objects containing this function. 269 // List of compiled code objects containing this function.
106 final List<ProfileCode> profileCodes = new List<ProfileCode>(); 270 final List<ProfileCode> profileCodes = new List<ProfileCode>();
107
108 // Absolute ticks: 271 // Absolute ticks:
109 int exclusiveTicks = 0; 272 int exclusiveTicks = 0;
110 int inclusiveTicks = 0; 273 int inclusiveTicks = 0;
111 274
112 // Global percentages: 275 // Global percentages:
113 double globalExclusiveTicks = 0.0; 276 double normalizedExclusiveTicks = 0.0;
114 double globalInclusiveTicks = 0.0; 277 double normalizedInclusiveTicks = 0.0;
278
279 String formattedInclusiveTicks = '';
280 String formattedExclusiveTicks = '';
281 String formattedExclusivePercent = '';
282 String formattedCpuTime = '';
283 String formattedOnStackTime = '';
284 final Set<String> attributes = new Set<String>();
115 285
116 int _sortCodes(ProfileCode a, ProfileCode b) { 286 int _sortCodes(ProfileCode a, ProfileCode b) {
117 if (a.code.isOptimized == b.code.isOptimized) { 287 if (a.code.isOptimized == b.code.isOptimized) {
118 return b.code.profile.exclusiveTicks - a.code.profile.exclusiveTicks; 288 return b.code.profile.exclusiveTicks - a.code.profile.exclusiveTicks;
119 } 289 }
120 if (a.code.isOptimized) { 290 if (a.code.isOptimized) {
121 return -1; 291 return -1;
122 } 292 }
123 return 1; 293 return 1;
124 } 294 }
125 295
296 // Does this function have an optimized version of itself?
297 bool hasOptimizedCode() {
298 for (var profileCode in profileCodes) {
299 if (profileCode.code.function != function) {
300 continue;
301 }
302 if (profileCode.code.isOptimized) {
303 return true;
304 }
305 }
306 return false;
307 }
308
309 // Does this function have an unoptimized version of itself?
310 bool hasUnoptimizedCode() {
311 for (var profileCode in profileCodes) {
312 if (profileCode.code.kind == CodeKind.Stub) {
313 continue;
314 }
315 if (!profileCode.code.isDartCode) {
316 continue;
317 }
318 if (!profileCode.code.isOptimized) {
319 return true;
320 }
321 }
322 return false;
323 }
324
325 // Has this function been inlined in another function?
326 bool isInlined() {
327 for (var profileCode in profileCodes) {
328 if (profileCode.code.kind == CodeKind.Stub) {
329 continue;
330 }
331 if (!profileCode.code.isDartCode) {
332 continue;
333 }
334 // If the code's function isn't this function.
335 if (profileCode.code.function != function) {
336 return true;
337 }
338 }
339 return false;
340 }
341
342 void _addKindBasedAttributes(Set<String> attribs) {
343 if (function.kind == FunctionKind.kTag) {
344 attribs.add('tag');
345 } else if (function.kind == FunctionKind.kStub) {
346 attribs.add('dart');
347 attribs.add('stub');
348 } else if (function.kind == FunctionKind.kNative) {
349 attribs.add('native');
350 } else if (function.kind.isSynthetic()) {
351 attribs.add('synthetic');
352 } else {
353 attribs.add('dart');
354 }
355 }
356
126 ProfileFunction.fromMap(this.profile, this.function, Map data) { 357 ProfileFunction.fromMap(this.profile, this.function, Map data) {
127 for (var codeIndex in data['codes']) { 358 for (var codeIndex in data['codes']) {
128 var profileCode = profile.codes[codeIndex]; 359 var profileCode = profile.codes[codeIndex];
129 profileCodes.add(profileCode); 360 profileCodes.add(profileCode);
130 } 361 }
131 profileCodes.sort(_sortCodes); 362 profileCodes.sort(_sortCodes);
132 363
364 if (hasOptimizedCode()) {
365 attributes.add('optimized');
366 }
367 if (hasUnoptimizedCode()) {
368 attributes.add('unoptimized');
369 }
370 if (isInlined()) {
371 attributes.add('inlined');
372 }
373 _addKindBasedAttributes(attributes);
133 exclusiveTicks = int.parse(data['exclusiveTicks']); 374 exclusiveTicks = int.parse(data['exclusiveTicks']);
134 inclusiveTicks = int.parse(data['inclusiveTicks']); 375 inclusiveTicks = int.parse(data['inclusiveTicks']);
135 376
136 globalExclusiveTicks = exclusiveTicks / profile.sampleCount; 377 normalizedExclusiveTicks = exclusiveTicks / profile.sampleCount;
137 globalInclusiveTicks = inclusiveTicks / profile.sampleCount; 378 normalizedInclusiveTicks = inclusiveTicks / profile.sampleCount;
379
380 formattedExclusivePercent =
381 Utils.formatPercent(exclusiveTicks, profile.sampleCount);
382
383 formattedCpuTime =
384 Utils.formatTimeMilliseconds(
385 profile.approximateMillisecondsForCount(exclusiveTicks));
386
387 formattedOnStackTime =
388 Utils.formatTimeMilliseconds(
389 profile.approximateMillisecondsForCount(inclusiveTicks));
390
391 formattedInclusiveTicks =
392 '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} '
393 '($inclusiveTicks)';
394
395 formattedExclusiveTicks =
396 '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} '
397 '($exclusiveTicks)';
138 } 398 }
139 } 399 }
140 400
141 401
142 class CpuProfile { 402 class CpuProfile {
143 final double MICROSECONDS_PER_SECOND = 1000000.0; 403 final double MICROSECONDS_PER_SECOND = 1000000.0;
144 final double displayThreshold = 0.0002; // 0.02%. 404 final double displayThreshold = 0.0002; // 0.02%.
145 405
146 Isolate isolate; 406 Isolate isolate;
147 407
148 int sampleCount = 0; 408 int sampleCount = 0;
149 int samplePeriod = 0; 409 int samplePeriod = 0;
150 double sampleRate = 0.0; 410 double sampleRate = 0.0;
151 411
152 int stackDepth = 0; 412 int stackDepth = 0;
153 413
154 double timeSpan = 0.0; 414 double timeSpan = 0.0;
155 415
156 CodeTrieNode codeTrieRoot; 416 final Map<String, CodeCallTree> codeTrees =
157 FunctionTrieNode functionTrieRoot; 417 <String, CodeCallTree>{};
418 final Map<String, FunctionCallTree> functionTrees =
419 <String, FunctionCallTree>{};
158 420
159 final List<ProfileCode> codes = new List<ProfileCode>(); 421 final List<ProfileCode> codes = new List<ProfileCode>();
160 final List<ProfileFunction> functions = new List<ProfileFunction>(); 422 final List<ProfileFunction> functions = new List<ProfileFunction>();
161 423
162 void clear() { 424 void clear() {
163 sampleCount = 0; 425 sampleCount = 0;
164 samplePeriod = 0; 426 samplePeriod = 0;
165 sampleRate = 0.0; 427 sampleRate = 0.0;
166 stackDepth = 0; 428 stackDepth = 0;
167 timeSpan = 0.0; 429 timeSpan = 0.0;
168 codeTrieRoot = null; 430 codeTrees.clear();
169 functionTrieRoot = null; 431 functionTrees.clear();
170 codes.clear(); 432 codes.clear();
171 functions.clear(); 433 functions.clear();
172 } 434 }
173 435
174 void load(Isolate isolate, ServiceMap profile) { 436 void load(Isolate isolate, ServiceMap profile) {
175 if ((isolate == null) || (profile == null)) { 437 if ((isolate == null) || (profile == null)) {
176 return; 438 return;
177 } 439 }
178 440
179 this.isolate = isolate; 441 this.isolate = isolate;
(...skipping 15 matching lines...) Expand all
195 } 457 }
196 458
197 // Process function table. 459 // Process function table.
198 for (var profileFunction in profile['functions']) { 460 for (var profileFunction in profile['functions']) {
199 ServiceFunction function = profileFunction['function']; 461 ServiceFunction function = profileFunction['function'];
200 assert(function != null); 462 assert(function != null);
201 functions.add( 463 functions.add(
202 new ProfileFunction.fromMap(this, function, profileFunction)); 464 new ProfileFunction.fromMap(this, function, profileFunction));
203 } 465 }
204 466
205 // Process code trie. 467 // Process code trees.
206 var exclusiveCodeTrie = profile['exclusiveCodeTrie']; 468 var exclusiveCodeTrie = profile['exclusiveCodeTrie'];
207 assert(exclusiveCodeTrie != null); 469 if (exclusiveCodeTrie != null) {
208 codeTrieRoot = _processCodeTrie(exclusiveCodeTrie); 470 codeTrees['exclusive'] = _loadCodeTree(false, exclusiveCodeTrie);
471 }
472 var inclusiveCodeTrie = profile['inclusiveCodeTrie'];
473 if (inclusiveCodeTrie != null) {
474 codeTrees['inclusive'] = _loadCodeTree(true, inclusiveCodeTrie);
475 }
209 476
210 // Process function trie. 477 // Process function trees.
211 var exclusiveFunctionTrie = profile['exclusiveFunctionTrie']; 478 var exclusiveFunctionTrie = profile['exclusiveFunctionTrie'];
212 assert(exclusiveFunctionTrie != null); 479 if (exclusiveFunctionTrie != null) {
213 functionTrieRoot = _processFunctionTrie(exclusiveFunctionTrie); 480 functionTrees['exclusive'] =
481 _loadFunctionTree(false, exclusiveFunctionTrie);
482 }
483 var inclusiveFunctionTrie = profile['inclusiveFunctionTrie'];
484 if (inclusiveFunctionTrie != null) {
485 functionTrees['inclusive'] =
486 _loadFunctionTree(true, inclusiveFunctionTrie);
487 }
214 } 488 }
215 489
216 // Data shared across calls to _read*TrieNode. 490 // Data shared across calls to _read*TrieNode.
217 int _trieDataCursor; 491 int _trieDataCursor;
218 List<int> _trieData; 492 List<int> _trieData;
219 493
220 // The code trie is serialized as a list of integers. Each node 494 // The code trie is serialized as a list of integers. Each node
221 // is recreated by consuming some portion of the list. The format is as 495 // is recreated by consuming some portion of the list. The format is as
222 // follows: 496 // follows:
223 // [0] index into codeTable of code object. 497 // [0] index into codeTable of code object.
224 // [1] tick count (number of times this stack frame occured). 498 // [1] tick count (number of times this stack frame occured).
225 // [2] child node count 499 // [2] child node count
226 // Reading the trie is done by recursively reading the tree depth-first 500 // Reading the trie is done by recursively reading the tree depth-first
227 // pre-order. 501 // pre-order.
228 CodeTrieNode _processCodeTrie(List<int> data) { 502 CodeCallTree _loadCodeTree(bool inclusive, List<int> data) {
229 // Setup state shared across calls to _readTrieNode. 503 // Setup state shared across calls to _readTrieNode.
230 _trieDataCursor = 0; 504 _trieDataCursor = 0;
231 _trieData = data; 505 _trieData = data;
232 if (_trieData == null) { 506 if (_trieData == null) {
233 return null; 507 return null;
234 } 508 }
235 if (_trieData.length < 3) { 509 if (_trieData.length < 3) {
236 // Not enough integers for 1 node. 510 // Not enough integers for 1 node.
237 return null; 511 return null;
238 } 512 }
239 // Read the tree, returns the root node. 513 // Read the tree, returns the root node.
240 return _readCodeTrieNode(); 514 var root = _readCodeTrieNode();
515 return new CodeCallTree(inclusive, root);
241 } 516 }
242 517
243 CodeTrieNode _readCodeTrieNode() { 518 CodeCallTreeNode _readCodeTrieNode() {
244 // Read index into code table. 519 // Read index into code table.
245 var index = _trieData[_trieDataCursor++]; 520 var index = _trieData[_trieDataCursor++];
246 // Lookup code object. 521 // Lookup code object.
247 var code = codes[index]; 522 var code = codes[index];
248 // Frame counter. 523 // Frame counter.
249 var count = _trieData[_trieDataCursor++]; 524 var count = _trieData[_trieDataCursor++];
250 // Create node. 525 // Create node.
251 var node = new CodeTrieNode(code, count); 526 var node = new CodeCallTreeNode(code, count);
252 // Number of children. 527 // Number of children.
253 var children = _trieData[_trieDataCursor++]; 528 var children = _trieData[_trieDataCursor++];
254 // Recursively read child nodes. 529 // Recursively read child nodes.
255 for (var i = 0; i < children; i++) { 530 for (var i = 0; i < children; i++) {
256 var child = _readCodeTrieNode(); 531 var child = _readCodeTrieNode();
257 node.children.add(child); 532 node.children.add(child);
258 } 533 }
259 return node; 534 return node;
260 } 535 }
261 536
262 FunctionTrieNode _processFunctionTrie(List<int> data) { 537 FunctionCallTree _loadFunctionTree(bool inclusive, List<int> data) {
263 // Setup state shared across calls to _readTrieNode. 538 // Setup state shared across calls to _readTrieNode.
264 _trieDataCursor = 0; 539 _trieDataCursor = 0;
265 _trieData = data; 540 _trieData = data;
266 if (_trieData == null) { 541 if (_trieData == null) {
267 return null; 542 return null;
268 } 543 }
269 if (_trieData.length < 3) { 544 if (_trieData.length < 3) {
270 // Not enough integers for 1 node. 545 // Not enough integers for 1 node.
271 return null; 546 return null;
272 } 547 }
273 // Read the tree, returns the root node. 548 // Read the tree, returns the root node.
274 return _readFunctionTrieNode(); 549 var root = _readFunctionTrieNode();
550 return new FunctionCallTree(inclusive, root);
275 } 551 }
276 552
277 FunctionTrieNode _readFunctionTrieNode() { 553 FunctionCallTreeNode _readFunctionTrieNode() {
278 // Read index into function table. 554 // Read index into function table.
279 var index = _trieData[_trieDataCursor++]; 555 var index = _trieData[_trieDataCursor++];
280 // Lookup function object. 556 // Lookup function object.
281 var function = functions[index]; 557 var function = functions[index];
282 // Frame counter. 558 // Frame counter.
283 var count = _trieData[_trieDataCursor++]; 559 var count = _trieData[_trieDataCursor++];
284 // Create node. 560 // Create node.
285 var node = new FunctionTrieNode(function, count); 561 var node = new FunctionCallTreeNode(function, count);
286 // Number of code index / count pairs. 562 // Number of code index / count pairs.
287 var codeCount = _trieData[_trieDataCursor++]; 563 var codeCount = _trieData[_trieDataCursor++];
288 var totalCodeTicks = 0; 564 var totalCodeTicks = 0;
289 for (var i = 0; i < codeCount; i++) { 565 for (var i = 0; i < codeCount; i++) {
290 var codeIndex = _trieData[_trieDataCursor++]; 566 var codeIndex = _trieData[_trieDataCursor++];
291 var code = codes[codeIndex]; 567 var code = codes[codeIndex];
292 var codeTicks = _trieData[_trieDataCursor++]; 568 var codeTicks = _trieData[_trieDataCursor++];
293 totalCodeTicks += codeTicks; 569 totalCodeTicks += codeTicks;
294 var nodeCode = new FunctionTrieNodeCode(code, codeTicks); 570 var nodeCode = new FunctionCallTreeNodeCode(code, codeTicks);
295 node.codes.add(nodeCode); 571 node.codes.add(nodeCode);
572 node.setCodeAttributes();
296 } 573 }
297 node._totalCodeTicks = totalCodeTicks; 574 node._totalCodeTicks = totalCodeTicks;
298 // Number of children. 575 // Number of children.
299 var children = _trieData[_trieDataCursor++]; 576 var children = _trieData[_trieDataCursor++];
300 // Recursively read child nodes. 577 // Recursively read child nodes.
301 for (var i = 0; i < children; i++) { 578 for (var i = 0; i < children; i++) {
302 var child = _readFunctionTrieNode(); 579 var child = _readFunctionTrieNode();
303 node.children.add(child); 580 node.children.add(child);
304 } 581 }
305 return node; 582 return node;
306 } 583 }
307 584
585 int approximateMillisecondsForCount(count) {
586 var MICROSECONDS_PER_MILLISECOND = 1000.0;
587 return (count * samplePeriod) ~/ MICROSECONDS_PER_MILLISECOND;
588 }
589
308 double approximateSecondsForCount(count) { 590 double approximateSecondsForCount(count) {
309 var MICROSECONDS_PER_SECOND = 1000000.0; 591 var MICROSECONDS_PER_SECOND = 1000000.0;
310 return (count * samplePeriod) / MICROSECONDS_PER_SECOND; 592 return (count * samplePeriod) / MICROSECONDS_PER_SECOND;
311 } 593 }
312 } 594 }
OLDNEW
« no previous file with comments | « runtime/observatory/lib/src/app/view_model.dart ('k') | runtime/observatory/lib/src/elements/class_tree.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698