Chromium Code Reviews| 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..01c74207a6187adb80da7de524856687196ad337 100644 |
| --- a/runtime/bin/vmservice/client/lib/src/observatory/model.dart |
| +++ b/runtime/bin/vmservice/client/lib/src/observatory/model.dart |
| @@ -55,8 +55,14 @@ 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 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.
|
| + var code_or_index; |
| + int count; |
| } |
| class Code extends Observable { |
| @@ -64,6 +70,8 @@ class Code extends Observable { |
| final int startAddress; |
| final int endAddress; |
| final List<CodeTick> ticks = []; |
| + final List<CodeCaller> callers = []; |
| + final List<CodeCaller> callees = []; |
| int inclusiveTicks = 0; |
| int exclusiveTicks = 0; |
| @observable final List<CodeInstruction> instructions = toObservable([]); |
| @@ -74,6 +82,28 @@ class Code extends Observable { |
| Code(this.kind, this.name, this.startAddress, this.endAddress); |
| + int sumCallersCount() => _sumCallCount(callers); |
| + int callersCount(Code code) => _individualCallCount(callers, code); |
| + int sumCalleesCount() => _sumCallCount(callees); |
| + 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.
|
| + |
| + int _sumCallCount(List<CodeCaller> calls) { |
| + var sum = 0; |
| + for (CodeCaller caller in calls) { |
| + sum += caller.count; |
| + } |
| + return sum; |
| + } |
| + |
| + 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.
|
| + for (CodeCaller caller in calls) { |
| + if (caller.code_or_index == code) { |
| + return caller.count; |
| + } |
| + } |
| + return 0; |
| + } |
| + |
| Code.fromMap(Map m) : |
| kind = CodeKind.Dart, |
| startAddress = int.parse(m['start'], radix:16), |
| @@ -87,7 +117,9 @@ class Code extends Observable { |
| }; |
| name = m['name']; |
| user_name = m['user_name']; |
| - _loadInstructions(m['disassembly']); |
| + if (m['disassembly'] != null) { |
| + _loadInstructions(m['disassembly']); |
| + } |
| } |
| /// Resets all tick counts to 0. |
| @@ -136,12 +168,14 @@ class Code extends Observable { |
| class Profile { |
| final Isolate isolate; |
| + final List<Code> _codeObjectsInImportOrder = new List<Code>(); |
| 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,9 +183,36 @@ class Profile { |
| Logger.root.warning('Error processing code object. $e $st', e, st); |
| } |
| }); |
| + 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.
|
| + for (var i = 0; i < codes.length; i++) { |
| + Code codeModel = _codeObjectsInImportOrder[i]; |
| + Map codeService = codes[i]; |
|
turnidge
2014/02/24 20:13:00
codeService sounds like a service that returns cod
|
| + _loadCallData(codeModel.callers, codeService['callers']); |
|
turnidge
2014/02/24 20:13:00
Would this work as an assignment?
codeModel.calle
|
| + _loadCallData(codeModel.callees, codeService['callees']); |
| + } |
| } |
| int totalSamples = 0; |
| + 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.
|
| + calls.clear(); |
| + // Do the initial load of the data. |
| + for (var i = 0; i < data.length; i += 2) { |
| + var codeCaller = new CodeCaller(); |
| + codeCaller.code_or_index = int.parse(data[i]); |
| + codeCaller.count = int.parse(data[i + 1]); |
| + calls.add(codeCaller); |
| + } |
| + // Replace indexes with actual code objects. |
| + for (var codeCaller in calls) { |
| + var index = codeCaller.code_or_index; |
| + assert(index >= 0); |
| + assert(index < _codeObjectsInImportOrder.length); |
| + 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.
|
| + } |
| + // Sort. |
| + calls.sort((a, b) => b.count - a.count); |
| + } |
| + |
| Code _processDartCode(Map dartCode) { |
| var codeObject = dartCode['code']; |
| if ((codeObject == null)) { |
| @@ -196,6 +257,7 @@ class Profile { |
| assert(code != null); |
| isolate.codes.add(code); |
| } |
| + _codeObjectsInImportOrder.add(code); |
| // Load code object tick counts and set them. |
| var inclusive = int.parse(profileCode['inclusive_ticks']); |
| var exclusive = int.parse(profileCode['exclusive_ticks']); |
| @@ -204,17 +266,19 @@ class Profile { |
| // Load address specific ticks. |
| List ticksList = profileCode['ticks']; |
| if (ticksList != null && (ticksList.length > 0)) { |
| - for (var i = 0; i < ticksList.length; i += 2) { |
| + assert((ticksList.length % 3) == 0); |
| + for (var i = 0; i < ticksList.length; i += 3) { |
| var address = int.parse(ticksList[i], radix:16); |
| - var ticks = int.parse(ticksList[i + 1]); |
| - var codeTick = new CodeTick(address, ticks); |
| + 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); |
| 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.tick(tick.address, tick.inclusive_ticks); |
| }); |
| code.instructions.forEach((i) { |
| i.updateTickString(code); |
| @@ -232,17 +296,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 { |