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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: runtime/bin/vmservice/client/lib/src/observatory/model.dart
diff --git a/runtime/bin/vmservice/client/lib/src/observatory/model.dart b/runtime/bin/vmservice/client/lib/src/observatory/model.dart
index 9ecfbe97d4675d69d1ba2cb0ece822993cb0eac9..4a6f3e40d71d496f90da8e5caa6edddde25481b5 100644
--- a/runtime/bin/vmservice/client/lib/src/observatory/model.dart
+++ b/runtime/bin/vmservice/client/lib/src/observatory/model.dart
@@ -55,8 +55,15 @@ class CodeKind {
class CodeTick {
final int address;
- final int ticks;
- CodeTick(this.address, this.ticks);
+ final int exclusive_ticks;
+ final int inclusive_ticks;
+ CodeTick(this.address, this.exclusive_ticks, this.inclusive_ticks);
+}
+
+class CodeCallCount {
+ final Code code;
+ final int count;
+ CodeCallCount(this.code, this.count);
}
class Code extends Observable {
@@ -64,30 +71,143 @@ class Code extends Observable {
final int startAddress;
final int endAddress;
final List<CodeTick> ticks = [];
+ final List<CodeCallCount> callers = [];
+ final List<CodeCallCount> callees = [];
int inclusiveTicks = 0;
int exclusiveTicks = 0;
@observable final List<CodeInstruction> instructions = toObservable([]);
@observable Map functionRef = toObservable({});
@observable Map codeRef = toObservable({});
@observable String name;
- @observable String user_name;
+ @observable String userName;
Code(this.kind, this.name, this.startAddress, this.endAddress);
- Code.fromMap(Map m) :
+ Code.fromMap(Map map) :
kind = CodeKind.Dart,
- startAddress = int.parse(m['start'], radix:16),
- endAddress = int.parse(m['end'], radix:16) {
- functionRef = toObservable(m['function']);
- codeRef = {
+ startAddress = int.parse(map['start'], radix: 16),
+ endAddress = int.parse(map['end'], radix: 16) {
+ functionRef = toObservable(map['function']);
+ codeRef = toObservable({
'type': '@Code',
- 'id': m['id'],
- 'name': m['name'],
- 'user_name': m['user_name']
- };
- name = m['name'];
- user_name = m['user_name'];
- _loadInstructions(m['disassembly']);
+ 'id': map['id'],
+ 'name': map['name'],
+ 'user_name': map['user_name']
+ });
+ name = map['name'];
+ userName = map['user_name'];
+ if (map['disassembly'] != null) {
+ _loadInstructions(map['disassembly']);
+ }
+ }
+
+ factory Code.fromProfileMap(Map map) {
+ var kind = CodeKind.fromString(map['kind']);
+ var startAddress;
+ var endAddress;
+ var name;
+ var userName;
+ var codeRef;
+ var functionRef;
+ // Initial extraction of startAddress, endAddress, and name depends on what
+ // kind of code this is and whether or not the code has been collected.
+ if (kind == CodeKind.Dart) {
+ var code = map['code'];
+ if (code != null) {
+ // Extract from Dart code.
+ startAddress = int.parse(code['start'], radix:16);
+ endAddress = int.parse(code['end'], radix:16);
+ name = code['name'];
+ userName = code['user_name'];
+ codeRef = toObservable({
+ 'type': '@Code',
+ 'id': code['id'],
+ 'name': name,
+ 'user_name': userName
+ });
+ functionRef = toObservable(code['function']);
+ }
+ }
+ if (startAddress == null) {
+ // Extract from Profile code.
+ // This is either a native or collected piece of code.
+ startAddress = int.parse(map['start'], radix:16);
+ endAddress = int.parse(map['end'], radix: 16);
+ name = map['name'];
+ userName = name;
+ }
+ var code = new Code(kind, name, startAddress, endAddress);
+ code.codeRef = codeRef;
+ code.functionRef = functionRef;
+ code.userName = userName;
+ if (map['disassembly'] != null) {
+ code._loadInstructions(map['disassembly']);
+ }
+ return code;
+ }
+
+ // Refresh tick counts, etc for a code object.
+ void _refresh(Map map) {
+ inclusiveTicks = int.parse(map['inclusive_ticks']);
+ exclusiveTicks = int.parse(map['exclusive_ticks']);
+ // Load address ticks.
+ var ticksList = map['ticks'];
+ if ((ticksList != null) && (ticksList.length > 0)) {
+ assert((ticks.length % 3) == 0);
+ for (var i = 0; i < ticksList.length; i += 3) {
+ var address = int.parse(ticksList[i], radix:16);
+ var inclusive_ticks = int.parse(ticksList[i + 1]);
+ var exclusive_ticks = int.parse(ticksList[i + 2]);
+ var codeTick = new CodeTick(address, exclusive_ticks, inclusive_ticks);
+ ticks.add(codeTick);
+ }
+ }
+ }
+
+ /// Sum all caller counts.
+ int sumCallersCount() => _sumCallCount(callers);
+ /// Specific caller count.
+ int callersCount(Code code) => _callCount(callers, code);
+ /// Sum of callees count.
+ int sumCalleesCount() => _sumCallCount(callees);
+ /// Specific callee count.
+ int calleesCount(Code code) => _callCount(callees, code);
+
+ int _sumCallCount(List<CodeCallCount> calls) {
+ var sum = 0;
+ for (CodeCallCount caller in calls) {
+ sum += caller.count;
+ }
+ return sum;
+ }
+
+ int _callCount(List<CodeCallCount> calls, Code code) {
+ for (CodeCallCount caller in calls) {
+ if (caller.code == code) {
+ return caller.count;
+ }
+ }
+ return 0;
+ }
+
+ void resolveCalls(Map code, List<Code> codes) {
+ _resolveCalls(callers, code['callers'], codes);
+ _resolveCalls(callees, code['callees'], codes);
+ }
+
+ void _resolveCalls(List<CodeCallCount> calls, List data, List<Code> codes) {
+ // Clear.
+ calls.clear();
+ // Resolve.
+ for (var i = 0; i < data.length; i += 2) {
+ var index = int.parse(data[i]);
+ var count = int.parse(data[i + 1]);
+ assert(index >= 0);
+ assert(index < codes.length);
+ calls.add(new CodeCallCount(codes[index], count));
+ }
+ // Sort to descending count order.
+ calls.sort((a, b) => b.count - a.count);
}
/// Resets all tick counts to 0.
@@ -136,12 +256,16 @@ class Code extends Observable {
class Profile {
final Isolate isolate;
+ final List<Code> _codeObjectsInImportOrder = new List<Code>();
+ int totalSamples = 0;
+
Profile.fromMap(this.isolate, Map m) {
var codes = m['codes'];
totalSamples = m['samples'];
Logger.root.info('Creating profile from ${totalSamples} samples '
'and ${codes.length} code objects.');
isolate.resetCodeTicks();
+ _codeObjectsInImportOrder.clear();
codes.forEach((code) {
try {
_processCode(code);
@@ -149,77 +273,39 @@ class Profile {
Logger.root.warning('Error processing code object. $e $st', e, st);
}
});
- }
- int totalSamples = 0;
-
- Code _processDartCode(Map dartCode) {
- var codeObject = dartCode['code'];
- if ((codeObject == null)) {
- // Detached code objects are handled like 'other' code.
- return _processOtherCode(CodeKind.Dart, dartCode);
+ // Now that code objects have been loaded, post-process them
+ // and resolve callers and callees.
+ assert(_codeObjectsInImportOrder.length == codes.length);
+ for (var i = 0; i < codes.length; i++) {
+ Code code = _codeObjectsInImportOrder[i];
+ code.resolveCalls(codes[i], _codeObjectsInImportOrder);
}
- var code = new Code.fromMap(codeObject);
- return code;
+ _codeObjectsInImportOrder.clear();
}
- Code _processOtherCode(CodeKind kind, Map otherCode) {
- var startAddress = int.parse(otherCode['start'], radix:16);
- var endAddress = int.parse(otherCode['end'], radix: 16);
- var name = otherCode['name'];
- assert(name != null);
- return new Code(kind, name, startAddress, endAddress);
+ int _extractCodeStartAddress(Map code) {
+ var kind = CodeKind.fromString(code['kind']);
+ if ((kind == CodeKind.Dart) && (code['code'] != null)) {
+ // Start address is inside the dart code map.
+ return int.parse(code['code']['start'], radix:16);
+ }
+ // Start address is inside the profile code map.
+ return int.parse(code['start'], radix:16);
}
void _processCode(Map profileCode) {
if (profileCode['type'] != 'ProfileCode') {
return;
}
- var kind = CodeKind.fromString(profileCode['kind']);
- var address;
- if (kind == CodeKind.Dart) {
- if (profileCode['code'] != null) {
- address = int.parse(profileCode['code']['start'], radix:16);
- } else {
- address = int.parse(profileCode['start'], radix:16);
- }
- } else {
- address = int.parse(profileCode['start'], radix:16);
- }
- assert(address != null);
+ int address = _extractCodeStartAddress(profileCode);
var code = isolate.findCodeByAddress(address);
if (code == null) {
- if (kind == CodeKind.Dart) {
- code = _processDartCode(profileCode);
- } else {
- code = _processOtherCode(kind, profileCode);
- }
- assert(code != null);
+ // Never seen a code object at this address before, create a new one.
+ code = new Code.fromProfileMap(profileCode);
isolate.codes.add(code);
}
- // Load code object tick counts and set them.
- var inclusive = int.parse(profileCode['inclusive_ticks']);
- var exclusive = int.parse(profileCode['exclusive_ticks']);
- code.inclusiveTicks = inclusive;
- code.exclusiveTicks = exclusive;
- // Load address specific ticks.
- List ticksList = profileCode['ticks'];
- if (ticksList != null && (ticksList.length > 0)) {
- for (var i = 0; i < ticksList.length; i += 2) {
- var address = int.parse(ticksList[i], radix:16);
- var ticks = int.parse(ticksList[i + 1]);
- var codeTick = new CodeTick(address, ticks);
- code.ticks.add(codeTick);
- }
- }
- if ((code.ticks.length > 0) && (code.instructions.length > 0)) {
- // Apply address ticks to instruction stream.
- code.ticks.forEach((CodeTick tick) {
- code.tick(tick.address, tick.ticks);
- });
- code.instructions.forEach((i) {
- i.updateTickString(code);
- });
- }
+ code._refresh(profileCode);
+ _codeObjectsInImportOrder.add(code);
}
List<Code> topExclusive(int count) {
@@ -232,17 +318,6 @@ class Profile {
}
return exclusive.sublist(0, count);
}
-
- List<Code> topInclusive(int count) {
- List<Code> inclusive = isolate.codes;
- inclusive.sort((Code a, Code b) {
- return b.inclusiveTicks - a.inclusiveTicks;
- });
- if ((inclusive.length < count) || (count == 0)) {
- return inclusive;
- }
- return inclusive.sublist(0, count);
- }
}
class ScriptLine extends Observable {

Powered by Google App Engine
This is Rietveld 408576698