Chromium Code Reviews| Index: runtime/bin/vmservice/client/lib/src/elements/heap_map.dart |
| =================================================================== |
| --- runtime/bin/vmservice/client/lib/src/elements/heap_map.dart (revision 0) |
| +++ runtime/bin/vmservice/client/lib/src/elements/heap_map.dart (revision 0) |
| @@ -0,0 +1,112 @@ |
| +// 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_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/app.dart'; |
| + |
| +/// Displays an Error response. |
| +@CustomTag('heap-map') |
| +class HeapMapElement extends ObservatoryElement { |
| + var _fragmentationCanvas; |
| + var _fragmentationData; |
| + |
| + @observable String status; |
| + @published ServiceMap fragmentation; |
| + |
| + HeapMapElement.created() : super.created() { |
| + } |
| + |
| + void enteredView() { |
| + super.enteredView(); |
| + _fragmentationCanvas = shadowRoot.querySelector("#fragmentation"); |
| + } |
| + |
| + List<int> _classIdToRGBA(int classId) { |
| + if (classId == fragmentation['free_class_id']) { |
| + return [255, 255, 255, 255]; |
| + } else { |
| + // TODO(koda): Pick random hue, but fixed saturation and value. |
| + var rng = new Random(classId); |
| + return [rng.nextInt(128), |
| + rng.nextInt(128), |
| + rng.nextInt(128), |
| + 255]; |
| + } |
| + } |
| + |
| + void _updateFragmentationData() { |
| + if (fragmentation == null || _fragmentationCanvas == null) { |
| + return; |
| + } |
| + var pages = fragmentation['pages']; |
| + // Calculate dimensions. |
| + var numPixels = 0; |
| + var colorMap = {}; |
| + for (var page in pages) { |
| + for (int i = 0; i < page.length; i += 2) { |
| + numPixels += page[i]; |
| + var classId = page[i + 1]; |
| + colorMap.putIfAbsent(classId, () => _classIdToRGBA(classId)); |
| + } |
| + } |
| + var width = _fragmentationCanvas.parent.client.width; |
| + var height = (numPixels + width - 1) ~/ width; |
| + // Render image. |
| + _fragmentationData = |
| + _fragmentationCanvas.context2D.createImageData(width, height); |
| + _fragmentationCanvas.width = _fragmentationData.width; |
| + _fragmentationCanvas.height = _fragmentationData.height; |
| + _renderPage(0, 0, colorMap); |
| + } |
| + |
| + void _renderPage(int startPage, int dataIndex, var colorMap) { |
| + var pages = fragmentation['pages']; |
| + status = 'Loaded $startPage of ${pages.length} pages'; |
| + if (startPage >= pages.length) { |
| + return; |
| + } |
| + var width = _fragmentationData.width; |
| + var dirtyBegin = (dataIndex / 4) ~/ width; |
| + var page = pages[startPage]; |
| + for (var i = 0; i < page.length; i += 2) { |
| + var count = page[i]; |
| + var color = colorMap[page[i + 1]]; |
| + for (var j = 0; j < count; ++j) { |
| + for (var component in color) { |
| + _fragmentationData.data[dataIndex++] = component; |
| + } |
| + } |
| + } |
| + var dirtyEnd = (dataIndex / 4 + width - 1) ~/ width; |
| + _fragmentationCanvas.context2D.putImageData( |
| + _fragmentationData, 0, 0, 0, dirtyBegin, width, dirtyEnd - dirtyBegin); |
| + new Future(() { |
| + _renderPage(startPage + 1, dataIndex, colorMap); |
|
Cutch
2014/03/17 16:00:11
Add a comment about what's going on with new Futur
koda
2014/03/17 17:13:59
Done.
|
| + }); |
| + } |
| + |
| + void refresh(var done) { |
| + if (fragmentation == null) { |
| + return; |
| + } |
| + fragmentation.isolate.get('heapmap').then((ServiceMap response) { |
| + assert(response['type'] == 'HeapMap'); |
| + fragmentation = response; |
| + }).catchError((e, st) { |
| + Logger.root.info('$e $st'); |
| + }).whenComplete(done); |
| + } |
| + |
| + void fragmentationChanged(oldValue) { |
| + _updateFragmentationData(); |
| + } |
| +} |