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

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, 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
(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 FunctionTrieNodeCode {
15 final ProfileCode code;
16 final int ticks;
17 FunctionTrieNodeCode(this.code, this.ticks);
18 }
19
20 class FunctionTrieNode {
21 final ProfileFunction profileFunction;
22 final int count;
23 final children = new List<FunctionTrieNode>();
24 final codes = new List<FunctionTrieNodeCode>();
25 int _totalCodeTicks = 0;
26 int get totalCodesTicks => _totalCodeTicks;
27 FunctionTrieNode(this.profileFunction, this.count);
28 }
29
30 class CodeTick {
31 final int exclusiveTicks;
32 final int inclusiveTicks;
33 CodeTick(this.exclusiveTicks, this.inclusiveTicks);
34 }
35
36 class InlineIntervalTick {
37 final int startAddress;
38 int _inclusiveTicks = 0;
39 int get inclusiveTicks => _inclusiveTicks;
40 int _exclusiveTicks = 0;
41 int get exclusiveTicks => _exclusiveTicks;
42 InlineIntervalTick(this.startAddress);
43 }
44
45 class ProfileCode {
46 final CpuProfile profile;
47 final Code code;
48 int exclusiveTicks;
49 int inclusiveTicks;
50 final addressTicks = new Map<int, CodeTick>();
51 final intervalTicks = new Map<int, InlineIntervalTick>();
52 String formattedInclusiveTicks = '';
53 String formattedExclusiveTicks = '';
54
55 void _processTicks(List<String> profileTicks) {
56 assert(profileTicks != null);
57 assert((profileTicks.length % 3) == 0);
58 for (var i = 0; i < profileTicks.length; i += 3) {
59 var address = int.parse(profileTicks[i], radix:16);
60 var exclusive = int.parse(profileTicks[i + 1]);
61 var inclusive = int.parse(profileTicks[i + 2]);
62 var tick = new CodeTick(exclusive, inclusive);
63 addressTicks[address] = tick;
64
65 var interval = code.findInterval(address);
66 if (interval != null) {
67 var intervalTick = intervalTicks[interval.start];
68 if (intervalTick == null) {
69 // Insert into map.
70 intervalTick = new InlineIntervalTick(interval.start);
71 intervalTicks[interval.start] = intervalTick;
72 }
73 intervalTick._inclusiveTicks += inclusive;
74 intervalTick._exclusiveTicks += exclusive;
75 }
76 }
77 }
78
79 ProfileCode.fromMap(this.profile, this.code, Map data) {
80 assert(profile != null);
81 assert(code != null);
82
83 code.profile = this;
84
85 inclusiveTicks = int.parse(data['inclusiveTicks']);
86 exclusiveTicks = int.parse(data['exclusiveTicks']);
87 var ticks = data['ticks'];
88 if (ticks != null) {
89 _processTicks(ticks);
90 }
91
92 formattedInclusiveTicks =
93 '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} '
94 '($inclusiveTicks)';
95
96 formattedExclusiveTicks =
97 '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} '
98 '($exclusiveTicks)';
99 }
100 }
101
102 class ProfileFunction {
103 final CpuProfile profile;
104 final ServiceFunction function;
105 // List of compiled code objects containing this function.
106 final List<ProfileCode> profileCodes = new List<ProfileCode>();
107
108 // Absolute ticks:
109 int exclusiveTicks = 0;
110 int inclusiveTicks = 0;
111
112 // Global percentages:
113 double globalExclusiveTicks = 0.0;
114 double globalInclusiveTicks = 0.0;
115
116 int _sortCodes(ProfileCode a, ProfileCode b) {
117 if (a.code.isOptimized == b.code.isOptimized) {
118 return b.code.profile.exclusiveTicks - a.code.profile.exclusiveTicks;
119 }
120 if (a.code.isOptimized) {
121 return -1;
122 }
123 return 1;
124 }
125
126 ProfileFunction.fromMap(this.profile, this.function, Map data) {
127 for (var codeIndex in data['codes']) {
128 var profileCode = profile.codes[codeIndex];
129 profileCodes.add(profileCode);
130 }
131 profileCodes.sort(_sortCodes);
132
133 exclusiveTicks = int.parse(data['exclusiveTicks']);
134 inclusiveTicks = int.parse(data['inclusiveTicks']);
135
136 globalExclusiveTicks = exclusiveTicks / profile.sampleCount;
137 globalInclusiveTicks = inclusiveTicks / profile.sampleCount;
138 }
139 }
140
141
142 class CpuProfile {
143 final double MICROSECONDS_PER_SECOND = 1000000.0;
144 final double displayThreshold = 0.0002; // 0.02%.
145
146 Isolate isolate;
147
148 int sampleCount = 0;
149 int samplePeriod = 0;
150 double sampleRate = 0.0;
151
152 int stackDepth = 0;
153
154 double timeSpan = 0.0;
155
156 CodeTrieNode codeTrieRoot;
157 FunctionTrieNode functionTrieRoot;
158
159 final List<ProfileCode> codes = new List<ProfileCode>();
160 final List<ProfileFunction> functions = new List<ProfileFunction>();
161
162 void clear() {
163 sampleCount = 0;
164 samplePeriod = 0;
165 sampleRate = 0.0;
166 stackDepth = 0;
167 timeSpan = 0.0;
168 codeTrieRoot = null;
169 functionTrieRoot = null;
170 codes.clear();
171 functions.clear();
172 }
173
174 void load(Isolate isolate, ServiceMap profile) {
175 if ((isolate == null) || (profile == null)) {
176 return;
177 }
178
179 this.isolate = isolate;
180 isolate.resetCachedProfileData();
181
182 clear();
183
184 sampleCount = profile['sampleCount'];
185 samplePeriod = profile['samplePeriod'];
186 sampleRate = (MICROSECONDS_PER_SECOND / samplePeriod);
187 stackDepth = profile['stackDepth'];
188 timeSpan = profile['timeSpan'];
189
190 // Process code table.
191 for (var codeRegion in profile['codes']) {
192 Code code = codeRegion['code'];
193 assert(code != null);
194 codes.add(new ProfileCode.fromMap(this, code, codeRegion));
195 }
196
197 // Process function table.
198 for (var profileFunction in profile['functions']) {
199 ServiceFunction function = profileFunction['function'];
200 assert(function != null);
201 functions.add(
202 new ProfileFunction.fromMap(this, function, profileFunction));
203 }
204
205 // Process code trie.
206 var exclusiveCodeTrie = profile['exclusiveCodeTrie'];
207 assert(exclusiveCodeTrie != null);
208 codeTrieRoot = _processCodeTrie(exclusiveCodeTrie);
209
210 // Process function trie.
211 var exclusiveFunctionTrie = profile['exclusiveFunctionTrie'];
212 assert(exclusiveFunctionTrie != null);
213 functionTrieRoot = _processFunctionTrie(exclusiveFunctionTrie);
214 }
215
216 // Data shared across calls to _read*TrieNode.
217 int _trieDataCursor;
218 List<int> _trieData;
219
220 // 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
222 // follows:
223 // [0] index into codeTable of code object.
224 // [1] tick count (number of times this stack frame occured).
225 // [2] child node count
226 // Reading the trie is done by recursively reading the tree depth-first
227 // pre-order.
228 CodeTrieNode _processCodeTrie(List<int> data) {
229 // Setup state shared across calls to _readTrieNode.
230 _trieDataCursor = 0;
231 _trieData = data;
232 if (_trieData == null) {
233 return null;
234 }
235 if (_trieData.length < 3) {
236 // Not enough integers for 1 node.
237 return null;
238 }
239 // Read the tree, returns the root node.
240 return _readCodeTrieNode();
241 }
242
243 CodeTrieNode _readCodeTrieNode() {
244 // Read index into code table.
245 var index = _trieData[_trieDataCursor++];
246 // Lookup code object.
247 var code = codes[index];
248 // Frame counter.
249 var count = _trieData[_trieDataCursor++];
250 // Create node.
251 var node = new CodeTrieNode(code, count);
252 // Number of children.
253 var children = _trieData[_trieDataCursor++];
254 // Recursively read child nodes.
255 for (var i = 0; i < children; i++) {
256 var child = _readCodeTrieNode();
257 node.children.add(child);
258 }
259 return node;
260 }
261
262 FunctionTrieNode _processFunctionTrie(List<int> data) {
263 // Setup state shared across calls to _readTrieNode.
264 _trieDataCursor = 0;
265 _trieData = data;
266 if (_trieData == null) {
267 return null;
268 }
269 if (_trieData.length < 3) {
270 // Not enough integers for 1 node.
271 return null;
272 }
273 // Read the tree, returns the root node.
274 return _readFunctionTrieNode();
275 }
276
277 FunctionTrieNode _readFunctionTrieNode() {
278 // Read index into function table.
279 var index = _trieData[_trieDataCursor++];
280 // Lookup function object.
281 var function = functions[index];
282 // Frame counter.
283 var count = _trieData[_trieDataCursor++];
284 // Create node.
285 var node = new FunctionTrieNode(function, count);
286 // Number of code index / count pairs.
287 var codeCount = _trieData[_trieDataCursor++];
288 var totalCodeTicks = 0;
289 for (var i = 0; i < codeCount; i++) {
290 var codeIndex = _trieData[_trieDataCursor++];
291 var code = codes[codeIndex];
292 var codeTicks = _trieData[_trieDataCursor++];
293 totalCodeTicks += codeTicks;
294 var nodeCode = new FunctionTrieNodeCode(code, codeTicks);
295 node.codes.add(nodeCode);
296 }
297 node._totalCodeTicks = totalCodeTicks;
298 // Number of children.
299 var children = _trieData[_trieDataCursor++];
300 // Recursively read child nodes.
301 for (var i = 0; i < children; i++) {
302 var child = _readFunctionTrieNode();
303 node.children.add(child);
304 }
305 return node;
306 }
307
308 double approximateSecondsForCount(count) {
309 var MICROSECONDS_PER_SECOND = 1000000.0;
310 return (count * samplePeriod) / MICROSECONDS_PER_SECOND;
311 }
312 }
OLDNEW
« no previous file with comments | « runtime/observatory/lib/src/app/view_model.dart ('k') | runtime/observatory/lib/src/elements/class_ref.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698