| Index: runtime/observatory/lib/src/elements/memory/dashboard.dart
|
| diff --git a/runtime/observatory/lib/src/elements/memory/dashboard.dart b/runtime/observatory/lib/src/elements/memory/dashboard.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2aa299ef5e5ce237ff25cb4a8d354b8c989a353c
|
| --- /dev/null
|
| +++ b/runtime/observatory/lib/src/elements/memory/dashboard.dart
|
| @@ -0,0 +1,162 @@
|
| +// Copyright (c) 2017, 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.
|
| +
|
| +/// This page is not directly reachable from the main Observatory ui.
|
| +/// It is mainly mented to be used from editors as an integrated tool.
|
| +///
|
| +/// This page mainly targeting developers and not VM experts, so concepts like
|
| +/// old and new heap are abstracted away.
|
| +///
|
| +/// The page comprises an overall memory usage of the VM from where it is
|
| +/// possible to select an isolate to deeply analyze.
|
| +/// See MemoryGraphElement
|
| +///
|
| +/// Once an isolate is selected it is possible to information specific to it.
|
| +/// See MemoryProfileElement
|
| +///
|
| +/// The logic in this Element is mainly mented to orchestrate the two
|
| +/// sub-components by means of positioning and message passing.
|
| +
|
| +import 'dart:async';
|
| +import 'dart:html';
|
| +import 'package:observatory/models.dart' as M;
|
| +import 'package:observatory/src/elements/helpers/nav_bar.dart';
|
| +import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
|
| +import 'package:observatory/src/elements/helpers/tag.dart';
|
| +import 'package:observatory/src/elements/nav/notify.dart';
|
| +import 'package:observatory/src/elements/memory/graph.dart';
|
| +import 'package:observatory/src/elements/memory/profile.dart';
|
| +
|
| +class MemoryDashboardElement extends HtmlElement implements Renderable {
|
| + static const tag = const Tag<MemoryDashboardElement>('memory-dashboard',
|
| + dependencies: const [
|
| + NavNotifyElement.tag,
|
| + MemoryGraphElement.tag,
|
| + MemoryProfileElement.tag
|
| + ]);
|
| +
|
| + RenderingScheduler<MemoryDashboardElement> _r;
|
| +
|
| + Stream<RenderedEvent<MemoryDashboardElement>> get onRendered => _r.onRendered;
|
| +
|
| + M.VMRef _vm;
|
| + M.IsolateRepository _isolates;
|
| + M.EditorRepository _editor;
|
| + M.AllocationProfileRepository _allocations;
|
| + M.EventRepository _events;
|
| + M.NotificationRepository _notifications;
|
| +
|
| + M.VM get vm => _vm;
|
| + M.NotificationRepository get notifications => _notifications;
|
| +
|
| + factory MemoryDashboardElement(
|
| + M.VM vm,
|
| + M.IsolateRepository isolates,
|
| + M.EditorRepository editor,
|
| + M.AllocationProfileRepository allocations,
|
| + M.EventRepository events,
|
| + M.NotificationRepository notifications,
|
| + {RenderingQueue queue}) {
|
| + assert(vm != null);
|
| + assert(isolates != null);
|
| + assert(editor != null);
|
| + assert(allocations != null);
|
| + assert(events != null);
|
| + assert(notifications != null);
|
| + MemoryDashboardElement e = document.createElement(tag.name);
|
| + e._r = new RenderingScheduler(e, queue: queue);
|
| + e._vm = vm;
|
| + e._isolates = isolates;
|
| + e._editor = editor;
|
| + e._allocations = allocations;
|
| + e._events = events;
|
| + e._notifications = notifications;
|
| + return e;
|
| + }
|
| +
|
| + MemoryDashboardElement.created() : super.created();
|
| +
|
| + @override
|
| + attached() {
|
| + super.attached();
|
| + _r.enable();
|
| + }
|
| +
|
| + @override
|
| + detached() {
|
| + super.detached();
|
| + _r.disable(notify: true);
|
| + children = [];
|
| + }
|
| +
|
| + M.IsolateRef _isolate;
|
| +
|
| + MemoryGraphElement _graph;
|
| +
|
| + void render() {
|
| + if (_graph == null) {
|
| + _graph = new MemoryGraphElement(vm, _isolates, _events, queue: _r.queue)
|
| + ..onIsolateSelected.listen(_onIsolateSelected);
|
| + }
|
| + children = [
|
| + navBar([new NavNotifyElement(_notifications, queue: _r.queue)]),
|
| + new DivElement()
|
| + ..classes = ['content-centered-big']
|
| + ..children = [
|
| + new HeadingElement.h2()..text = 'Memory Dashboard',
|
| + new HRElement(),
|
| + _graph,
|
| + new HRElement(),
|
| + ],
|
| + ];
|
| + if (_isolate == null) {
|
| + children.add(new DivElement()
|
| + ..classes = ['content-centered-big']
|
| + ..children = [new HeadingElement.h1()..text = "No isolate selected"]);
|
| + } else {
|
| + final MemoryProfileElement profile =
|
| + new MemoryProfileElement(_isolate, _editor, _events, _allocations);
|
| + final ButtonElement reload = new ButtonElement();
|
| + final ButtonElement gc = new ButtonElement();
|
| + children.addAll([
|
| + new DivElement()
|
| + ..classes = ['content-centered-big']
|
| + ..children = [
|
| + new HeadingElement.h1()
|
| + ..children = [
|
| + new Text("Isolate ${_isolate.name}"),
|
| + reload
|
| + ..classes = ['link', 'big']
|
| + ..text = ' ↺ '
|
| + ..title = 'Refresh'
|
| + ..onClick.listen((e) async {
|
| + gc.disabled = true;
|
| + reload.disabled = true;
|
| + await profile.reload();
|
| + gc.disabled = false;
|
| + reload.disabled = false;
|
| + }),
|
| + gc
|
| + ..classes = ['link', 'big']
|
| + ..text = ' ♺ '
|
| + ..title = 'Collect Garbage'
|
| + ..onClick.listen((e) async {
|
| + gc.disabled = true;
|
| + reload.disabled = true;
|
| + await profile.reload(gc: true);
|
| + gc.disabled = false;
|
| + reload.disabled = false;
|
| + }),
|
| + ]
|
| + ],
|
| + profile
|
| + ]);
|
| + }
|
| + }
|
| +
|
| + void _onIsolateSelected(IsolateSelectedEvent e) {
|
| + _r.checkAndReact(_isolate, e.isolate);
|
| + _isolate = e.isolate;
|
| + }
|
| +}
|
|
|