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

Side by Side Diff: runtime/bin/vmservice/client/lib/src/observatory/model.dart

Issue 168833005: Add callers and callees to profiler output (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 observatory; 5 part of observatory;
6 6
7 class CodeInstruction extends Observable { 7 class CodeInstruction extends Observable {
8 @observable final int address; 8 @observable final int address;
9 @observable final String machine; 9 @observable final String machine;
10 @observable final String human; 10 @observable final String human;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 } 48 }
49 throw new FallThroughError(); 49 throw new FallThroughError();
50 } 50 }
51 static const Native = const CodeKind._internal('Native'); 51 static const Native = const CodeKind._internal('Native');
52 static const Dart = const CodeKind._internal('Dart'); 52 static const Dart = const CodeKind._internal('Dart');
53 static const Collected = const CodeKind._internal('Collected'); 53 static const Collected = const CodeKind._internal('Collected');
54 } 54 }
55 55
56 class CodeTick { 56 class CodeTick {
57 final int address; 57 final int address;
58 final int ticks; 58 final int exclusive_ticks;
59 CodeTick(this.address, this.ticks); 59 final int inclusive_ticks;
60 CodeTick(this.address, this.exclusive_ticks, this.inclusive_ticks);
61 }
62
63 class CodeCaller {
turnidge 2014/02/24 20:13:00 This isn't necessarily a caller, right? It can be
Cutch 2014/02/25 16:44:47 Done.
64 var code_or_index;
65 int count;
60 } 66 }
61 67
62 class Code extends Observable { 68 class Code extends Observable {
63 final CodeKind kind; 69 final CodeKind kind;
64 final int startAddress; 70 final int startAddress;
65 final int endAddress; 71 final int endAddress;
66 final List<CodeTick> ticks = []; 72 final List<CodeTick> ticks = [];
73 final List<CodeCaller> callers = [];
74 final List<CodeCaller> callees = [];
67 int inclusiveTicks = 0; 75 int inclusiveTicks = 0;
68 int exclusiveTicks = 0; 76 int exclusiveTicks = 0;
69 @observable final List<CodeInstruction> instructions = toObservable([]); 77 @observable final List<CodeInstruction> instructions = toObservable([]);
70 @observable Map functionRef = toObservable({}); 78 @observable Map functionRef = toObservable({});
71 @observable Map codeRef = toObservable({}); 79 @observable Map codeRef = toObservable({});
72 @observable String name; 80 @observable String name;
73 @observable String user_name; 81 @observable String user_name;
74 82
75 Code(this.kind, this.name, this.startAddress, this.endAddress); 83 Code(this.kind, this.name, this.startAddress, this.endAddress);
76 84
85 int sumCallersCount() => _sumCallCount(callers);
86 int callersCount(Code code) => _individualCallCount(callers, code);
87 int sumCalleesCount() => _sumCallCount(callees);
88 int calleesCount(Code code) => _individualCallCount(callees, code);
turnidge 2014/02/24 20:13:00 Maybe add simple comments.
Cutch 2014/02/25 16:44:47 Done.
89
90 int _sumCallCount(List<CodeCaller> calls) {
91 var sum = 0;
92 for (CodeCaller caller in calls) {
93 sum += caller.count;
94 }
95 return sum;
96 }
97
98 int _individualCallCount(List<CodeCaller> calls, Code code) {
turnidge 2014/02/24 20:13:00 Maybe just _callCount?
Cutch 2014/02/25 16:44:47 Done.
99 for (CodeCaller caller in calls) {
100 if (caller.code_or_index == code) {
101 return caller.count;
102 }
103 }
104 return 0;
105 }
106
77 Code.fromMap(Map m) : 107 Code.fromMap(Map m) :
78 kind = CodeKind.Dart, 108 kind = CodeKind.Dart,
79 startAddress = int.parse(m['start'], radix:16), 109 startAddress = int.parse(m['start'], radix:16),
80 endAddress = int.parse(m['end'], radix:16) { 110 endAddress = int.parse(m['end'], radix:16) {
81 functionRef = toObservable(m['function']); 111 functionRef = toObservable(m['function']);
82 codeRef = { 112 codeRef = {
83 'type': '@Code', 113 'type': '@Code',
84 'id': m['id'], 114 'id': m['id'],
85 'name': m['name'], 115 'name': m['name'],
86 'user_name': m['user_name'] 116 'user_name': m['user_name']
87 }; 117 };
88 name = m['name']; 118 name = m['name'];
89 user_name = m['user_name']; 119 user_name = m['user_name'];
90 _loadInstructions(m['disassembly']); 120 if (m['disassembly'] != null) {
121 _loadInstructions(m['disassembly']);
122 }
91 } 123 }
92 124
93 /// Resets all tick counts to 0. 125 /// Resets all tick counts to 0.
94 void resetTicks() { 126 void resetTicks() {
95 inclusiveTicks = 0; 127 inclusiveTicks = 0;
96 exclusiveTicks = 0; 128 exclusiveTicks = 0;
97 ticks.clear(); 129 ticks.clear();
98 for (var instruction in instructions) { 130 for (var instruction in instructions) {
99 instruction.ticks = 0; 131 instruction.ticks = 0;
100 } 132 }
(...skipping 28 matching lines...) Expand all
129 } 161 }
130 162
131 /// returns true if [address] is inside the address range. 163 /// returns true if [address] is inside the address range.
132 bool contains(int address) { 164 bool contains(int address) {
133 return (address >= startAddress) && (address < endAddress); 165 return (address >= startAddress) && (address < endAddress);
134 } 166 }
135 } 167 }
136 168
137 class Profile { 169 class Profile {
138 final Isolate isolate; 170 final Isolate isolate;
171 final List<Code> _codeObjectsInImportOrder = new List<Code>();
139 Profile.fromMap(this.isolate, Map m) { 172 Profile.fromMap(this.isolate, Map m) {
140 var codes = m['codes']; 173 var codes = m['codes'];
141 totalSamples = m['samples']; 174 totalSamples = m['samples'];
142 Logger.root.info('Creating profile from ${totalSamples} samples ' 175 Logger.root.info('Creating profile from ${totalSamples} samples '
143 'and ${codes.length} code objects.'); 176 'and ${codes.length} code objects.');
144 isolate.resetCodeTicks(); 177 isolate.resetCodeTicks();
178 _codeObjectsInImportOrder.clear();
145 codes.forEach((code) { 179 codes.forEach((code) {
146 try { 180 try {
147 _processCode(code); 181 _processCode(code);
148 } catch (e, st) { 182 } catch (e, st) {
149 Logger.root.warning('Error processing code object. $e $st', e, st); 183 Logger.root.warning('Error processing code object. $e $st', e, st);
150 } 184 }
151 }); 185 });
186 assert(_codeObjectsInImportOrder.length == codes.length);
turnidge 2014/02/24 20:13:00 Maybe a comment here, along the lines of: "Once a
Cutch 2014/02/25 16:44:47 Done.
187 for (var i = 0; i < codes.length; i++) {
188 Code codeModel = _codeObjectsInImportOrder[i];
189 Map codeService = codes[i];
turnidge 2014/02/24 20:13:00 codeService sounds like a service that returns cod
190 _loadCallData(codeModel.callers, codeService['callers']);
turnidge 2014/02/24 20:13:00 Would this work as an assignment? codeModel.calle
191 _loadCallData(codeModel.callees, codeService['callees']);
192 }
152 } 193 }
153 int totalSamples = 0; 194 int totalSamples = 0;
154 195
196 void _loadCallData(List<CodeCaller> calls, List data) {
turnidge 2014/02/24 20:13:00 How about a different name? Maybe "_resolveCalls"
Cutch 2014/02/25 16:44:47 Done.
197 calls.clear();
198 // Do the initial load of the data.
199 for (var i = 0; i < data.length; i += 2) {
200 var codeCaller = new CodeCaller();
201 codeCaller.code_or_index = int.parse(data[i]);
202 codeCaller.count = int.parse(data[i + 1]);
203 calls.add(codeCaller);
204 }
205 // Replace indexes with actual code objects.
206 for (var codeCaller in calls) {
207 var index = codeCaller.code_or_index;
208 assert(index >= 0);
209 assert(index < _codeObjectsInImportOrder.length);
210 codeCaller.code_or_index = _codeObjectsInImportOrder[index];
turnidge 2014/02/24 20:13:00 Do you need this second loop? Why not resolve the
Cutch 2014/02/25 16:44:47 Done.
211 }
212 // Sort.
213 calls.sort((a, b) => b.count - a.count);
214 }
215
155 Code _processDartCode(Map dartCode) { 216 Code _processDartCode(Map dartCode) {
156 var codeObject = dartCode['code']; 217 var codeObject = dartCode['code'];
157 if ((codeObject == null)) { 218 if ((codeObject == null)) {
158 // Detached code objects are handled like 'other' code. 219 // Detached code objects are handled like 'other' code.
159 return _processOtherCode(CodeKind.Dart, dartCode); 220 return _processOtherCode(CodeKind.Dart, dartCode);
160 } 221 }
161 var code = new Code.fromMap(codeObject); 222 var code = new Code.fromMap(codeObject);
162 return code; 223 return code;
163 } 224 }
164 225
(...skipping 24 matching lines...) Expand all
189 var code = isolate.findCodeByAddress(address); 250 var code = isolate.findCodeByAddress(address);
190 if (code == null) { 251 if (code == null) {
191 if (kind == CodeKind.Dart) { 252 if (kind == CodeKind.Dart) {
192 code = _processDartCode(profileCode); 253 code = _processDartCode(profileCode);
193 } else { 254 } else {
194 code = _processOtherCode(kind, profileCode); 255 code = _processOtherCode(kind, profileCode);
195 } 256 }
196 assert(code != null); 257 assert(code != null);
197 isolate.codes.add(code); 258 isolate.codes.add(code);
198 } 259 }
260 _codeObjectsInImportOrder.add(code);
199 // Load code object tick counts and set them. 261 // Load code object tick counts and set them.
200 var inclusive = int.parse(profileCode['inclusive_ticks']); 262 var inclusive = int.parse(profileCode['inclusive_ticks']);
201 var exclusive = int.parse(profileCode['exclusive_ticks']); 263 var exclusive = int.parse(profileCode['exclusive_ticks']);
202 code.inclusiveTicks = inclusive; 264 code.inclusiveTicks = inclusive;
203 code.exclusiveTicks = exclusive; 265 code.exclusiveTicks = exclusive;
204 // Load address specific ticks. 266 // Load address specific ticks.
205 List ticksList = profileCode['ticks']; 267 List ticksList = profileCode['ticks'];
206 if (ticksList != null && (ticksList.length > 0)) { 268 if (ticksList != null && (ticksList.length > 0)) {
207 for (var i = 0; i < ticksList.length; i += 2) { 269 assert((ticksList.length % 3) == 0);
270 for (var i = 0; i < ticksList.length; i += 3) {
208 var address = int.parse(ticksList[i], radix:16); 271 var address = int.parse(ticksList[i], radix:16);
209 var ticks = int.parse(ticksList[i + 1]); 272 var inclusive_ticks = int.parse(ticksList[i + 1]);
210 var codeTick = new CodeTick(address, ticks); 273 var exclusive_ticks = int.parse(ticksList[i + 2]);
274 var codeTick = new CodeTick(address, exclusive_ticks, inclusive_ticks);
211 code.ticks.add(codeTick); 275 code.ticks.add(codeTick);
212 } 276 }
213 } 277 }
214 if ((code.ticks.length > 0) && (code.instructions.length > 0)) { 278 if ((code.ticks.length > 0) && (code.instructions.length > 0)) {
215 // Apply address ticks to instruction stream. 279 // Apply address ticks to instruction stream.
216 code.ticks.forEach((CodeTick tick) { 280 code.ticks.forEach((CodeTick tick) {
217 code.tick(tick.address, tick.ticks); 281 code.tick(tick.address, tick.inclusive_ticks);
218 }); 282 });
219 code.instructions.forEach((i) { 283 code.instructions.forEach((i) {
220 i.updateTickString(code); 284 i.updateTickString(code);
221 }); 285 });
222 } 286 }
223 } 287 }
224 288
225 List<Code> topExclusive(int count) { 289 List<Code> topExclusive(int count) {
226 List<Code> exclusive = isolate.codes; 290 List<Code> exclusive = isolate.codes;
227 exclusive.sort((Code a, Code b) { 291 exclusive.sort((Code a, Code b) {
228 return b.exclusiveTicks - a.exclusiveTicks; 292 return b.exclusiveTicks - a.exclusiveTicks;
229 }); 293 });
230 if ((exclusive.length < count) || (count == 0)) { 294 if ((exclusive.length < count) || (count == 0)) {
231 return exclusive; 295 return exclusive;
232 } 296 }
233 return exclusive.sublist(0, count); 297 return exclusive.sublist(0, count);
234 } 298 }
235
236 List<Code> topInclusive(int count) {
237 List<Code> inclusive = isolate.codes;
238 inclusive.sort((Code a, Code b) {
239 return b.inclusiveTicks - a.inclusiveTicks;
240 });
241 if ((inclusive.length < count) || (count == 0)) {
242 return inclusive;
243 }
244 return inclusive.sublist(0, count);
245 }
246 } 299 }
247 300
248 class ScriptLine extends Observable { 301 class ScriptLine extends Observable {
249 @observable final int line; 302 @observable final int line;
250 @observable int hits = -1; 303 @observable int hits = -1;
251 @observable String text = ''; 304 @observable String text = '';
252 /// Is this a line of executable code? 305 /// Is this a line of executable code?
253 bool get executable => hits >= 0; 306 bool get executable => hits >= 0;
254 /// Has this line executed before? 307 /// Has this line executed before?
255 bool get covered => hits > 0; 308 bool get covered => hits > 0;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 if (executableLines == 0) { 391 if (executableLines == 0) {
339 return 0.0; 392 return 0.0;
340 } 393 }
341 return (coveredLines / executableLines) * 100.0; 394 return (coveredLines / executableLines) * 100.0;
342 } 395 }
343 396
344 @observable String coveredPercentageFormatted() { 397 @observable String coveredPercentageFormatted() {
345 return '(' + coveredPercentage().toStringAsFixed(1) + '% covered)'; 398 return '(' + coveredPercentage().toStringAsFixed(1) + '% covered)';
346 } 399 }
347 } 400 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698