| Index: runtime/observatory/lib/src/elements/heap_snapshot.dart
|
| diff --git a/runtime/observatory/lib/src/elements/heap_snapshot.dart b/runtime/observatory/lib/src/elements/heap_snapshot.dart
|
| index 2fd6e7882247f5d014aa80cb3cb8b53602f3f691..7389daa2aaea72ea8b4da9e9362cce68612f9534 100644
|
| --- a/runtime/observatory/lib/src/elements/heap_snapshot.dart
|
| +++ b/runtime/observatory/lib/src/elements/heap_snapshot.dart
|
| @@ -24,7 +24,7 @@ import 'package:observatory/src/elements/nav/top_menu.dart';
|
| import 'package:observatory/src/elements/nav/vm_menu.dart';
|
| import 'package:observatory/utils.dart';
|
|
|
| -enum HeapSnapshotTreeMode { dominatorTree, groupByClass }
|
| +enum HeapSnapshotTreeMode { dominatorTree, mergedDominatorTree, groupByClass }
|
|
|
| class HeapSnapshotElement extends HtmlElement implements Renderable {
|
| static const tag =
|
| @@ -266,6 +266,23 @@ class HeapSnapshotElement extends HtmlElement implements Renderable {
|
| _tree
|
| ]);
|
| break;
|
| + case HeapSnapshotTreeMode.mergedDominatorTree:
|
| + _tree = new VirtualTreeElement(
|
| + _createMergedDominator, _updateMergedDominator,
|
| + _getChildrenMergedDominator,
|
| + items: _getChildrenMergedDominator(_snapshot.mergedDominatorTree),
|
| + queue: _r.queue);
|
| + _tree.expand(_snapshot.mergedDominatorTree);
|
| + final text = 'A heap dominator tree, where siblings with the same class'
|
| + ' have been merged into a single node.';
|
| + report.addAll([
|
| + new DivElement()
|
| + ..classes = ['content-centered-big', 'explanation']
|
| + ..text = text
|
| + ..title = text,
|
| + _tree
|
| + ]);
|
| + break;
|
| case HeapSnapshotTreeMode.groupByClass:
|
| final items = _snapshot.classReferences.toList();
|
| items.sort((a, b) => b.shallowSize - a.shallowSize);
|
| @@ -299,6 +316,24 @@ class HeapSnapshotElement extends HtmlElement implements Renderable {
|
| ];
|
| }
|
|
|
| + static Element _createMergedDominator(toggle) {
|
| + return new DivElement()
|
| + ..classes = ['tree-item']
|
| + ..children = [
|
| + new SpanElement()
|
| + ..classes = ['size']
|
| + ..title = 'retained size',
|
| + new SpanElement()..classes = ['lines'],
|
| + new ButtonElement()
|
| + ..classes = ['expander']
|
| + ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
|
| + new SpanElement()
|
| + ..classes = ['percentage']
|
| + ..title = 'percentage of heap being retained',
|
| + new SpanElement()..classes = ['name']
|
| + ];
|
| + }
|
| +
|
| static Element _createGroup(toggle) {
|
| return new DivElement()
|
| ..classes = ['tree-item']
|
| @@ -327,6 +362,13 @@ class HeapSnapshotElement extends HtmlElement implements Renderable {
|
| .where((child) => child.retainedSize >= kMinRetainedSize)
|
| .take(kMaxChildren);
|
| }
|
| + static _getChildrenMergedDominator(M.HeapSnapshotMergedDominatorNode node) {
|
| + final list = node.children.toList();
|
| + list.sort((a, b) => b.retainedSize - a.retainedSize);
|
| + return list
|
| + .where((child) => child.retainedSize >= kMinRetainedSize)
|
| + .take(kMaxChildren);
|
| + }
|
|
|
| static _getChildrenGroup(item) {
|
| if (item is M.HeapSnapshotClassReferences) {
|
| @@ -361,6 +403,31 @@ class HeapSnapshotElement extends HtmlElement implements Renderable {
|
| });
|
| }
|
|
|
| + void _updateMergedDominator(
|
| + HtmlElement element, M.HeapSnapshotMergedDominatorNode node, int depth) {
|
| + element.children[0].text = Utils.formatSize(node.retainedSize);
|
| + _updateLines(element.children[1].children, depth);
|
| + if (_getChildrenMergedDominator(node).isNotEmpty) {
|
| + element.children[2].text = _tree.isExpanded(node) ? '▼' : '►';
|
| + } else {
|
| + element.children[2].text = '';
|
| + }
|
| + element.children[3].text =
|
| + Utils.formatPercentNormalized(node.retainedSize * 1.0 / _snapshot.size);
|
| + final wrapper = new SpanElement()
|
| + ..classes = ['name']
|
| + ..text = 'Loading...';
|
| + element.children[4] = wrapper;
|
| + node.klass.then((klass) {
|
| + wrapper
|
| + ..text = ''
|
| + ..children = [
|
| + new SpanElement()..text = '${node.instanceCount} instances of ',
|
| + anyRef(_isolate, klass, _instances, queue: _r.queue)
|
| + ];
|
| + });
|
| + }
|
| +
|
| void _updateGroup(HtmlElement element, item, int depth) {
|
| _updateLines(element.children[1].children, depth);
|
| if (item is M.HeapSnapshotClassReferences) {
|
| @@ -424,6 +491,8 @@ class HeapSnapshotElement extends HtmlElement implements Renderable {
|
| switch (mode) {
|
| case HeapSnapshotTreeMode.dominatorTree:
|
| return 'Dominator tree';
|
| + case HeapSnapshotTreeMode.mergedDominatorTree:
|
| + return 'Dominator tree (merged siblings by class)';
|
| case HeapSnapshotTreeMode.groupByClass:
|
| return 'Group by class';
|
| }
|
|
|