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

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

Issue 2279973002: Converted Observatory heap-map element (Closed)
Patch Set: Fixed 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_map.dart
diff --git a/runtime/observatory/lib/src/elements/heap_map.dart b/runtime/observatory/lib/src/elements/heap_map.dart
index a91e3166162024188bc2340a7cc243b7763f2a5c..1797239737fd74abd78858458264bc48e1b6d8d8 100644
--- a/runtime/observatory/lib/src/elements/heap_map.dart
+++ b/runtime/observatory/lib/src/elements/heap_map.dart
@@ -7,56 +7,82 @@ library heap_map_element;
import 'dart:async';
import 'dart:html';
import 'dart:math';
-import 'observatory_element.dart';
-import 'package:observatory/service.dart';
-import 'package:logging/logging.dart';
-import 'package:polymer/polymer.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/service.dart' as S;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/src/elements/nav/bar.dart';
+import 'package:observatory/src/elements/nav/isolate_menu.dart';
+import 'package:observatory/src/elements/nav/menu.dart';
+import 'package:observatory/src/elements/nav/notify.dart';
+import 'package:observatory/src/elements/nav/refresh.dart';
+import 'package:observatory/src/elements/nav/top_menu.dart';
+import 'package:observatory/src/elements/nav/vm_menu.dart';
+class HeapMapElement extends HtmlElement implements Renderable {
+ static const tag = const Tag<HeapMapElement>('heap-map',
+ dependencies: const [
+ NavBarElement.tag,
+ NavTopMenuElement.tag,
+ NavVMMenuElement.tag,
+ NavIsolateMenuElement.tag,
+ NavMenuElement.tag,
+ NavRefreshElement.tag,
+ NavNotifyElement.tag,
+ ]);
-// A reference to a particular pixel of ImageData.
-class PixelReference {
- final _data;
- var _dataIndex;
- static const NUM_COLOR_COMPONENTS = 4;
+ RenderingScheduler<HeapMapElement> _r;
- PixelReference(ImageData data, Point<int> point)
- : _data = data,
- _dataIndex = (point.y * data.width + point.x) * NUM_COLOR_COMPONENTS;
+ Stream<RenderedEvent<HeapMapElement>> get onRendered =>
+ _r.onRendered;
- PixelReference._fromDataIndex(this._data, this._dataIndex);
+ M.VM _vm;
+ M.IsolateRef _isolate;
+ M.EventRepository _events;
+ M.NotificationRepository _notifications;
+ M.VMRef get vm => _vm;
+ M.IsolateRef get isolate => _isolate;
+ M.NotificationRepository get notifications => _notifications;
- Point<int> get point =>
- new Point(index % _data.width, index ~/ _data.width);
-
- void set color(Iterable<int> color) {
- _data.data.setRange(
- _dataIndex, _dataIndex + NUM_COLOR_COMPONENTS, color);
+ factory HeapMapElement(M.VM vm, M.IsolateRef isolate,
+ M.EventRepository events,
+ M.NotificationRepository notifications,
+ {RenderingQueue queue}) {
+ assert(vm != null);
+ assert(isolate != null);
+ assert(events != null);
+ assert(notifications != null);
+ HeapMapElement e = document.createElement(tag.name);
+ e._r = new RenderingScheduler(e, queue: queue);
+ e._vm = vm;
+ e._isolate = isolate;
+ e._events = events;
+ e._notifications = notifications;
+ return e;
}
- Iterable<int> get color =>
- _data.data.getRange(_dataIndex, _dataIndex + NUM_COLOR_COMPONENTS);
-
- // Returns the next pixel in row-major order.
- PixelReference next() => new PixelReference._fromDataIndex(
- _data, _dataIndex + NUM_COLOR_COMPONENTS);
+ HeapMapElement.created() : super.created();
- // The row-major index of this pixel.
- int get index => _dataIndex ~/ NUM_COLOR_COMPONENTS;
-}
+ @override
+ attached() {
+ super.attached();
+ _r.enable();
+ _refresh();
+ }
-class ObjectInfo {
- final address;
- final size;
- ObjectInfo(this.address, this.size);
-}
+ @override
+ detached() {
+ super.detached();
+ _r.disable(notify: true);
+ children = [];
+ }
-@CustomTag('heap-map')
-class HeapMapElement extends ObservatoryElement {
- CanvasElement _fragmentationCanvas;
+ CanvasElement _canvas;
var _fragmentationData;
- var _pageHeight;
- var _classIdToColor = {};
- var _colorToClassId = {};
- var _classIdToName = {};
+ double _pageHeight;
+ final _classIdToColor = {};
+ final _colorToClassId = {};
+ final _classIdToName = {};
static final _freeColor = [255, 255, 255, 255];
static final _pageSeparationColor = [0, 0, 0, 255];
@@ -65,19 +91,37 @@ class HeapMapElement extends ObservatoryElement {
// TODO(koda): Improve interface for huge heaps.
static const _MAX_CANVAS_HEIGHT = 6000;
- @observable String status;
- @published Isolate isolate;
- @observable ServiceMap fragmentation;
+ String _status;
+ S.ServiceMap _fragmentation;
- HeapMapElement.created() : super.created() {
- }
-
- @override
- void attached() {
- super.attached();
- _fragmentationCanvas = shadowRoot.querySelector("#fragmentation");
- _fragmentationCanvas.onMouseMove.listen(_handleMouseMove);
- _fragmentationCanvas.onMouseDown.listen(_handleClick);
+ void render() {
+ if (_canvas == null) {
+ _canvas = new CanvasElement()
+ ..width = 1
+ ..height= 1
+ ..onMouseMove.listen(_handleMouseMove)
+ ..onMouseDown.listen(_handleClick);
+ }
+ children = [
+ new NavBarElement(queue: _r.queue)
+ ..children = [
+ new NavTopMenuElement(queue: _r.queue),
+ new NavVMMenuElement(_vm, _events, queue: _r.queue),
+ new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+ new NavMenuElement('heap map', last: true,
+ link: Uris.heapMap(_isolate), queue: _r.queue),
+ new NavRefreshElement(queue: _r.queue)
+ ..onRefresh.listen((_) => _refresh()),
+ new NavNotifyElement(_notifications, queue: _r.queue)
+ ],
+ new DivElement()..classes = const ['content-centered-big']
+ ..children = [
+ new HeadingElement.h2()..text = _status,
+ new HRElement(),
+ ],
+ new DivElement()..classes = ['flex-row']
+ ..children = [_canvas]
+ ];
}
// Encode color as single integer, to enable using it as a map key.
@@ -97,12 +141,12 @@ class HeapMapElement extends ObservatoryElement {
void _updateClassList(classList, int freeClassId) {
for (var member in classList['classes']) {
- if (member is! Class) {
+ if (member is! S.Class) {
// TODO(turnidge): The printing for some of these non-class
// members is broken. Fix this:
//
// Logger.root.info('$member');
- Logger.root.info('Ignoring non-class in class list');
+ print('Ignoring non-class in class list');
continue;
}
var classId = int.parse(member.id.split('/').last);
@@ -125,14 +169,14 @@ class HeapMapElement extends ObservatoryElement {
}
ObjectInfo _objectAt(Point<int> point) {
- if (fragmentation == null || _fragmentationCanvas == null) {
+ if (_fragmentation == null || _canvas == null) {
return null;
}
var pagePixels = _pageHeight * _fragmentationData.width;
var index = new PixelReference(_fragmentationData, point).index;
var pageIndex = index ~/ pagePixels;
var pageOffset = index % pagePixels;
- var pages = fragmentation['pages'];
+ var pages = _fragmentation['pages'];
if (pageIndex < 0 || pageIndex >= pages.length) {
return null;
}
@@ -150,54 +194,60 @@ class HeapMapElement extends ObservatoryElement {
}
}
return new ObjectInfo(int.parse(page['objectStart']) +
- pageOffset * fragmentation['unitSizeBytes'],
- size * fragmentation['unitSizeBytes']);
+ pageOffset * _fragmentation['unitSizeBytes'],
+ size * _fragmentation['unitSizeBytes']);
}
void _handleMouseMove(MouseEvent event) {
var info = _objectAt(event.offset);
if (info == null) {
- status = '';
+ _status = '';
+ _r.dirty();
return;
}
var addressString = '${info.size}B @ 0x${info.address.toRadixString(16)}';
var className = _classNameAt(event.offset);
- status = (className == '') ? '-' : '$className $addressString';
+ _status = (className == '') ? '-' : '$className $addressString';
+ _r.dirty();
}
void _handleClick(MouseEvent event) {
- var address = _objectAt(event.offset).address.toRadixString(16);
+ final isolate = _isolate as S.Isolate;
+ final address = _objectAt(event.offset).address.toRadixString(16);
isolate.getObjectByAddress(address).then((result) {
if (result.type != 'Sentinel') {
- app.locationManager.go(gotoLink('/inspect', result));
+ new AnchorElement(
+ href: Uris.inspect(_isolate, object: result as S.HeapObject)
+ ).click();
}
});
}
void _updateFragmentationData() {
- if (fragmentation == null || _fragmentationCanvas == null) {
+ if (_fragmentation == null || _canvas == null) {
return;
}
_updateClassList(
- fragmentation['classList'], fragmentation['freeClassId']);
- var pages = fragmentation['pages'];
- var width = _fragmentationCanvas.parent.client.width;
+ _fragmentation['classList'], _fragmentation['freeClassId']);
+ var pages = _fragmentation['pages'];
+ var width = _canvas.parent.client.width;
_pageHeight = _PAGE_SEPARATION_HEIGHT +
- fragmentation['pageSizeBytes'] ~/
- fragmentation['unitSizeBytes'] ~/ width;
+ _fragmentation['pageSizeBytes'] ~/
+ _fragmentation['unitSizeBytes'] ~/ width;
var height = min(_pageHeight * pages.length, _MAX_CANVAS_HEIGHT);
_fragmentationData =
- _fragmentationCanvas.context2D.createImageData(width, height);
- _fragmentationCanvas.width = _fragmentationData.width;
- _fragmentationCanvas.height = _fragmentationData.height;
+ _canvas.context2D.createImageData(width, height);
+ _canvas.width = _fragmentationData.width;
+ _canvas.height = _fragmentationData.height;
_renderPages(0);
}
// Renders and draws asynchronously, one page at a time to avoid
// blocking the UI.
void _renderPages(int startPage) {
- var pages = fragmentation['pages'];
- status = 'Loaded $startPage of ${pages.length} pages';
+ var pages = _fragmentation['pages'];
+ _status = 'Loaded $startPage of ${pages.length} pages';
+ _r.dirty();
var startY = startPage * _pageHeight;
var endY = startY + _pageHeight;
if (startPage >= pages.length || endY > _fragmentationData.height) {
@@ -218,7 +268,7 @@ class HeapMapElement extends ObservatoryElement {
pixel.color = _pageSeparationColor;
pixel = pixel.next();
}
- _fragmentationCanvas.context2D.putImageData(
+ _canvas.context2D.putImageData(
_fragmentationData, 0, 0, 0, startY, _fragmentationData.width, endY);
// Continue with the next page, asynchronously.
new Future(() {
@@ -226,33 +276,49 @@ class HeapMapElement extends ObservatoryElement {
});
}
- void isolateChanged(oldValue) {
- if (isolate == null) {
- fragmentation = null;
- return;
- }
- isolate.invokeRpc('_getHeapMap', {}).then((ServiceMap response) {
+ Future _refresh() {
+ final isolate = _isolate as S.Isolate;
+ return isolate.invokeRpc('_getHeapMap', {}).then((S.ServiceMap response) {
assert(response['type'] == 'HeapMap');
- fragmentation = response;
- }).catchError((e, st) {
- Logger.root.info('$e $st');
+ _fragmentation = response;
+ _updateFragmentationData();
});
}
+}
- Future refresh() {
- if (isolate == null) {
- return new Future.value(null);
- }
- return isolate.invokeRpc('_getHeapMap', {}).then((ServiceMap response) {
- assert(response['type'] == 'HeapMap');
- fragmentation = response;
- });
- }
+// A reference to a particular pixel of ImageData.
+class PixelReference {
+ final _data;
+ var _dataIndex;
+ static const NUM_COLOR_COMPONENTS = 4;
- void fragmentationChanged(oldValue) {
- // Async, in case attached has not yet run (observed in JS version).
- new Future(() {
- _updateFragmentationData();
- });
+ PixelReference(ImageData data, Point<int> point)
+ : _data = data,
+ _dataIndex = (point.y * data.width + point.x) * NUM_COLOR_COMPONENTS;
+
+ PixelReference._fromDataIndex(this._data, this._dataIndex);
+
+ Point<int> get point =>
+ new Point(index % _data.width, index ~/ _data.width);
+
+ void set color(Iterable<int> color) {
+ _data.data.setRange(
+ _dataIndex, _dataIndex + NUM_COLOR_COMPONENTS, color);
}
+
+ Iterable<int> get color =>
+ _data.data.getRange(_dataIndex, _dataIndex + NUM_COLOR_COMPONENTS);
+
+ // Returns the next pixel in row-major order.
+ PixelReference next() => new PixelReference._fromDataIndex(
+ _data, _dataIndex + NUM_COLOR_COMPONENTS);
+
+ // The row-major index of this pixel.
+ int get index => _dataIndex ~/ NUM_COLOR_COMPONENTS;
+}
+
+class ObjectInfo {
+ final address;
+ final size;
+ ObjectInfo(this.address, this.size);
}
« no previous file with comments | « runtime/observatory/lib/src/elements/css/shared.css ('k') | runtime/observatory/lib/src/elements/heap_map.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698