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

Unified Diff: runtime/observatory/lib/src/elements/heap_profile.dart

Issue 2255613002: Converted Observatory heap-profile element (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Better sorting tests Created 4 years, 4 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/observatory/lib/src/elements/heap_profile.dart
diff --git a/runtime/observatory/lib/src/elements/heap_profile.dart b/runtime/observatory/lib/src/elements/heap_profile.dart
deleted file mode 100644
index 3e0116e76b06057f27513e39f073eed98b1fa7c9..0000000000000000000000000000000000000000
--- a/runtime/observatory/lib/src/elements/heap_profile.dart
+++ /dev/null
@@ -1,406 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library heap_profile_element;
-
-import 'dart:async';
-import 'dart:html';
-import 'class_ref_wrapper.dart';
-import 'observatory_element.dart';
-import 'package:charted/charted.dart';
-import 'package:observatory/app.dart';
-import 'package:observatory/service.dart';
-import 'package:observatory/elements.dart';
-import 'package:polymer/polymer.dart';
-
-class ClassSortedTable extends SortedTable {
-
- ClassSortedTable(columns) : super(columns);
-
- @override
- dynamic getSortKeyFor(int row, int col) {
- if (col == 0) {
- // Use class name as sort key.
- return rows[row].values[col].name;
- }
- return super.getSortKeyFor(row, col);
- }
-}
-
-@CustomTag('heap-profile')
-class HeapProfileElement extends ObservatoryElement {
- @observable String lastServiceGC = '---';
- @observable String lastAccumulatorReset = '---';
-
- // Pie chart of new space usage.
- var _newPieChart;
- final _newPieChartRows = [];
- // Pie chart of old space usage.
- var _oldPieChart;
- final _oldPieChartRows = [];
-
- @observable ClassSortedTable classTable;
- var _classTableBody;
-
- @published bool autoRefresh = false;
- var _subscriptionFuture;
-
- @published Isolate isolate;
- @observable ServiceMap profile;
-
- final _pieChartColumns = [
- new ChartColumnSpec(label: 'Type', type: ChartColumnSpec.TYPE_STRING),
- new ChartColumnSpec(label: 'Size', formatter: (v) => v.toString())
- ];
-
- HeapProfileElement.created() : super.created() {
- _initPieChartData(_newPieChartRows);
- _initPieChartData(_oldPieChartRows);
-
- // Create class table model.
- var columns = [
- new SortedTableColumn('Class'),
- new SortedTableColumn(''), // Spacer column.
- new SortedTableColumn.withFormatter('Accumulated Size (New)',
- Utils.formatSize),
- new SortedTableColumn.withFormatter('Accumulated Instances',
- Utils.formatCommaSeparated),
- new SortedTableColumn.withFormatter('Current Size',
- Utils.formatSize),
- new SortedTableColumn.withFormatter('Current Instances',
- Utils.formatCommaSeparated),
- new SortedTableColumn(''), // Spacer column.
- new SortedTableColumn.withFormatter('Accumulator Size (Old)',
- Utils.formatSize),
- new SortedTableColumn.withFormatter('Accumulator Instances',
- Utils.formatCommaSeparated),
- new SortedTableColumn.withFormatter('Current Size',
- Utils.formatSize),
- new SortedTableColumn.withFormatter('Current Instances',
- Utils.formatCommaSeparated)
- ];
- classTable = new ClassSortedTable(columns);
- // By default, start with accumulated new space bytes.
- classTable.sortColumnIndex = 2;
- }
-
- LayoutArea _makePieChart(String id, List rows) {
- var wrapper = shadowRoot.querySelector(id);
- var areaHost = wrapper.querySelector('.chart-host');
- assert(areaHost != null);
- var legendHost = wrapper.querySelector('.chart-legend-host');
- assert(legendHost != null);
- var series = new ChartSeries(id, [1], new PieChartRenderer(
- sortDataByValue: false
- ));
- var config = new ChartConfig([series], [0]);
- config.minimumSize = new Rect(300, 300);
- config.legend = new ChartLegend(legendHost, showValues: true);
- var data = new ChartData(_pieChartColumns, rows);
- var area = new LayoutArea(areaHost,
- data,
- config,
- state: new ChartState(),
- autoUpdate: false);
- area.addChartBehavior(new Hovercard());
- area.addChartBehavior(new AxisLabelTooltip());
- return area;
- }
-
- @override
- void attached() {
- super.attached();
- _newPieChart = _makePieChart('#new-pie-chart', _newPieChartRows);
- _oldPieChart = _makePieChart('#old-pie-chart', _oldPieChartRows);
- _classTableBody = shadowRoot.querySelector('#classTableBody');
- _subscriptionFuture =
- app.vm.listenEventStream(VM.kGCStream, _onEvent);
- }
-
- @override
- void detached() {
- cancelFutureSubscription(_subscriptionFuture);
- _subscriptionFuture = null;
- super.detached();
- }
-
- // Keep at most one outstanding auto-refresh RPC.
- bool refreshAutoPending = false;
- bool refreshAutoQueued = false;
-
- void _onEvent(ServiceEvent event) {
- assert(event.kind == 'GC');
- if (autoRefresh) {
- if (!refreshAutoPending) {
- refreshAuto();
- } else {
- // Remember to refresh once more, to ensure latest profile.
- refreshAutoQueued = true;
- }
- }
- }
-
- void refreshAuto() {
- refreshAutoPending = true;
- refreshAutoQueued = false;
- refresh().then((_) {
- refreshAutoPending = false;
- // Keep refreshing if at least one GC event was received while waiting.
- if (refreshAutoQueued) {
- refreshAuto();
- }
- }).catchError(app.handleException);
- }
-
- static const _USED_INDEX = 0;
- static const _FREE_INDEX = 1;
- static const _EXTERNAL_INDEX = 2;
-
- static const _VALUE_INDEX = 1;
-
- void _initPieChartData(List rows) {
- rows.add(['Used', 0]);
- rows.add(['Free', 0]);
- rows.add(['External', 0]);
- }
-
- void _updatePieChartData(List rows, HeapSpace space) {
- rows[_USED_INDEX][_VALUE_INDEX] = space.used;
- rows[_FREE_INDEX][_VALUE_INDEX] = space.capacity - space.used;
- rows[_EXTERNAL_INDEX][_VALUE_INDEX] = space.external;
- }
-
- void _updatePieCharts() {
- assert(profile != null);
- _updatePieChartData(_newPieChartRows, isolate.newSpace);
- _updatePieChartData(_oldPieChartRows, isolate.oldSpace);
- }
-
- void _updateClasses() {
- for (ServiceMap clsAllocations in profile['members']) {
- Class cls = clsAllocations['class'];
- if (cls == null) {
- continue;
- }
- cls.newSpace.update(clsAllocations['new']);
- cls.oldSpace.update(clsAllocations['old']);
- }
- }
-
- void _updateClassTable() {
- classTable.clearRows();
- for (ServiceMap clsAllocations in profile['members']) {
- Class cls = clsAllocations['class'];
- if (cls == null) {
- continue;
- }
- if (cls.hasNoAllocations) {
- // If a class has no allocations, don't display it.
- continue;
- }
- var row = [cls,
- '', // Spacer column.
- cls.newSpace.accumulated.bytes,
- cls.newSpace.accumulated.instances,
- cls.newSpace.current.bytes,
- cls.newSpace.current.instances,
- '', // Spacer column.
- cls.oldSpace.accumulated.bytes,
- cls.oldSpace.accumulated.instances,
- cls.oldSpace.current.bytes,
- cls.oldSpace.current.instances];
- classTable.addRow(new SortedTableRow(row));
- }
- classTable.sort();
- }
-
- void _addClassTableDomRow() {
- assert(_classTableBody != null);
- var tr = new TableRowElement();
-
- // Add class ref.
- var cell = tr.insertCell(-1);
- ClassRefElement classRef = new Element.tag('class-ref');
- cell.children.add(classRef);
-
- // Add spacer.
- cell = tr.insertCell(-1);
- cell.classes.add('left-border-spacer');
-
- // Add new space.
- cell = tr.insertCell(-1);
- cell = tr.insertCell(-1);
- cell = tr.insertCell(-1);
- cell = tr.insertCell(-1);
-
- // Add spacer.
- cell = tr.insertCell(-1);
- cell.classes.add('left-border-spacer');
-
- // Add old space.
- cell = tr.insertCell(-1);
- cell = tr.insertCell(-1);
- cell = tr.insertCell(-1);
- cell = tr.insertCell(-1);
-
- // Add row to table.
- _classTableBody.children.add(tr);
- }
-
- void _fillClassTableDomRow(TableRowElement tr, int rowIndex) {
- const SPACER_COLUMNS = const [1, 6];
-
- var row = classTable.rows[rowIndex];
- // Add class ref.
- ClassRefElementWrapper classRef = tr.children[0].children[0];
- classRef.ref = row.values[0];
-
- for (var i = 1; i < row.values.length; i++) {
- if (SPACER_COLUMNS.contains(i)) {
- // Skip spacer columns.
- continue;
- }
- var cell = tr.children[i];
- cell.title = row.values[i].toString();
- cell.text = classTable.getFormattedValue(rowIndex, i);
- if (i > 1) { // Numbers.
- cell.style.textAlign = 'right';
- cell.style.paddingLeft = '1em';
- }
- }
- }
-
- void _updateClassTableInDom() {
- assert(_classTableBody != null);
- // Resize DOM table.
- if (_classTableBody.children.length > classTable.sortedRows.length) {
- // Shrink the table.
- var deadRows =
- _classTableBody.children.length - classTable.sortedRows.length;
- for (var i = 0; i < deadRows; i++) {
- _classTableBody.children.removeLast();
- }
- } else if (_classTableBody.children.length < classTable.sortedRows.length) {
- // Grow table.
- var newRows =
- classTable.sortedRows.length - _classTableBody.children.length;
- for (var i = 0; i < newRows; i++) {
- _addClassTableDomRow();
- }
- }
- assert(_classTableBody.children.length == classTable.sortedRows.length);
- // Fill table.
- for (var i = 0; i < classTable.sortedRows.length; i++) {
- var rowIndex = classTable.sortedRows[i];
- var tr = _classTableBody.children[i];
- _fillClassTableDomRow(tr, rowIndex);
- }
- }
-
- void _drawCharts() {
- _newPieChart.draw();
- _oldPieChart.draw();
- }
-
- @observable void changeSort(Event e, var detail, Element target) {
- if (target is TableCellElement) {
- if (classTable.sortColumnIndex != target.cellIndex) {
- classTable.sortColumnIndex = target.cellIndex;
- classTable.sortDescending = true;
- } else {
- classTable.sortDescending = !classTable.sortDescending;
- }
- classTable.sort();
- _updateClassTableInDom();
- }
- }
-
- void isolateChanged(oldValue) {
- if (isolate == null) {
- profile = null;
- return;
- }
- isolate.invokeRpc('_getAllocationProfile', {})
- .then(_update)
- .catchError(app.handleException);
- }
-
- Future refresh() {
- if (isolate == null) {
- return new Future.value(null);
- }
- return isolate.invokeRpc('_getAllocationProfile', {})
- .then(_update);
- }
-
- Future refreshGC() {
- if (isolate == null) {
- return new Future.value(null);
- }
- return isolate.invokeRpc('_getAllocationProfile', { 'gc': 'full' })
- .then(_update);
- }
-
- Future resetAccumulator() {
- if (isolate == null) {
- return new Future.value(null);
- }
- return isolate.invokeRpc('_getAllocationProfile', { 'reset': 'true' })
- .then(_update);
- }
-
- void _update(ServiceMap newProfile) {
- profile = newProfile;
- }
-
- void profileChanged(oldValue) {
- if (profile == null) {
- return;
- }
- isolate.updateHeapsFromMap(profile['heaps']);
- var millis = int.parse(profile['dateLastAccumulatorReset']);
- if (millis != 0) {
- lastAccumulatorReset =
- new DateTime.fromMillisecondsSinceEpoch(millis).toString();
- }
- millis = int.parse(profile['dateLastServiceGC']);
- if (millis != 0) {
- lastServiceGC =
- new DateTime.fromMillisecondsSinceEpoch(millis).toString();
- }
- _updatePieCharts();
- _updateClasses();
- _updateClassTable();
- _updateClassTableInDom();
- _drawCharts();
- notifyPropertyChange(#formattedAverage, 0, 1);
- notifyPropertyChange(#formattedTotalCollectionTime, 0, 1);
- notifyPropertyChange(#formattedCollections, 0, 1);
- }
-
- @observable String formattedAverage(bool newSpace) {
- if (profile == null) {
- return '';
- }
- var heap = newSpace ? isolate.newSpace : isolate.oldSpace;
- var avg = ((heap.totalCollectionTimeInSeconds * 1000.0) / heap.collections);
- return '${avg.toStringAsFixed(2)} ms';
- }
-
- @observable String formattedCollections(bool newSpace) {
- if (profile == null) {
- return '';
- }
- var heap = newSpace ? isolate.newSpace : isolate.oldSpace;
- return heap.collections.toString();
- }
-
- @observable String formattedTotalCollectionTime(bool newSpace) {
- if (profile == null) {
- return '';
- }
- var heap = newSpace ? isolate.newSpace : isolate.oldSpace;
- return '${Utils.formatSeconds(heap.totalCollectionTimeInSeconds)} secs';
- }
-}
« no previous file with comments | « runtime/observatory/lib/src/elements/css/shared.css ('k') | runtime/observatory/lib/src/elements/heap_profile.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698