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; |
+ } |
+} |