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

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

Issue 135843006: Improve Code object support in service and observatory (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 11 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) 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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of observatory;
6
7 class CodeInstruction extends Observable {
8 @observable final int address;
9 @observable final String machine;
10 @observable final String human;
11 @observable int ticks = 0;
12 @observable String formattedTicks = '';
13 @observable String formattedAddress() {
14 return '0x${address.toRadixString(16)}';
15 }
16 CodeInstruction(this.address, this.machine, this.human);
17 void updateTickString(Code code) {
18 formattedTicks = '';
19 if ((code == null) || (code.inclusiveTicks == 0)) {
20 return;
21 }
22 double percent = (ticks / code.inclusiveTicks) * 100.0;
23 if (percent <= 0.00) {
24 return;
25 }
26 formattedTicks = percent.toStringAsFixed(2);
turnidge 2014/01/17 19:30:21 Is it important to cache the formattedTicks? Woul
Cutch 2014/01/17 21:15:42 I only cache the percentage now (and only if it's
27 }
28 }
29
30 class CodeKind {
31 final _value;
32 const CodeKind._internal(this._value);
33 String toString() => 'CodeKind.$_value';
34
35 static CodeKind fromString(String s) {
36 if (s == 'Native') {
37 return Native;
38 } else if (s == 'Dart') {
39 return Dart;
40 } else if (s == 'Collected') {
41 return Collected;
42 }
43 throw new FallThroughError();
44 }
45 static const Native = const CodeKind._internal('Native');
46 static const Dart = const CodeKind._internal('Dart');
47 static const Collected = const CodeKind._internal('Collected');
48 }
49
50 class CodeTick {
51 final int address;
52 final int ticks;
53 CodeTick(this.address, this.ticks);
54 }
55
56 class Code extends Observable {
57 final CodeKind kind;
58 final int startAddress;
59 final int endAddress;
60 final List<CodeTick> ticks = [];
61 int inclusiveTicks = 0;
62 int exclusiveTicks = 0;
63 @observable final List<CodeInstruction> instructions = toObservable([]);
64 @observable Map functionRef = toObservable({});
65 @observable Map codeRef = toObservable({});
66 @observable String name;
67 @observable String user_name;
68
69 Code(this.kind, this.name, this.startAddress, this.endAddress);
70
71 Code.fromMap(Map m) :
72 kind = CodeKind.Dart,
73 startAddress = int.parse(m['start'], radix:16),
74 endAddress = int.parse(m['end'], radix:16) {
75 functionRef = toObservable(m['function']);
76 codeRef = {
77 'type': '@Code',
78 'id': m['id'],
79 'name': m['name'],
80 'user_name': m['user_name']
81 };
82 name = m['name'];
83 user_name = m['user_name'];
84 _loadInstructions(m['disassembly']);
85 }
86
87 /// Resets all tick counts to 0.
88 void resetTicks() {
89 inclusiveTicks = 0;
90 exclusiveTicks = 0;
91 ticks.clear();
92 for (var i = 0; i < instructions.length; i++) {
turnidge 2014/01/17 19:30:21 does this work instead of using an index to iterat
Cutch 2014/01/17 21:15:42 Done.
93 var instruction = instructions[i];
94 instruction.ticks = 0;
95 }
96 }
97
98 /// Adds [count] to the tick count for the instruction at [address].
99 void tick(int address, int count) {
100 for (var i = 0; i < instructions.length; i++) {
101 var instruction = instructions[i];
102 if (instruction.address == address) {
103 instruction.ticks += count;
104 return;
105 }
106 }
107 }
108
109 /// Clears [instructions] and then adds all instructions from
110 /// [instructionList].
111 void _loadInstructions(List instructionList) {
112 if (instructionList == null) {
turnidge 2014/01/17 19:30:21 Does this happen?
Cutch 2014/01/17 21:15:42 Done.
113 return;
114 }
115 instructions.clear();
116 // Load disassembly into code object.
117 for (int i = 0; i < instructionList.length; i += 3) {
118 if (instructionList[i] == '') {
119 // Code comment.
120 // TODO(johnmccutchan): Insert code comments into instructions.
121 continue;
122 }
123 var address = int.parse(instructionList[i]);
124 var machine = instructionList[i + 1];
125 var human = instructionList[i + 2];
126 instructions.add(new CodeInstruction(address, machine, human));
127 }
128 }
129
130 /// returns true if [address] is inside the address range.
131 bool contains(int address) {
132 return (address >= startAddress) && (address < endAddress);
133 }
134 }
135
136 class Profile {
137 final Isolate isolate;
138 Profile.fromMap(this.isolate, Map m) {
139 var codes = m['codes'];
140 totalSamples = m['samples'];
141 Logger.root.info('Creating profile from ${totalSamples} samples '
142 'and ${codes.length} code objects.');
143 isolate.resetCodeTicks();
144 codes.forEach((code) {
145 try {
146 _processCode(code);
147 } catch (e, st) {
148 Logger.root.warning('Error processing code object.', e, st);
149 }
150 });
151 }
152 int totalSamples = 0;
153
154 Code _processDartCode(Map dartCode) {
155 var codeObject = dartCode['code'];
156 if ((codeObject == null)) {
157 // Detached code objects are handled like 'other' code.
158 return _processOtherCode(CodeKind.Dart, dartCode);
159 }
160 var code = new Code.fromMap(codeObject);
161 return code;
162 }
163
164 Code _processOtherCode(CodeKind kind, Map otherCode) {
165 var startAddress = int.parse(otherCode['start'], radix:16);
166 var endAddress = int.parse(otherCode['end'], radix: 16);
167 var name = otherCode['name'];
168 assert(name != null);
169 return new Code(kind, name, startAddress, endAddress);
170 }
171
172 void _processCode(Map profileCode) {
173 if (profileCode['type'] != 'ProfileCode') {
174 return;
175 }
176 var kind = CodeKind.fromString(profileCode['kind']);
177 var address;
178 if (kind == CodeKind.Dart) {
179 address = int.parse(profileCode['code']['start'], radix:16);
180 } else {
181 address = int.parse(profileCode['start'], radix:16);
182 }
183 var code = isolate.findCodeByAddress(address);
184 if (code == null) {
185 if (kind == CodeKind.Dart) {
186 code = _processDartCode(profileCode);
187 } else {
188 code = _processOtherCode(kind, profileCode);
189 }
190 assert(code != null);
191 Logger.root.info(
192 'Added code with 0x${address.toRadixString(16)} to isolate.');
193 isolate.codes.add(code);
194 }
195 // Load code object tick counts and set them.
196 var inclusive = int.parse(profileCode['inclusive_ticks']);
197 var exclusive = int.parse(profileCode['exclusive_ticks']);
198 code.inclusiveTicks = inclusive;
199 code.exclusiveTicks = exclusive;
200 // Load address specific ticks.
201 List ticksList = profileCode['ticks'];
202 if (ticksList != null && (ticksList.length > 0)) {
203 for (var i = 0; i < ticksList.length; i += 2) {
204 var address = int.parse(ticksList[i], radix:16);
205 var ticks = int.parse(ticksList[i + 1]);
206 var codeTick = new CodeTick(address, ticks);
207 code.ticks.add(codeTick);
208 }
209 }
210 if ((code.ticks.length > 0) && (code.instructions.length > 0)) {
211 // Apply address ticks to instruction stream.
212 code.ticks.forEach((CodeTick tick) {
213 code.tick(tick.address, tick.ticks);
214 });
215 code.instructions.forEach((i) {
216 i.updateTickString(code);
217 });
218 }
219 }
220
221
222
turnidge 2014/01/17 19:30:21 Too many blank lines?
Cutch 2014/01/17 21:15:42 Done.
223 List<Code> topExclusive(int N) {
turnidge 2014/01/17 19:30:21 N uses a non-standard variable casing. Consider "
Cutch 2014/01/17 21:15:42 Done.
224 List<Code> exclusive = isolate.codes;
225 exclusive.sort((Code a, Code b) {
226 return b.exclusiveTicks - a.exclusiveTicks;
227 });
228 if ((exclusive.length < N) || (N == 0)) {
229 return exclusive;
230 }
231 return exclusive.sublist(0, N);
232 }
233
234 List<Code> topInclusive(int N) {
235 List<Code> inclusive = isolate.codes;
236 inclusive.sort((Code a, Code b) {
237 return b.inclusiveTicks - a.inclusiveTicks;
238 });
239 if ((inclusive.length < N) || (N == 0)) {
240 return inclusive;
241 }
242 return inclusive.sublist(0, N);
243 }
244 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698