| Index: runtime/bin/vmservice/client/lib/src/observatory_elements/heap_profile.dart
|
| diff --git a/runtime/bin/vmservice/client/lib/src/observatory_elements/heap_profile.dart b/runtime/bin/vmservice/client/lib/src/observatory_elements/heap_profile.dart
|
| index 15eb2d609e3d04403240bd165fdc8898082e63c5..db78b94e3f0abf4a7123a01b975d45c49346fab9 100644
|
| --- a/runtime/bin/vmservice/client/lib/src/observatory_elements/heap_profile.dart
|
| +++ b/runtime/bin/vmservice/client/lib/src/observatory_elements/heap_profile.dart
|
| @@ -4,6 +4,7 @@
|
|
|
| library heap_profile_element;
|
|
|
| +import 'dart:async';
|
| import 'dart:html';
|
| import 'package:logging/logging.dart';
|
| import 'package:polymer/polymer.dart';
|
| @@ -20,26 +21,98 @@ class HeapProfileElement extends ObservatoryElement {
|
| static const ALLOCATED_SINCE_GC = 4;
|
| static const ALLOCATED_SINCE_GC_SIZE = 5;
|
|
|
| + var _newPieDataTable;
|
| + var _newPieChart;
|
| +
|
| + var _oldPieDataTable;
|
| + var _oldPieChart;
|
| +
|
| + var _tableDataTable;
|
| + var _tableChart;
|
| +
|
| @published Map profile;
|
| - @published List sortedProfile;
|
| - int _sortColumnIndex = 1;
|
| - HeapProfileElement.created() : super.created();
|
| -
|
| - // Display columns.
|
| - @observable final List<String> columns = [
|
| - 'Class',
|
| - 'Current (new)',
|
| - 'Allocated Since GC (new)',
|
| - 'Total before GC (new)',
|
| - 'Survivors (new)',
|
| - 'Current (old)',
|
| - 'Allocated Since GC (old)',
|
| - 'Total before GC (old)',
|
| - 'Survivors (old)',
|
| - ];
|
| +
|
| + HeapProfileElement.created() : super.created() {
|
| + _tableDataTable = new DataTable();
|
| + _tableDataTable.addColumn('string', 'Class');
|
| + _tableDataTable.addColumn('number', 'Current (new)');
|
| + _tableDataTable.addColumn('number', 'Allocated Since GC (new)');
|
| + _tableDataTable.addColumn('number', 'Total before GC (new)');
|
| + _tableDataTable.addColumn('number', 'Survivors (new)');
|
| + _tableDataTable.addColumn('number', 'Current (old)');
|
| + _tableDataTable.addColumn('number', 'Allocated Since GC (old)');
|
| + _tableDataTable.addColumn('number', 'Total before GC (old)');
|
| + _tableDataTable.addColumn('number', 'Survivors (old)');
|
| + _newPieDataTable = new DataTable();
|
| + _newPieDataTable.addColumn('string', 'Type');
|
| + _newPieDataTable.addColumn('number', 'Size');
|
| + _oldPieDataTable = new DataTable();
|
| + _oldPieDataTable.addColumn('string', 'Type');
|
| + _oldPieDataTable.addColumn('number', 'Size');
|
| + }
|
| +
|
| + void enteredView() {
|
| + super.enteredView();
|
| + _tableChart = new Chart('Table',
|
| + shadowRoot.querySelector('#table'));
|
| + _tableChart.options['allowHtml'] = true;
|
| + _tableChart.options['sortColumn'] = 1;
|
| + _tableChart.options['sortAscending'] = false;
|
| + _newPieChart = new Chart('PieChart',
|
| + shadowRoot.querySelector('#newPieChart'));
|
| + _newPieChart.options['title'] = 'New Space';
|
| + _oldPieChart = new Chart('PieChart',
|
| + shadowRoot.querySelector('#oldPieChart'));
|
| + _oldPieChart.options['title'] = 'Old Space';
|
| + _draw();
|
| + }
|
| +
|
| + bool _first = true;
|
| +
|
| + void _updateChartData() {
|
| + if ((profile == null) || (profile['members'] is! List) ||
|
| + (profile['members'].length == 0)) {
|
| + return;
|
| + }
|
| + assert(_tableDataTable != null);
|
| + _tableDataTable.clearRows();
|
| + for (Map cls in profile['members']) {
|
| + var url =
|
| + app.locationManager.currentIsolateRelativeLink(cls['class']['id']);
|
| + _tableDataTable.addRow(
|
| + ['<a href="$url">${_columnValue(cls, 0)}</a>',
|
| + _columnValue(cls, 1),
|
| + _columnValue(cls, 2),
|
| + _columnValue(cls, 3),
|
| + _columnValue(cls, 4),
|
| + _columnValue(cls, 5),
|
| + _columnValue(cls, 6),
|
| + _columnValue(cls, 7),
|
| + _columnValue(cls, 8)]);
|
| + }
|
| + _newPieDataTable.clearRows();
|
| + var heap = profile['heaps']['new'];
|
| + _newPieDataTable.addRow(['Used', heap['used']]);
|
| + _newPieDataTable.addRow(['Free', heap['capacity'] - heap['used']]);
|
| + _oldPieDataTable.clearRows();
|
| + heap = profile['heaps']['old'];
|
| + _oldPieDataTable.addRow(['Used', heap['used']]);
|
| + _oldPieDataTable.addRow(['Free', heap['capacity'] - heap['used']]);
|
| + _draw();
|
| + }
|
| +
|
| + void _draw() {
|
| + if (_tableChart == null) {
|
| + return;
|
| + }
|
| + _tableChart.draw(_tableDataTable);
|
| + _newPieChart.draw(_newPieDataTable);
|
| + _oldPieChart.draw(_oldPieDataTable);
|
| + }
|
|
|
| dynamic _columnValue(Map v, int index) {
|
| - assert(columns.length == 9);
|
| + assert(index >= 0);
|
| + assert(index < 9);
|
| switch (index) {
|
| case 0:
|
| return v['class']['user_name'];
|
| @@ -62,43 +135,6 @@ class HeapProfileElement extends ObservatoryElement {
|
| }
|
| }
|
|
|
| - int _sortColumn(Map a, Map b, int index) {
|
| - var aValue = _columnValue(a, index);
|
| - var bValue = _columnValue(b, index);
|
| - return Comparable.compare(bValue, aValue);
|
| - }
|
| -
|
| - _sort() {
|
| - if ((profile == null) || (profile['members'] is! List) ||
|
| - (profile['members'].length == 0)) {
|
| - sortedProfile = toObservable([]);
|
| - return;
|
| - }
|
| - sortedProfile = profile['members'].toList();
|
| - sortedProfile.sort((a, b) => _sortColumn(a, b, _sortColumnIndex));
|
| - sortedProfile = toObservable(sortedProfile);
|
| - notifyPropertyChange(#sortedProfile, [], sortedProfile);
|
| - notifyPropertyChange(#current, 0, 1);
|
| - notifyPropertyChange(#allocated, 0, 1);
|
| - notifyPropertyChange(#beforeGC, 0, 1);
|
| - notifyPropertyChange(#afterGC, 0, 1);
|
| - }
|
| -
|
| - void changeSortColumn(Event e, var detail, Element target) {
|
| - var message = target.attributes['data-msg'];
|
| - var index;
|
| - try {
|
| - index = int.parse(message);
|
| - } catch (e) {
|
| - return;
|
| - }
|
| - assert(index is int);
|
| - assert(index > 0);
|
| - assert(index < columns.length);
|
| - _sortColumnIndex = index;
|
| - _sort();
|
| - }
|
| -
|
| void refreshData(Event e, var detail, Node target) {
|
| var isolateId = app.locationManager.currentIsolateId();
|
| var isolate = app.isolateManager.getIsolate(isolateId);
|
| @@ -116,84 +152,38 @@ class HeapProfileElement extends ObservatoryElement {
|
| }
|
|
|
| void profileChanged(oldValue) {
|
| - _sort();
|
| - notifyPropertyChange(#status, [], status);
|
| + _updateChartData();
|
| + notifyPropertyChange(#formattedAverage, [], formattedAverage);
|
| + notifyPropertyChange(#formattedTotalCollectionTime, [],
|
| + formattedTotalCollectionTime);
|
| + notifyPropertyChange(#formattedCollections, [], formattedCollections);
|
| }
|
|
|
| - String status(bool new_space) {
|
| + @observable String formattedAverage(bool newSpace) {
|
| if (profile == null) {
|
| return '';
|
| }
|
| - String space = new_space ? 'new' : 'old';
|
| + String space = newSpace ? 'new' : 'old';
|
| Map heap = profile['heaps'][space];
|
| - var usage = '${ObservatoryApplication.scaledSizeUnits(heap['used'])} / '
|
| - '${ObservatoryApplication.scaledSizeUnits(heap['capacity'])}';
|
| - var timings = '${ObservatoryApplication.timeUnits(heap['time'])} secs';
|
| - var collections = '${heap['collections']} collections';
|
| - var avgTime = '${(heap['time'] * 1000.0) / heap['collections']} ms';
|
| - return '$usage ($timings) [$collections] $avgTime';
|
| - }
|
| -
|
| - String current(Map cls, bool new_space, [bool instances = false]) {
|
| - if (cls is !Map) {
|
| - return '';
|
| - }
|
| - List data = cls[new_space ? 'new' : 'old'];
|
| - if (data == null) {
|
| - return '';
|
| - }
|
| - int current = data[instances ? LIVE_AFTER_GC : LIVE_AFTER_GC_SIZE] +
|
| - data[instances ? ALLOCATED_SINCE_GC : ALLOCATED_SINCE_GC_SIZE];
|
| - if (instances) {
|
| - return '$current';
|
| - }
|
| - return ObservatoryApplication.scaledSizeUnits(current);
|
| + var r = ((heap['time'] * 1000.0) / heap['collections']).toStringAsFixed(2);
|
| + return '$r ms';
|
| }
|
|
|
| - String allocated(Map cls, bool new_space, [bool instances = false]) {
|
| - if (cls is !Map) {
|
| - return '';
|
| - }
|
| - List data = cls[new_space ? 'new' : 'old'];
|
| - if (data == null) {
|
| - return '';
|
| - }
|
| - int current =
|
| - data[instances ? ALLOCATED_SINCE_GC : ALLOCATED_SINCE_GC_SIZE];
|
| - if (instances) {
|
| - return '$current';
|
| - }
|
| - return ObservatoryApplication.scaledSizeUnits(current);
|
| - }
|
| -
|
| - String beforeGC(Map cls, bool new_space, [bool instances = false]) {
|
| - if (cls is! Map) {
|
| - return '';
|
| - }
|
| - List data = cls[new_space ? 'new' : 'old'];
|
| - if (data == null) {
|
| + @observable String formattedCollections(bool newSpace) {
|
| + if (profile == null) {
|
| return '';
|
| }
|
| - int current =
|
| - data[instances ? ALLOCATED_BEFORE_GC : ALLOCATED_BEFORE_GC_SIZE];
|
| - if (instances) {
|
| - return '$current';
|
| - }
|
| - return ObservatoryApplication.scaledSizeUnits(current);
|
| + String space = newSpace ? 'new' : 'old';
|
| + Map heap = profile['heaps'][space];
|
| + return '${heap['collections']}';
|
| }
|
|
|
| - String afterGC(Map cls, bool new_space, [bool instances = false]) {
|
| - if (cls is! Map) {
|
| - return '';
|
| - }
|
| - List data = cls[new_space ? 'new' : 'old'];
|
| - if (data == null) {
|
| + @observable String formattedTotalCollectionTime(bool newSpace) {
|
| + if (profile == null) {
|
| return '';
|
| }
|
| - int current = data[instances ? LIVE_AFTER_GC : LIVE_AFTER_GC_SIZE];
|
| - if (instances) {
|
| - return '$current';
|
| - }
|
| - return ObservatoryApplication.scaledSizeUnits(current);
|
| + String space = newSpace ? 'new' : 'old';
|
| + Map heap = profile['heaps'][space];
|
| + return '${ObservatoryApplication.timeUnits(heap['time'])} secs';
|
| }
|
| }
|
|
|