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

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

Issue 928833003: Add Function based profile tree (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 10 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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of cpu_profiler;
6
7 class CodeTrieNode {
8 final ProfileCode profileCode;
9 final int count;
10 final children = new List<CodeTrieNode>();
11 CodeTrieNode(this.profileCode, this.count);
12 }
13
14 class FunctionTrieNode {
15 final ProfileFunction profileFunction;
16 final int count;
17 final children = new List<FunctionTrieNode>();
18 FunctionTrieNode(this.profileFunction, this.count);
19 }
20
21 class CodeTick {
22 final int address;
23 final int exclusiveTicks;
24 final int inclusiveTicks;
25 CodeTick(this.address, this.exclusiveTicks, this.inclusiveTicks);
26 }
27
28 class ProfileCode {
29 final CpuProfile profile;
30 final Code code;
31 int exclusiveTicks;
32 int inclusiveTicks;
33 final addressTicks = new Map<int, CodeTick>();
34 String formattedInclusiveTicks = '';
35 String formattedExclusiveTicks = '';
36
37 void _processTicks(List<String> profileTicks) {
38 assert(profileTicks != null);
39 assert((profileTicks.length % 3) == 0);
40 for (var i = 0; i < profileTicks.length; i += 3) {
41 var address = int.parse(profileTicks[i], radix:16);
42 var exclusive = int.parse(profileTicks[i + 1]);
43 var inclusive = int.parse(profileTicks[i + 2]);
44 var tick = new CodeTick(address, exclusive, inclusive);
45 addressTicks[address] = tick;
46 }
47 }
48
49 ProfileCode.fromMap(this.profile, this.code, Map data) {
50 assert(profile != null);
51 assert(code != null);
52
53 code.profile = this;
54
55 inclusiveTicks = int.parse(data['inclusiveTicks']);
56 exclusiveTicks = int.parse(data['exclusiveTicks']);
57 var ticks = data['ticks'];
58 if (ticks != null) {
59 _processTicks(ticks);
60 }
61
62 formattedInclusiveTicks =
63 '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} '
64 '($inclusiveTicks)';
65
66 formattedExclusiveTicks =
67 '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} '
68 '($exclusiveTicks)';
69 }
70 }
71
72 class ProfileFunction {
73 final CpuProfile profile;
74 final ServiceFunction function;
75 // List of compiled code objects containing this function.
76 final List<ProfileCode> profileCodes = new List<ProfileCode>();
77
78 // Absolute ticks:
79 int exclusiveTicks = 0;
80 int inclusiveTicks = 0;
81 int exclusiveOptimizedTicks = 0;
82 int inclusiveOptimizedTicks = 0;
83
84 // Global percentages:
85 double globalExclusiveTicks = 0.0;
86 double globalInclusiveTicks = 0.0;
87 double globalExclusiveOptimizedTicks = 0.0;
88 double globalInclusiveOptimizedTicks = 0.0;
89
90 int _sortCodes(ProfileCode a, ProfileCode b) {
91 if (a.code.isOptimized == b.code.isOptimized) {
92 return 0;
93 }
94 if (a.code.isOptimized) {
95 return -1;
96 }
97 return 1;
98 }
99
100 ProfileFunction.fromMap(this.profile, this.function, Map data) {
101 for (var codeIndex in data['codes']) {
102 var profileCode = profile.codes[codeIndex];
103 profileCodes.add(profileCode);
104 exclusiveTicks += profileCode.exclusiveTicks;
105 inclusiveTicks += profileCode.inclusiveTicks;
106 if (profileCode.code.isOptimized) {
107 exclusiveOptimizedTicks += profileCode.exclusiveTicks;
108 inclusiveOptimizedTicks += profileCode.inclusiveTicks;
109 }
110 }
111
112 profileCodes.sort(_sortCodes);
113
114 globalExclusiveTicks = exclusiveTicks / profile.sampleCount;
115 globalInclusiveTicks = inclusiveTicks / profile.sampleCount;
116
117 globalExclusiveOptimizedTicks =
118 exclusiveOptimizedTicks / profile.sampleCount;
119 globalInclusiveOptimizedTicks =
120 inclusiveOptimizedTicks / profile.sampleCount;
121 }
122 }
123
124
125 class CpuProfile {
126 final double MICROSECONDS_PER_SECOND = 1000000.0;
127 final double displayThreshold = 0.0002; // 0.02%.
128
129 Isolate isolate;
130
131 int sampleCount = 0;
132 int samplePeriod = 0;
133 double sampleRate = 0.0;
134
135 int stackDepth = 0;
136
137 double timeSpan = 0.0;
138
139 CodeTrieNode codeTrieRoot;
140 FunctionTrieNode functionTrieRoot;
141
142 final List<ProfileCode> codes = new List<ProfileCode>();
143 final List<ProfileFunction> functions = new List<ProfileFunction>();
144
145 void clear() {
146 codeTrieRoot = null;
147 functionTrieRoot = null;
148 codes.clear();
149 functions.clear();
150 }
151
152 void load(Isolate isolate, ServiceMap profile) {
153 if ((isolate == null) || (profile == null)) {
154 return;
155 }
156
157 this.isolate = isolate;
158 isolate.resetCachedProfileData();
159
160 clear();
161
162 sampleCount = profile['sampleCount'];
163 samplePeriod = profile['samplePeriod'];
164 sampleRate = (MICROSECONDS_PER_SECOND / samplePeriod);
165 stackDepth = profile['stackDepth'];
166 timeSpan = profile['timeSpan'];
167
168 // Process code table.
169 for (var codeRegion in profile['codes']) {
170 Code code = codeRegion['code'];
171 assert(code != null);
172 codes.add(new ProfileCode.fromMap(this, code, codeRegion));
173 }
174
175 // Process function table.
176 for (var profileFunction in profile['functions']) {
177 ServiceFunction function = profileFunction['function'];
178 assert(function != null);
179 functions.add(
180 new ProfileFunction.fromMap(this, function, profileFunction));
181 }
182
183 // Process code trie.
184 var exclusiveCodeTrie = profile['exclusiveCodeTrie'];
185 assert(exclusiveCodeTrie != null);
186 codeTrieRoot = _processCodeTrie(exclusiveCodeTrie);
187
188 // Process function trie.
189 var exclusiveFunctionTrie = profile['exclusiveFunctionTrie'];
190 assert(exclusiveFunctionTrie != null);
191 functionTrieRoot = _processFunctionTrie(exclusiveFunctionTrie);
192 }
193
194 // Data shared across calls to _read*TrieNode.
195 int _trieDataCursor;
196 List<int> _trieData;
197
198 // The code trie is serialized as a list of integers. Each node
199 // is recreated by consuming some portion of the list. The format is as
200 // follows:
201 // [0] index into codeTable of code object.
202 // [1] tick count (number of times this stack frame occured).
203 // [2] child node count
204 // Reading the trie is done by recursively reading the tree depth-first
205 // pre-order.
206 CodeTrieNode _processCodeTrie(List<int> data) {
207 // Setup state shared across calls to _readTrieNode.
208 _trieDataCursor = 0;
209 _trieData = data;
210 if (_trieData == null) {
211 return null;
212 }
213 if (_trieData.length < 3) {
214 // Not enough integers for 1 node.
215 return null;
216 }
217 // Read the tree, returns the root node.
218 return _readCodeTrieNode();
219 }
220
221 CodeTrieNode _readCodeTrieNode() {
222 // Read index into code table.
223 var index = _trieData[_trieDataCursor++];
224 // Lookup code object.
225 var code = codes[index];
226 // Frame counter.
227 var count = _trieData[_trieDataCursor++];
228 // Create node.
229 var node = new CodeTrieNode(code, count);
230 // Number of children.
231 var children = _trieData[_trieDataCursor++];
232 // Recursively read child nodes.
233 for (var i = 0; i < children; i++) {
234 var child = _readCodeTrieNode();
235 node.children.add(child);
236 }
237 return node;
238 }
239
240 FunctionTrieNode _processFunctionTrie(List<int> data) {
241 // Setup state shared across calls to _readTrieNode.
242 _trieDataCursor = 0;
243 _trieData = data;
244 if (_trieData == null) {
245 return null;
246 }
247 if (_trieData.length < 3) {
248 // Not enough integers for 1 node.
249 return null;
250 }
251 // Read the tree, returns the root node.
252 return _readFunctionTrieNode();
253 }
254
255 FunctionTrieNode _readFunctionTrieNode() {
256 // Read index into function table.
257 var index = _trieData[_trieDataCursor++];
258 // Lookup function object.
259 var function = functions[index];
260 // Frame counter.
261 var count = _trieData[_trieDataCursor++];
262 // Create node.
263 var node = new FunctionTrieNode(function, count);
264 // Number of children.
265 var children = _trieData[_trieDataCursor++];
266 // Recursively read child nodes.
267 for (var i = 0; i < children; i++) {
268 var child = _readFunctionTrieNode();
269 node.children.add(child);
270 }
271 return node;
272 }
273
274 double approximateSecondsForCount(count) {
275 var MICROSECONDS_PER_SECOND = 1000000.0;
276 return (count * samplePeriod) / MICROSECONDS_PER_SECOND;
277 }
278 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698