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

Side by Side Diff: runtime/observatory/lib/src/elements/memory/profile.dart

Issue 2989083002: Add memory-dashboard page to Observatory (Closed)
Patch Set: Created 3 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 import 'dart:async';
6 import 'dart:html';
7 import 'package:observatory/models.dart' as M;
8 import 'package:observatory/src/elements/class_ref.dart';
9 import 'package:observatory/src/elements/containers/virtual_collection.dart';
10 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
11 import 'package:observatory/src/elements/helpers/tag.dart';
12 import 'package:observatory/utils.dart';
13
14 enum _SortingField {
15 accumulatedSize,
16 accumulatedInstances,
17 currentSize,
18 currentInstances,
19 className,
20 }
21
22 enum _SortingDirection { ascending, descending }
23
24 class MemoryProfileElement extends HtmlElement implements Renderable {
25 static const tag = const Tag<MemoryProfileElement>('memory-profile',
26 dependencies: const [ClassRefElement.tag, VirtualCollectionElement.tag]);
27
28 RenderingScheduler<MemoryProfileElement> _r;
29
30 Stream<RenderedEvent<MemoryProfileElement>> get onRendered => _r.onRendered;
31
32 M.IsolateRef _isolate;
33 M.EventRepository _events;
34 M.AllocationProfileRepository _repository;
35 M.AllocationProfile _profile;
36 M.EditorRepository _editor;
37 StreamSubscription _gcSubscription;
38 _SortingField _sortingField = _SortingField.accumulatedInstances;
39 _SortingDirection _sortingDirection = _SortingDirection.descending;
40
41 M.IsolateRef get isolate => _isolate;
42
43 factory MemoryProfileElement(M.IsolateRef isolate, M.EditorRepository editor,
44 M.EventRepository events, M.AllocationProfileRepository repository,
45 {RenderingQueue queue}) {
46 assert(isolate != null);
47 assert(events != null);
48 assert(editor != null);
49 assert(repository != null);
50 MemoryProfileElement e = document.createElement(tag.name);
51 e._r = new RenderingScheduler(e, queue: queue);
52 e._isolate = isolate;
53 e._editor = editor;
54 e._events = events;
55 e._repository = repository;
56 return e;
57 }
58
59 MemoryProfileElement.created() : super.created();
60
61 @override
62 attached() {
63 super.attached();
64 _r.enable();
65 _refresh(gc: true);
66 _gcSubscription = _events.onGCEvent.listen((e) {
67 if (e.isolate.id == _isolate.id) {
68 _refresh();
69 }
70 });
71 }
72
73 @override
74 detached() {
75 super.detached();
76 _r.disable(notify: true);
77 children = [];
78 _gcSubscription.cancel();
79 }
80
81 Future reload({bool gc = false, bool reset = false}) async {
82 return _refresh(gc: gc, reset: reset);
83 }
84
85 void render() {
86 if (_profile == null) {
87 children = [
88 new DivElement()
89 ..classes = ['content-centered-big']
90 ..children = [new HeadingElement.h2()..text = 'Loading...']
91 ];
92 } else {
93 children = [
94 new VirtualCollectionElement(
95 _createCollectionLine, _updateCollectionLine,
96 createHeader: _createCollectionHeader,
97 items: _profile.members.toList()..sort(_createSorter()),
98 queue: _r.queue)
99 ];
100 }
101 }
102
103 _createSorter() {
104 var getter;
105 switch (_sortingField) {
106 case _SortingField.accumulatedSize:
107 getter = _getAccumulatedSize;
108 break;
109 case _SortingField.accumulatedInstances:
110 getter = _getAccumulatedInstances;
111 break;
112 case _SortingField.currentSize:
113 getter = _getCurrentSize;
114 break;
115 case _SortingField.currentInstances:
116 getter = _getCurrentInstances;
117 break;
118 case _SortingField.className:
119 getter = (M.ClassHeapStats s) => s.clazz.name;
120 break;
121 }
122 switch (_sortingDirection) {
123 case _SortingDirection.ascending:
124 return (a, b) => getter(a).compareTo(getter(b));
125 case _SortingDirection.descending:
126 return (a, b) => getter(b).compareTo(getter(a));
127 }
128 }
129
130 static Element _createCollectionLine() => new DivElement()
131 ..classes = ['collection-item']
132 ..children = [
133 new SpanElement()
134 ..classes = ['bytes']
135 ..text = '0B',
136 new SpanElement()
137 ..classes = ['instances']
138 ..text = '0',
139 new SpanElement()
140 ..classes = ['bytes']
141 ..text = '0B',
142 new SpanElement()
143 ..classes = ['instances']
144 ..text = '0',
145 new SpanElement()..classes = ['name']
146 ];
147
148 Element _createCollectionHeader() {
149 final resetAccumulators = new ButtonElement();
150 return new DivElement()
151 ..children = [
152 new DivElement()
153 ..classes = ['collection-item']
154 ..children = [
155 new SpanElement()
156 ..classes = ['group']
157 ..children = [
158 new Text('Since Last '),
159 resetAccumulators
160 ..text = 'Reset↺'
161 ..title = 'Reset'
162 ..onClick.listen((_) async {
163 resetAccumulators.disabled = true;
164 await _refresh(reset: true);
165 resetAccumulators.disabled = false;
166 })
167 ],
168 new SpanElement()
169 ..classes = ['group']
170 ..text = 'Current'
171 ],
172 new DivElement()
173 ..classes = ['collection-item']
174 ..children = [
175 _createHeaderButton(const ['bytes'], 'Size',
176 _SortingField.accumulatedSize, _SortingDirection.descending),
177 _createHeaderButton(
178 const ['instances'],
179 'Instances',
180 _SortingField.accumulatedInstances,
181 _SortingDirection.descending),
182 _createHeaderButton(const ['bytes'], 'Size',
183 _SortingField.currentSize, _SortingDirection.descending),
184 _createHeaderButton(const ['instances'], 'Instances',
185 _SortingField.currentInstances, _SortingDirection.descending),
186 _createHeaderButton(const ['name'], 'Class',
187 _SortingField.className, _SortingDirection.ascending)
188 ],
189 ];
190 }
191
192 ButtonElement _createHeaderButton(List<String> classes, String text,
193 _SortingField field, _SortingDirection direction) =>
194 new ButtonElement()
195 ..classes = classes
196 ..text = _sortingField != field
197 ? text
198 : _sortingDirection == _SortingDirection.ascending
199 ? '$text▼'
200 : '$text▲'
201 ..onClick.listen((_) => _setSorting(field, direction));
202
203 void _setSorting(_SortingField field, _SortingDirection defaultDirection) {
204 if (_sortingField == field) {
205 switch (_sortingDirection) {
206 case _SortingDirection.descending:
207 _sortingDirection = _SortingDirection.ascending;
208 break;
209 case _SortingDirection.ascending:
210 _sortingDirection = _SortingDirection.descending;
211 break;
212 }
213 } else {
214 _sortingDirection = defaultDirection;
215 _sortingField = field;
216 }
217 _r.dirty();
218 }
219
220 void _updateCollectionLine(Element e, M.ClassHeapStats item, index) {
221 e.children[0].text = Utils.formatSize(_getAccumulatedSize(item));
222 e.children[1].text = '${_getAccumulatedInstances(item)}';
223 e.children[2].text = Utils.formatSize(_getCurrentSize(item));
224 e.children[3].text = '${_getCurrentInstances(item)}';
225 e.children[4] = new ClassRefElement(_isolate, item.clazz, queue: _r.queue)
226 ..classes = ['name'];
227 Element.clickEvent.forTarget(e.children[4], useCapture: true).listen((e) {
228 if (_editor.canOpenClass) {
229 e.preventDefault();
230 _editor.openClass(isolate, item.clazz);
231 }
232 });
233 }
234
235 Future _refresh({bool gc: false, bool reset: false}) async {
236 _profile = null;
237 _r.dirty();
238 _profile = await _repository.get(_isolate, gc: gc, reset: reset);
239 _r.dirty();
240 }
241
242 static int _getAccumulatedSize(M.ClassHeapStats s) =>
243 s.newSpace.accumulated.bytes + s.oldSpace.accumulated.bytes;
244 static int _getAccumulatedInstances(M.ClassHeapStats s) =>
245 s.newSpace.accumulated.instances + s.oldSpace.accumulated.instances;
246 static int _getCurrentSize(M.ClassHeapStats s) =>
247 s.newSpace.current.bytes + s.oldSpace.current.bytes;
248 static int _getCurrentInstances(M.ClassHeapStats s) =>
249 s.newSpace.current.instances + s.oldSpace.current.instances;
250 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698