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

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

Issue 2989083002: Add memory-dashboard page to Observatory (Closed)
Patch Set: Upgrade to latest virtual-collection 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
siva 2017/08/03 18:14:51 2017
cbernaschina 2017/08/03 22:32:53 Done.
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();
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 List<HtmlElement> _createCollectionHeader() {
149 final resetAccumulators = new ButtonElement();
150 return [
151 new DivElement()
152 ..classes = ['collection-item']
153 ..children = [
154 new SpanElement()
155 ..classes = ['group']
156 ..children = [
157 new Text('Since Last '),
158 resetAccumulators
159 ..text = 'Reset↺'
160 ..title = 'Reset'
161 ..onClick.listen((_) async {
162 resetAccumulators.disabled = true;
163 await _refresh(reset: true);
164 resetAccumulators.disabled = false;
165 })
166 ],
167 new SpanElement()
168 ..classes = ['group']
169 ..text = 'Current'
170 ],
171 new DivElement()
172 ..classes = ['collection-item']
173 ..children = [
174 _createHeaderButton(const ['bytes'], 'Size',
175 _SortingField.accumulatedSize, _SortingDirection.descending),
176 _createHeaderButton(const ['instances'], 'Instances',
177 _SortingField.accumulatedInstances, _SortingDirection.descending),
178 _createHeaderButton(const ['bytes'], 'Size',
179 _SortingField.currentSize, _SortingDirection.descending),
180 _createHeaderButton(const ['instances'], 'Instances',
181 _SortingField.currentInstances, _SortingDirection.descending),
182 _createHeaderButton(const ['name'], 'Class', _SortingField.className,
183 _SortingDirection.ascending)
184 ],
185 ];
186 }
187
188 ButtonElement _createHeaderButton(List<String> classes, String text,
189 _SortingField field, _SortingDirection direction) =>
190 new ButtonElement()
191 ..classes = classes
192 ..text = _sortingField != field
193 ? text
194 : _sortingDirection == _SortingDirection.ascending
195 ? '$text▼'
196 : '$text▲'
197 ..onClick.listen((_) => _setSorting(field, direction));
198
199 void _setSorting(_SortingField field, _SortingDirection defaultDirection) {
200 if (_sortingField == field) {
201 switch (_sortingDirection) {
202 case _SortingDirection.descending:
203 _sortingDirection = _SortingDirection.ascending;
204 break;
205 case _SortingDirection.ascending:
206 _sortingDirection = _SortingDirection.descending;
207 break;
208 }
209 } else {
210 _sortingDirection = defaultDirection;
211 _sortingField = field;
212 }
213 _r.dirty();
214 }
215
216 void _updateCollectionLine(Element e, M.ClassHeapStats item, index) {
217 e.children[0].text = Utils.formatSize(_getAccumulatedSize(item));
218 e.children[1].text = '${_getAccumulatedInstances(item)}';
219 e.children[2].text = Utils.formatSize(_getCurrentSize(item));
220 e.children[3].text = '${_getCurrentInstances(item)}';
221 e.children[4] = new ClassRefElement(_isolate, item.clazz, queue: _r.queue)
222 ..classes = ['name'];
223 Element.clickEvent.forTarget(e.children[4], useCapture: true).listen((e) {
224 if (_editor.canOpenClass) {
225 e.preventDefault();
226 _editor.openClass(isolate, item.clazz);
227 }
228 });
229 }
230
231 Future _refresh({bool gc: false, bool reset: false}) async {
232 _profile = null;
233 _r.dirty();
234 _profile = await _repository.get(_isolate, gc: gc, reset: reset);
235 _r.dirty();
236 }
237
238 static int _getAccumulatedSize(M.ClassHeapStats s) =>
239 s.newSpace.accumulated.bytes + s.oldSpace.accumulated.bytes;
240 static int _getAccumulatedInstances(M.ClassHeapStats s) =>
241 s.newSpace.accumulated.instances + s.oldSpace.accumulated.instances;
242 static int _getCurrentSize(M.ClassHeapStats s) =>
243 s.newSpace.current.bytes + s.oldSpace.current.bytes;
244 static int _getCurrentInstances(M.ClassHeapStats s) =>
245 s.newSpace.current.instances + s.oldSpace.current.instances;
246 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698