OLD | NEW |
---|---|
(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:charted/charted.dart'; | |
8 import "package:charted/charts/charts.dart"; | |
9 import 'package:observatory/models.dart' as M; | |
10 import 'package:observatory/src/elements/class_ref.dart'; | |
11 import 'package:observatory/src/elements/containers/virtual_collection.dart'; | |
12 import 'package:observatory/src/elements/helpers/nav_bar.dart'; | |
13 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; | |
14 import 'package:observatory/src/elements/helpers/tag.dart'; | |
15 import 'package:observatory/src/elements/nav/isolate_menu.dart'; | |
16 import 'package:observatory/src/elements/nav/notify.dart'; | |
17 import 'package:observatory/src/elements/nav/refresh.dart'; | |
18 import 'package:observatory/src/elements/nav/top_menu.dart'; | |
19 import 'package:observatory/src/elements/nav/vm_menu.dart'; | |
20 import 'package:observatory/utils.dart'; | |
21 | |
22 enum _SortingField { | |
23 accumulatedSize, | |
24 accumulatedInstances, | |
25 currentSize, | |
26 currentInstances, | |
27 newAccumulatedSize, | |
28 newAccumulatedInstances, | |
29 newCurrentSize, | |
30 newCurrentInstances, | |
31 oldAccumulatedSize, | |
32 oldAccumulatedInstances, | |
33 oldCurrentSize, | |
34 oldCurrentInstances, | |
35 className, | |
36 } | |
37 | |
38 enum _SortingDirection { ascending, descending } | |
39 | |
40 class MemoryDashboardElement extends HtmlElement implements Renderable { | |
rmacnak
2017/06/27 16:47:56
This currently looks like just a copy of the alloc
cbernaschina
2017/06/27 17:03:25
It is the initial version of the User Oriented too
| |
41 static const tag = const Tag<MemoryDashboardElement>('memory-dashboard', | |
42 dependencies: const [ | |
43 ClassRefElement.tag, | |
44 NavTopMenuElement.tag, | |
45 NavVMMenuElement.tag, | |
46 NavIsolateMenuElement.tag, | |
47 NavRefreshElement.tag, | |
48 NavNotifyElement.tag, | |
49 VirtualCollectionElement.tag | |
50 ]); | |
51 | |
52 RenderingScheduler<MemoryDashboardElement> _r; | |
53 | |
54 Stream<RenderedEvent<MemoryDashboardElement>> get onRendered => _r.onRendered; | |
55 | |
56 M.VM _vm; | |
57 M.IsolateRef _isolate; | |
58 M.EventRepository _events; | |
59 M.NotificationRepository _notifications; | |
60 M.AllocationProfileRepository _repository; | |
61 M.AllocationProfile _profile; | |
62 M.EditorRepository _editor; | |
63 bool _autoRefresh = false; | |
64 bool _isCompacted = false; | |
65 StreamSubscription _gcSubscription; | |
66 _SortingField _sortingField = _SortingField.className; | |
67 _SortingDirection _sortingDirection = _SortingDirection.ascending; | |
68 | |
69 M.VMRef get vm => _vm; | |
70 M.IsolateRef get isolate => _isolate; | |
71 M.NotificationRepository get notifications => _notifications; | |
72 | |
73 factory MemoryDashboardElement( | |
74 M.VM vm, | |
75 M.IsolateRef isolate, | |
76 M.EventRepository events, | |
77 M.NotificationRepository notifications, | |
78 M.AllocationProfileRepository repository, | |
79 M.EditorRepository editor, | |
80 {RenderingQueue queue}) { | |
81 assert(vm != null); | |
82 assert(isolate != null); | |
83 assert(events != null); | |
84 assert(notifications != null); | |
85 assert(repository != null); | |
86 assert(editor != null); | |
87 MemoryDashboardElement e = document.createElement(tag.name); | |
88 e._r = new RenderingScheduler(e, queue: queue); | |
89 e._vm = vm; | |
90 e._isolate = isolate; | |
91 e._events = events; | |
92 e._notifications = notifications; | |
93 e._repository = repository; | |
94 e._editor = editor; | |
95 return e; | |
96 } | |
97 | |
98 MemoryDashboardElement.created() : super.created(); | |
99 | |
100 @override | |
101 attached() { | |
102 super.attached(); | |
103 _r.enable(); | |
104 _refresh(); | |
105 _gcSubscription = _events.onGCEvent.listen((e) { | |
106 if (_autoRefresh && (e.isolate.id == _isolate.id)) { | |
107 _refresh(); | |
108 } | |
109 }); | |
110 } | |
111 | |
112 @override | |
113 detached() { | |
114 super.detached(); | |
115 _r.disable(notify: true); | |
116 children = []; | |
117 _gcSubscription.cancel(); | |
118 } | |
119 | |
120 void render() { | |
121 children = [ | |
122 navBar([ | |
123 new NavRefreshElement( | |
124 label: 'Download', disabled: _profile == null, queue: _r.queue) | |
125 ..onRefresh.listen((_) => _downloadCSV()), | |
126 new NavRefreshElement(label: 'Reset Accumulator', queue: _r.queue) | |
127 ..onRefresh.listen((_) => _refresh(reset: true)), | |
128 new NavRefreshElement(label: 'GC', queue: _r.queue) | |
129 ..onRefresh.listen((_) => _refresh(gc: true)), | |
130 new NavRefreshElement(queue: _r.queue) | |
131 ..onRefresh.listen((_) => _refresh()), | |
132 new DivElement() | |
133 ..classes = ['nav-option'] | |
134 ..children = [ | |
135 new CheckboxInputElement() | |
136 ..id = 'allocation-profile-auto-refresh' | |
137 ..checked = _autoRefresh | |
138 ..onChange.listen((_) => _autoRefresh = !_autoRefresh), | |
139 new LabelElement() | |
140 ..htmlFor = 'allocation-profile-auto-refresh' | |
141 ..text = 'Auto-refresh on GC' | |
142 ], | |
143 new NavNotifyElement(_notifications, queue: _r.queue) | |
144 ]), | |
145 new DivElement() | |
146 ..classes = ['content-centered-big'] | |
147 ..children = [ | |
148 new HeadingElement.h2()..text = 'Allocation Profile', | |
149 new HRElement() | |
150 ] | |
151 ]; | |
152 if (_profile == null) { | |
153 children.addAll([ | |
154 new DivElement() | |
155 ..classes = ['content-centered-big'] | |
156 ..children = [new HeadingElement.h2()..text = 'Loading...'] | |
157 ]); | |
158 } else { | |
159 final newChartHost = new DivElement()..classes = ['host']; | |
160 final newChartLegend = new DivElement()..classes = ['legend']; | |
161 final oldChartHost = new DivElement()..classes = ['host']; | |
162 final oldChartLegend = new DivElement()..classes = ['legend']; | |
163 children.addAll([ | |
164 new DivElement() | |
165 ..classes = ['content-centered-big'] | |
166 ..children = _isCompacted | |
167 ? [] | |
168 : [ | |
169 new DivElement() | |
170 ..classes = ['memberList'] | |
171 ..children = [ | |
172 new DivElement() | |
173 ..classes = ['memberItem'] | |
174 ..children = [ | |
175 new DivElement() | |
176 ..classes = ['memberName'] | |
177 ..text = 'last forced GC at', | |
178 new DivElement() | |
179 ..classes = ['memberValue'] | |
180 ..text = _profile.lastServiceGC == null | |
181 ? '---' | |
182 : '${_profile.lastServiceGC}', | |
183 ], | |
184 new DivElement() | |
185 ..classes = ['memberItem'] | |
186 ..children = [ | |
187 new DivElement() | |
188 ..classes = ['memberName'] | |
189 ..text = 'last accumulator reset at', | |
190 new DivElement() | |
191 ..classes = ['memberValue'] | |
192 ..text = _profile.lastAccumulatorReset == null | |
193 ? '---' | |
194 : '${_profile.lastAccumulatorReset}', | |
195 ] | |
196 ], | |
197 new HRElement(), | |
198 ], | |
199 new DivElement() | |
200 ..classes = ['content-centered-big', 'compactable'] | |
201 ..children = [ | |
202 new DivElement() | |
203 ..classes = ['heap-space', 'left'] | |
204 ..children = _isCompacted | |
205 ? [ | |
206 new HeadingElement.h2() | |
207 ..text = 'New Generation ' | |
208 '(${_usedCaption(_profile.newSpace)})', | |
209 ] | |
210 : [ | |
211 new HeadingElement.h2()..text = 'New Generation', | |
212 new BRElement(), | |
213 new DivElement() | |
214 ..classes = ['memberList'] | |
215 ..children = _createSpaceMembers(_profile.newSpace), | |
216 new BRElement(), | |
217 new DivElement() | |
218 ..classes = ['chart'] | |
219 ..children = [newChartLegend, newChartHost] | |
220 ], | |
221 new DivElement() | |
222 ..classes = ['heap-space', 'right'] | |
223 ..children = _isCompacted | |
224 ? [ | |
225 new HeadingElement.h2() | |
226 ..text = '(${_usedCaption(_profile.oldSpace)}) ' | |
227 'Old Generation', | |
228 ] | |
229 : [ | |
230 new HeadingElement.h2()..text = 'Old Generation', | |
231 new BRElement(), | |
232 new DivElement() | |
233 ..classes = ['memberList'] | |
234 ..children = _createSpaceMembers(_profile.oldSpace), | |
235 new BRElement(), | |
236 new DivElement() | |
237 ..classes = ['chart'] | |
238 ..children = [oldChartLegend, oldChartHost] | |
239 ], | |
240 new ButtonElement() | |
241 ..classes = ['compact'] | |
242 ..text = _isCompacted ? 'expand ▼' : 'compact ▲' | |
243 ..onClick.listen((_) { | |
244 _isCompacted = !_isCompacted; | |
245 _r.dirty(); | |
246 }), | |
247 new HRElement() | |
248 ], | |
249 new DivElement() | |
250 ..classes = _isCompacted ? ['collection', 'expanded'] : ['collection'] | |
251 ..children = [ | |
252 new VirtualCollectionElement( | |
253 _createCollectionLine, _updateCollectionLine, | |
254 createHeader: _createCollectionHeader, | |
255 items: _profile.members.toList()..sort(_createSorter()), | |
256 queue: _r.queue) | |
257 ] | |
258 ]); | |
259 _renderGraph(newChartHost, newChartLegend, _profile.newSpace); | |
260 _renderGraph(oldChartHost, oldChartLegend, _profile.oldSpace); | |
261 } | |
262 } | |
263 | |
264 _createSorter() { | |
265 var getter; | |
266 switch (_sortingField) { | |
267 case _SortingField.accumulatedSize: | |
268 getter = _getAccumulatedSize; | |
269 break; | |
270 case _SortingField.accumulatedInstances: | |
271 getter = _getAccumulatedInstances; | |
272 break; | |
273 case _SortingField.currentSize: | |
274 getter = _getCurrentSize; | |
275 break; | |
276 case _SortingField.currentInstances: | |
277 getter = _getCurrentInstances; | |
278 break; | |
279 case _SortingField.newAccumulatedSize: | |
280 getter = _getNewAccumulatedSize; | |
281 break; | |
282 case _SortingField.newAccumulatedInstances: | |
283 getter = _getNewAccumulatedInstances; | |
284 break; | |
285 case _SortingField.newCurrentSize: | |
286 getter = _getNewCurrentSize; | |
287 break; | |
288 case _SortingField.newCurrentInstances: | |
289 getter = _getNewCurrentInstances; | |
290 break; | |
291 case _SortingField.oldAccumulatedSize: | |
292 getter = _getOldAccumulatedSize; | |
293 break; | |
294 case _SortingField.oldAccumulatedInstances: | |
295 getter = _getOldAccumulatedInstances; | |
296 break; | |
297 case _SortingField.oldCurrentSize: | |
298 getter = _getOldCurrentSize; | |
299 break; | |
300 case _SortingField.oldCurrentInstances: | |
301 getter = _getOldCurrentInstances; | |
302 break; | |
303 case _SortingField.className: | |
304 getter = (M.ClassHeapStats s) => s.clazz.name; | |
305 break; | |
306 } | |
307 switch (_sortingDirection) { | |
308 case _SortingDirection.ascending: | |
309 return (a, b) => getter(a).compareTo(getter(b)); | |
310 case _SortingDirection.descending: | |
311 return (a, b) => getter(b).compareTo(getter(a)); | |
312 } | |
313 } | |
314 | |
315 static Element _createCollectionLine() => new DivElement() | |
316 ..classes = ['collection-item'] | |
317 ..children = [ | |
318 new SpanElement() | |
319 ..classes = ['bytes'] | |
320 ..text = '0B', | |
321 new SpanElement() | |
322 ..classes = ['instances'] | |
323 ..text = '0', | |
324 new SpanElement() | |
325 ..classes = ['bytes'] | |
326 ..text = '0B', | |
327 new SpanElement() | |
328 ..classes = ['instances'] | |
329 ..text = '0', | |
330 new SpanElement() | |
331 ..classes = ['bytes'] | |
332 ..text = '0B', | |
333 new SpanElement() | |
334 ..classes = ['instances'] | |
335 ..text = '0', | |
336 new SpanElement() | |
337 ..classes = ['bytes'] | |
338 ..text = '0B', | |
339 new SpanElement() | |
340 ..classes = ['instances'] | |
341 ..text = '0', | |
342 new SpanElement() | |
343 ..classes = ['bytes'] | |
344 ..text = '0B', | |
345 new SpanElement() | |
346 ..classes = ['instances'] | |
347 ..text = '0', | |
348 new SpanElement() | |
349 ..classes = ['bytes'] | |
350 ..text = '0B', | |
351 new SpanElement() | |
352 ..classes = ['instances'] | |
353 ..text = '0', | |
354 new SpanElement()..classes = ['name'] | |
355 ]; | |
356 | |
357 Element _createCollectionHeader() => new DivElement() | |
358 ..children = [ | |
359 new DivElement() | |
360 ..classes = ['collection-item'] | |
361 ..children = [ | |
362 new SpanElement() | |
363 ..classes = ['group'] | |
364 ..text = 'Accumulated', | |
365 new SpanElement() | |
366 ..classes = ['group'] | |
367 ..text = 'Current', | |
368 new SpanElement() | |
369 ..classes = ['group'] | |
370 ..text = '(NEW) Accumulated', | |
371 new SpanElement() | |
372 ..classes = ['group'] | |
373 ..text = '(NEW) Current', | |
374 new SpanElement() | |
375 ..classes = ['group'] | |
376 ..text = '(OLD) Accumulated', | |
377 new SpanElement() | |
378 ..classes = ['group'] | |
379 ..text = '(OLD) Current', | |
380 ], | |
381 new DivElement() | |
382 ..classes = ['collection-item'] | |
383 ..children = [ | |
384 _createHeaderButton(const ['bytes'], 'Size', | |
385 _SortingField.accumulatedSize, _SortingDirection.descending), | |
386 _createHeaderButton(const ['instances'], 'Instances', | |
387 _SortingField.accumulatedInstances, _SortingDirection.descending), | |
388 _createHeaderButton(const ['bytes'], 'Size', | |
389 _SortingField.currentSize, _SortingDirection.descending), | |
390 _createHeaderButton(const ['instances'], 'Instances', | |
391 _SortingField.currentInstances, _SortingDirection.descending), | |
392 _createHeaderButton(const ['bytes'], 'Size', | |
393 _SortingField.newAccumulatedSize, _SortingDirection.descending), | |
394 _createHeaderButton( | |
395 const ['instances'], | |
396 'Instances', | |
397 _SortingField.newAccumulatedInstances, | |
398 _SortingDirection.descending), | |
399 _createHeaderButton(const ['bytes'], 'Size', | |
400 _SortingField.newCurrentSize, _SortingDirection.descending), | |
401 _createHeaderButton(const ['instances'], 'Instances', | |
402 _SortingField.newCurrentInstances, _SortingDirection.descending), | |
403 _createHeaderButton(const ['bytes'], 'Size', | |
404 _SortingField.oldAccumulatedSize, _SortingDirection.descending), | |
405 _createHeaderButton( | |
406 const ['instances'], | |
407 'Instances', | |
408 _SortingField.oldAccumulatedInstances, | |
409 _SortingDirection.descending), | |
410 _createHeaderButton(const ['bytes'], 'Size', | |
411 _SortingField.oldCurrentSize, _SortingDirection.descending), | |
412 _createHeaderButton(const ['instances'], 'Instances', | |
413 _SortingField.oldCurrentInstances, _SortingDirection.descending), | |
414 _createHeaderButton(const ['name'], 'Class', _SortingField.className, | |
415 _SortingDirection.ascending) | |
416 ], | |
417 ]; | |
418 | |
419 ButtonElement _createHeaderButton(List<String> classes, String text, | |
420 _SortingField field, _SortingDirection direction) => | |
421 new ButtonElement() | |
422 ..classes = classes | |
423 ..text = _sortingField != field | |
424 ? text | |
425 : _sortingDirection == _SortingDirection.ascending | |
426 ? '$text▼' | |
427 : '$text▲' | |
428 ..onClick.listen((_) => _setSorting(field, direction)); | |
429 | |
430 void _setSorting(_SortingField field, _SortingDirection defaultDirection) { | |
431 if (_sortingField == field) { | |
432 switch (_sortingDirection) { | |
433 case _SortingDirection.descending: | |
434 _sortingDirection = _SortingDirection.ascending; | |
435 break; | |
436 case _SortingDirection.ascending: | |
437 _sortingDirection = _SortingDirection.descending; | |
438 break; | |
439 } | |
440 } else { | |
441 _sortingDirection = defaultDirection; | |
442 _sortingField = field; | |
443 } | |
444 _r.dirty(); | |
445 } | |
446 | |
447 void _updateCollectionLine(Element e, M.ClassHeapStats item, index) { | |
448 e.children[0].text = Utils.formatSize(_getAccumulatedSize(item)); | |
449 e.children[1].text = '${_getAccumulatedInstances(item)}'; | |
450 e.children[2].text = Utils.formatSize(_getCurrentSize(item)); | |
451 e.children[3].text = '${_getCurrentInstances(item)}'; | |
452 e.children[4].text = Utils.formatSize(_getNewAccumulatedSize(item)); | |
453 e.children[5].text = '${_getNewAccumulatedInstances(item)}'; | |
454 e.children[6].text = Utils.formatSize(_getNewCurrentSize(item)); | |
455 e.children[7].text = '${_getNewCurrentInstances(item)}'; | |
456 e.children[8].text = Utils.formatSize(_getOldAccumulatedSize(item)); | |
457 e.children[9].text = '${_getOldAccumulatedInstances(item)}'; | |
458 e.children[10].text = Utils.formatSize(_getOldCurrentSize(item)); | |
459 e.children[11].text = '${_getOldCurrentInstances(item)}'; | |
460 e.children[12] = new ClassRefElement(_isolate, item.clazz, queue: _r.queue) | |
461 ..classes = ['name']; | |
462 Element.clickEvent.forTarget(e.children[12], useCapture: true).listen((e) { | |
463 e.preventDefault(); | |
464 _editor.sendObject(isolate, item.clazz); | |
465 window.close(); | |
466 }); | |
467 } | |
468 | |
469 static String _usedCaption(M.HeapSpace space) => | |
470 '${Utils.formatSize(space.used)}' | |
471 ' of ' | |
472 '${Utils.formatSize(space.capacity)}'; | |
473 | |
474 static List<Element> _createSpaceMembers(M.HeapSpace space) { | |
475 final used = _usedCaption(space); | |
476 final ext = '${Utils.formatSize(space.external)}'; | |
477 final collections = '${space.collections}'; | |
478 final avgCollectionTime = | |
479 '${Utils.formatDurationInMilliseconds(space.avgCollectionTime)} ms'; | |
480 final totalCollectionTime = | |
481 '${Utils.formatDurationInSeconds(space.totalCollectionTime)} secs'; | |
482 final avgCollectionPeriod = | |
483 '${Utils.formatDurationInMilliseconds(space.avgCollectionPeriod)} ms'; | |
484 return [ | |
485 new DivElement() | |
486 ..classes = ['memberItem'] | |
487 ..children = [ | |
488 new DivElement() | |
489 ..classes = ['memberName'] | |
490 ..text = 'used', | |
491 new DivElement() | |
492 ..classes = ['memberValue'] | |
493 ..text = used | |
494 ], | |
495 new DivElement() | |
496 ..classes = ['memberItem'] | |
497 ..children = [ | |
498 new DivElement() | |
499 ..classes = ['memberName'] | |
500 ..text = 'external', | |
501 new DivElement() | |
502 ..classes = ['memberValue'] | |
503 ..text = ext | |
504 ], | |
505 new DivElement() | |
506 ..classes = ['memberItem'] | |
507 ..children = [ | |
508 new DivElement() | |
509 ..classes = ['memberName'] | |
510 ..text = 'collections', | |
511 new DivElement() | |
512 ..classes = ['memberValue'] | |
513 ..text = collections | |
514 ], | |
515 new DivElement() | |
516 ..classes = ['memberItem'] | |
517 ..children = [ | |
518 new DivElement() | |
519 ..classes = ['memberName'] | |
520 ..text = 'average collection time', | |
521 new DivElement() | |
522 ..classes = ['memberValue'] | |
523 ..text = avgCollectionTime | |
524 ], | |
525 new DivElement() | |
526 ..classes = ['memberItem'] | |
527 ..children = [ | |
528 new DivElement() | |
529 ..classes = ['memberName'] | |
530 ..text = 'cumulative collection time', | |
531 new DivElement() | |
532 ..classes = ['memberValue'] | |
533 ..text = totalCollectionTime | |
534 ], | |
535 new DivElement() | |
536 ..classes = ['memberItem'] | |
537 ..children = [ | |
538 new DivElement() | |
539 ..classes = ['memberName'] | |
540 ..text = 'average time between collections', | |
541 new DivElement() | |
542 ..classes = ['memberValue'] | |
543 ..text = avgCollectionPeriod | |
544 ] | |
545 ]; | |
546 } | |
547 | |
548 static final _columns = [ | |
549 new ChartColumnSpec(label: 'Type', type: ChartColumnSpec.TYPE_STRING), | |
550 new ChartColumnSpec(label: 'Size', formatter: (v) => v.toString()) | |
551 ]; | |
552 | |
553 static void _renderGraph(Element host, Element legend, M.HeapSpace space) { | |
554 final series = [ | |
555 new ChartSeries("Work", [1], new PieChartRenderer(sortDataByValue: false)) | |
556 ]; | |
557 final rect = host.getBoundingClientRect(); | |
558 final minSize = new Rect.size(rect.width, rect.height); | |
559 final config = new ChartConfig(series, [0]) | |
560 ..minimumSize = minSize | |
561 ..legend = new ChartLegend(legend, showValues: true); | |
562 final data = new ChartData(_columns, [ | |
563 ['Used', space.used], | |
564 ['Free', space.capacity - space.used], | |
565 ['External', space.external] | |
566 ]); | |
567 | |
568 new LayoutArea(host, data, config, | |
569 state: new ChartState(), autoUpdate: true) | |
570 ..draw(); | |
571 } | |
572 | |
573 Future _refresh({bool gc: false, bool reset: false}) async { | |
574 _profile = null; | |
575 _r.dirty(); | |
576 _profile = await _repository.get(_isolate, gc: gc, reset: reset); | |
577 _r.dirty(); | |
578 } | |
579 | |
580 void _downloadCSV() { | |
581 assert(_profile != null); | |
582 final header = [ | |
583 '"Accumulator Size"', | |
584 '"Accumulator Instances"', | |
585 '"Current Size"', | |
586 '"Current Instances"', | |
587 '"(NEW) Accumulator Size"', | |
588 '"(NEW) Accumulator Instances"', | |
589 '"(NEW) Current Size"', | |
590 '"(NEW) Current Instances"', | |
591 '"(OLD) Accumulator Size"', | |
592 '"(OLD) Accumulator Instances"', | |
593 '"(OLD) Current Size"', | |
594 '"(OLD) Current Instances"', | |
595 'Class' | |
596 ].join(',') + | |
597 '\n'; | |
598 AnchorElement tl = document.createElement('a'); | |
599 tl | |
600 ..attributes['href'] = 'data:text/plain;charset=utf-8,' + | |
601 Uri.encodeComponent(header + | |
602 (_profile.members.toList()..sort(_createSorter())) | |
603 .map(_csvOut) | |
604 .join('\n')) | |
605 ..attributes['download'] = 'heap-profile.csv' | |
606 ..click(); | |
607 } | |
608 | |
609 static _csvOut(M.ClassHeapStats s) { | |
610 return [ | |
611 _getAccumulatedSize(s), | |
612 _getAccumulatedInstances(s), | |
613 _getCurrentSize(s), | |
614 _getCurrentInstances(s), | |
615 _getNewAccumulatedSize(s), | |
616 _getNewAccumulatedInstances(s), | |
617 _getNewCurrentSize(s), | |
618 _getNewCurrentInstances(s), | |
619 _getOldAccumulatedSize(s), | |
620 _getOldAccumulatedInstances(s), | |
621 _getOldCurrentSize(s), | |
622 _getOldCurrentInstances(s), | |
623 s.clazz.name | |
624 ].join(','); | |
625 } | |
626 | |
627 static int _getAccumulatedSize(M.ClassHeapStats s) => | |
628 s.newSpace.accumulated.bytes + s.oldSpace.accumulated.bytes; | |
629 static int _getAccumulatedInstances(M.ClassHeapStats s) => | |
630 s.newSpace.accumulated.instances + s.oldSpace.accumulated.instances; | |
631 static int _getCurrentSize(M.ClassHeapStats s) => | |
632 s.newSpace.current.bytes + s.oldSpace.current.bytes; | |
633 static int _getCurrentInstances(M.ClassHeapStats s) => | |
634 s.newSpace.current.instances + s.oldSpace.current.instances; | |
635 static int _getNewAccumulatedSize(M.ClassHeapStats s) => | |
636 s.newSpace.accumulated.bytes; | |
637 static int _getNewAccumulatedInstances(M.ClassHeapStats s) => | |
638 s.newSpace.accumulated.instances; | |
639 static int _getNewCurrentSize(M.ClassHeapStats s) => s.newSpace.current.bytes; | |
640 static int _getNewCurrentInstances(M.ClassHeapStats s) => | |
641 s.newSpace.current.instances; | |
642 static int _getOldAccumulatedSize(M.ClassHeapStats s) => | |
643 s.oldSpace.accumulated.bytes; | |
644 static int _getOldAccumulatedInstances(M.ClassHeapStats s) => | |
645 s.oldSpace.accumulated.instances; | |
646 static int _getOldCurrentSize(M.ClassHeapStats s) => s.oldSpace.current.bytes; | |
647 static int _getOldCurrentInstances(M.ClassHeapStats s) => | |
648 s.oldSpace.current.instances; | |
649 } | |
OLD | NEW |