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

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

Issue 2502283003: Add a version of heap snapshots that use only fields and stack frames as roots and only include ins… (Closed)
Patch Set: . Created 4 years, 1 month 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
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 5 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
6 // for details. All rights reserved. Use of this source code is governed by a 6 // for details. All rights reserved. Use of this source code is governed by a
7 // BSD-style license that can be found in the LICENSE file. 7 // BSD-style license that can be found in the LICENSE file.
8 8
9 import 'dart:async'; 9 import 'dart:async';
10 import 'dart:html'; 10 import 'dart:html';
11 import 'dart:math' as Math; 11 import 'dart:math' as Math;
12 import 'package:observatory/models.dart' as M; 12 import 'package:observatory/models.dart' as M;
13 import 'package:observatory/src/elements/class_ref.dart'; 13 import 'package:observatory/src/elements/class_ref.dart';
14 import 'package:observatory/src/elements/containers/virtual_tree.dart'; 14 import 'package:observatory/src/elements/containers/virtual_tree.dart';
15 import 'package:observatory/src/elements/helpers/any_ref.dart'; 15 import 'package:observatory/src/elements/helpers/any_ref.dart';
16 import 'package:observatory/src/elements/helpers/nav_bar.dart'; 16 import 'package:observatory/src/elements/helpers/nav_bar.dart';
17 import 'package:observatory/src/elements/helpers/nav_menu.dart'; 17 import 'package:observatory/src/elements/helpers/nav_menu.dart';
18 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; 18 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
19 import 'package:observatory/src/elements/helpers/tag.dart'; 19 import 'package:observatory/src/elements/helpers/tag.dart';
20 import 'package:observatory/src/elements/helpers/uris.dart';
20 import 'package:observatory/src/elements/nav/isolate_menu.dart'; 21 import 'package:observatory/src/elements/nav/isolate_menu.dart';
21 import 'package:observatory/src/elements/nav/notify.dart'; 22 import 'package:observatory/src/elements/nav/notify.dart';
22 import 'package:observatory/src/elements/nav/refresh.dart'; 23 import 'package:observatory/src/elements/nav/refresh.dart';
23 import 'package:observatory/src/elements/nav/top_menu.dart'; 24 import 'package:observatory/src/elements/nav/top_menu.dart';
24 import 'package:observatory/src/elements/nav/vm_menu.dart'; 25 import 'package:observatory/src/elements/nav/vm_menu.dart';
25 import 'package:observatory/utils.dart'; 26 import 'package:observatory/utils.dart';
26 27
28 enum HeapSnapshotRoots { user, vm }
27 enum HeapSnapshotTreeMode { dominatorTree, mergedDominatorTree, groupByClass } 29 enum HeapSnapshotTreeMode { dominatorTree, mergedDominatorTree, groupByClass }
28 30
29 class HeapSnapshotElement extends HtmlElement implements Renderable { 31 class HeapSnapshotElement extends HtmlElement implements Renderable {
30 static const tag = 32 static const tag =
31 const Tag<HeapSnapshotElement>('heap-snapshot', dependencies: const [ 33 const Tag<HeapSnapshotElement>('heap-snapshot', dependencies: const [
32 ClassRefElement.tag, 34 ClassRefElement.tag,
33 NavTopMenuElement.tag, 35 NavTopMenuElement.tag,
34 NavVMMenuElement.tag, 36 NavVMMenuElement.tag,
35 NavIsolateMenuElement.tag, 37 NavIsolateMenuElement.tag,
36 NavRefreshElement.tag, 38 NavRefreshElement.tag,
37 NavNotifyElement.tag, 39 NavNotifyElement.tag,
38 VirtualTreeElement.tag, 40 VirtualTreeElement.tag,
39 ]); 41 ]);
40 42
41 RenderingScheduler<HeapSnapshotElement> _r; 43 RenderingScheduler<HeapSnapshotElement> _r;
42 44
43 Stream<RenderedEvent<HeapSnapshotElement>> get onRendered => _r.onRendered; 45 Stream<RenderedEvent<HeapSnapshotElement>> get onRendered => _r.onRendered;
44 46
45 M.VM _vm; 47 M.VM _vm;
46 M.IsolateRef _isolate; 48 M.IsolateRef _isolate;
47 M.EventRepository _events; 49 M.EventRepository _events;
48 M.NotificationRepository _notifications; 50 M.NotificationRepository _notifications;
49 M.HeapSnapshotRepository _snapshots; 51 M.HeapSnapshotRepository _snapshots;
50 M.InstanceRepository _instances; 52 M.InstanceRepository _instances;
51 M.HeapSnapshot _snapshot; 53 M.HeapSnapshot _snapshot;
52 Stream<M.HeapSnapshotLoadingProgressEvent> _progressStream; 54 Stream<M.HeapSnapshotLoadingProgressEvent> _progressStream;
53 M.HeapSnapshotLoadingProgress _progress; 55 M.HeapSnapshotLoadingProgress _progress;
56 HeapSnapshotRoots _roots = HeapSnapshotRoots.user;
54 HeapSnapshotTreeMode _mode = HeapSnapshotTreeMode.dominatorTree; 57 HeapSnapshotTreeMode _mode = HeapSnapshotTreeMode.dominatorTree;
55 58
56 M.IsolateRef get isolate => _isolate; 59 M.IsolateRef get isolate => _isolate;
57 M.NotificationRepository get notifications => _notifications; 60 M.NotificationRepository get notifications => _notifications;
58 M.HeapSnapshotRepository get profiles => _snapshots; 61 M.HeapSnapshotRepository get profiles => _snapshots;
59 M.VMRef get vm => _vm; 62 M.VMRef get vm => _vm;
60 63
61 factory HeapSnapshotElement( 64 factory HeapSnapshotElement(
62 M.VM vm, 65 M.VM vm,
63 M.IsolateRef isolate, 66 M.IsolateRef isolate,
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 break; 134 break;
132 case M.HeapSnapshotLoadingStatus.loaded: 135 case M.HeapSnapshotLoadingStatus.loaded:
133 content.addAll(_createReport()); 136 content.addAll(_createReport());
134 break; 137 break;
135 } 138 }
136 children = content; 139 children = content;
137 } 140 }
138 141
139 Future _refresh() async { 142 Future _refresh() async {
140 _progress = null; 143 _progress = null;
141 _progressStream = _snapshots.get(isolate); 144 _progressStream = _snapshots.get(isolate,
145 roots: rootsToString(_roots),
146 gc: true);
142 _r.dirty(); 147 _r.dirty();
143 _progressStream.listen((e) { 148 _progressStream.listen((e) {
144 _progress = e.progress; 149 _progress = e.progress;
145 _r.dirty(); 150 _r.dirty();
146 }); 151 });
147 _progress = (await _progressStream.first).progress; 152 _progress = (await _progressStream.first).progress;
148 _r.dirty(); 153 _r.dirty();
149 if (M.isHeapSnapshotProgressRunning(_progress.status)) { 154 if (M.isHeapSnapshotProgressRunning(_progress.status)) {
150 _progress = (await _progressStream.last).progress; 155 _progress = (await _progressStream.last).progress;
151 _snapshot = _progress.snapshot; 156 _snapshot = _progress.snapshot;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 ..text = 'Size ', 231 ..text = 'Size ',
227 new DivElement() 232 new DivElement()
228 ..classes = ['memberName'] 233 ..classes = ['memberName']
229 ..text = Utils.formatSize(_snapshot.size) 234 ..text = Utils.formatSize(_snapshot.size)
230 ], 235 ],
231 new DivElement() 236 new DivElement()
232 ..classes = ['memberItem'] 237 ..classes = ['memberItem']
233 ..children = [ 238 ..children = [
234 new DivElement() 239 new DivElement()
235 ..classes = ['memberName'] 240 ..classes = ['memberName']
241 ..text = 'Roots ',
242 new DivElement()
243 ..classes = ['memberName']
244 ..children = _createRootsSelect()
245 ],
246 new DivElement()
247 ..classes = ['memberItem']
248 ..children = [
249 new DivElement()
250 ..classes = ['memberName']
236 ..text = 'Analysis ', 251 ..text = 'Analysis ',
237 new DivElement() 252 new DivElement()
238 ..classes = ['memberName'] 253 ..classes = ['memberName']
239 ..children = _createModeSelect() 254 ..children = _createModeSelect()
240 ] 255 ]
241 ] 256 ]
242 ], 257 ],
243 ]; 258 ];
244 switch (_mode) { 259 switch (_mode) {
245 case HeapSnapshotTreeMode.dominatorTree: 260 case HeapSnapshotTreeMode.dominatorTree:
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 element.children[2].text = _tree.isExpanded(node) ? '▼' : '►'; 404 element.children[2].text = _tree.isExpanded(node) ? '▼' : '►';
390 } else { 405 } else {
391 element.children[2].text = ''; 406 element.children[2].text = '';
392 } 407 }
393 element.children[3].text = 408 element.children[3].text =
394 Utils.formatPercentNormalized(node.retainedSize * 1.0 / _snapshot.size); 409 Utils.formatPercentNormalized(node.retainedSize * 1.0 / _snapshot.size);
395 final wrapper = new SpanElement() 410 final wrapper = new SpanElement()
396 ..classes = ['name'] 411 ..classes = ['name']
397 ..text = 'Loading...'; 412 ..text = 'Loading...';
398 element.children[4] = wrapper; 413 element.children[4] = wrapper;
399 node.object.then((object) { 414 if (node.isStack) {
400 wrapper 415 wrapper
401 ..text = '' 416 ..text = ''
402 ..children = [anyRef(_isolate, object, _instances, queue: _r.queue)]; 417 ..children = [
403 }); 418 new AnchorElement(href: Uris.debugger(isolate))
419 ..text = 'stack frames'
420 ];
421 } else {
422 node.object.then((object) {
423 wrapper
424 ..text = ''
425 ..children = [anyRef(_isolate, object, _instances, queue: _r.queue)];
426 });
427 }
404 } 428 }
405 429
406 void _updateMergedDominator( 430 void _updateMergedDominator(
407 HtmlElement element, M.HeapSnapshotMergedDominatorNode node, int depth) { 431 HtmlElement element, M.HeapSnapshotMergedDominatorNode node, int depth) {
408 element.children[0].text = Utils.formatSize(node.retainedSize); 432 element.children[0].text = Utils.formatSize(node.retainedSize);
409 _updateLines(element.children[1].children, depth); 433 _updateLines(element.children[1].children, depth);
410 if (_getChildrenMergedDominator(node).isNotEmpty) { 434 if (_getChildrenMergedDominator(node).isNotEmpty) {
411 element.children[2].text = _tree.isExpanded(node) ? '▼' : '►'; 435 element.children[2].text = _tree.isExpanded(node) ? '▼' : '►';
412 } else { 436 } else {
413 element.children[2].text = ''; 437 element.children[2].text = '';
414 } 438 }
415 element.children[3].text = 439 element.children[3].text =
416 Utils.formatPercentNormalized(node.retainedSize * 1.0 / _snapshot.size); 440 Utils.formatPercentNormalized(node.retainedSize * 1.0 / _snapshot.size);
417 final wrapper = new SpanElement() 441 final wrapper = new SpanElement()
418 ..classes = ['name'] 442 ..classes = ['name']
419 ..text = 'Loading...'; 443 ..text = 'Loading...';
420 element.children[4] = wrapper; 444 element.children[4] = wrapper;
421 node.klass.then((klass) { 445 if (node.isStack) {
422 wrapper 446 wrapper
423 ..text = '' 447 ..text = ''
424 ..children = [ 448 ..children = [
425 new SpanElement()..text = '${node.instanceCount} instances of ', 449 new AnchorElement(href: Uris.debugger(isolate))
426 anyRef(_isolate, klass, _instances, queue: _r.queue) 450 ..text = 'stack frames'
427 ]; 451 ];
428 }); 452 } else {
453 node.klass.then((klass) {
454 wrapper
455 ..text = ''
456 ..children = [
457 new SpanElement()..text = '${node.instanceCount} instances of ',
458 anyRef(_isolate, klass, _instances, queue: _r.queue)
459 ];
460 });
461 }
429 } 462 }
430 463
431 void _updateGroup(HtmlElement element, item, int depth) { 464 void _updateGroup(HtmlElement element, item, int depth) {
432 _updateLines(element.children[1].children, depth); 465 _updateLines(element.children[1].children, depth);
433 if (item is M.HeapSnapshotClassReferences) { 466 if (item is M.HeapSnapshotClassReferences) {
434 element.children[0].text = Utils.formatSize(item.shallowSize); 467 element.children[0].text = Utils.formatSize(item.shallowSize);
435 element.children[2].text = _tree.isExpanded(item) ? '▼' : '►'; 468 element.children[2].text = _tree.isExpanded(item) ? '▼' : '►';
436 element.children[3].text = '${item.instances} instances of '; 469 element.children[3].text = '${item.instances} instances of ';
437 element.children[4] = new ClassRefElement(_isolate, item.clazz, 470 element.children[4] = new ClassRefElement(_isolate, item.clazz,
438 queue: _r.queue)..classes = ['name']; 471 queue: _r.queue)..classes = ['name'];
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 static _updateLines(List<Element> lines, int n) { 513 static _updateLines(List<Element> lines, int n) {
481 n = Math.max(0, n); 514 n = Math.max(0, n);
482 while (lines.length > n) { 515 while (lines.length > n) {
483 lines.removeLast(); 516 lines.removeLast();
484 } 517 }
485 while (lines.length < n) { 518 while (lines.length < n) {
486 lines.add(new SpanElement()); 519 lines.add(new SpanElement());
487 } 520 }
488 } 521 }
489 522
523 static String rootsToString(HeapSnapshotRoots roots) {
524 switch (roots) {
525 case HeapSnapshotRoots.user:
526 return 'User';
527 case HeapSnapshotRoots.vm:
528 return 'VM';
529 }
530 throw new Exception('Unknown HeapSnapshotRoots');
531 }
532
533 List<Element> _createRootsSelect() {
534 var s;
535 return [
536 s = new SelectElement()
537 ..classes = ['roots-select']
538 ..value = rootsToString(_roots)
539 ..children = HeapSnapshotRoots.values.map((roots) {
540 return new OptionElement(
541 value: rootsToString(roots),
542 selected: _roots == roots)..text = rootsToString(roots);
543 }).toList(growable: false)
544 ..onChange.listen((_) {
545 _roots = HeapSnapshotRoots.values[s.selectedIndex];
546 _refresh();
547 })
548 ];
549 }
550
490 static String modeToString(HeapSnapshotTreeMode mode) { 551 static String modeToString(HeapSnapshotTreeMode mode) {
491 switch (mode) { 552 switch (mode) {
492 case HeapSnapshotTreeMode.dominatorTree: 553 case HeapSnapshotTreeMode.dominatorTree:
493 return 'Dominator tree'; 554 return 'Dominator tree';
494 case HeapSnapshotTreeMode.mergedDominatorTree: 555 case HeapSnapshotTreeMode.mergedDominatorTree:
495 return 'Dominator tree (merged siblings by class)'; 556 return 'Dominator tree (merged siblings by class)';
496 case HeapSnapshotTreeMode.groupByClass: 557 case HeapSnapshotTreeMode.groupByClass:
497 return 'Group by class'; 558 return 'Group by class';
498 } 559 }
499 throw new Exception('Unknown ProfileTreeMode'); 560 throw new Exception('Unknown HeapSnapshotTreeMode');
500 } 561 }
501 562
502 List<Element> _createModeSelect() { 563 List<Element> _createModeSelect() {
503 var s; 564 var s;
504 return [ 565 return [
505 s = new SelectElement() 566 s = new SelectElement()
506 ..classes = ['analysis-select'] 567 ..classes = ['analysis-select']
507 ..value = modeToString(_mode) 568 ..value = modeToString(_mode)
508 ..children = HeapSnapshotTreeMode.values.map((mode) { 569 ..children = HeapSnapshotTreeMode.values.map((mode) {
509 return new OptionElement( 570 return new OptionElement(
510 value: modeToString(mode), 571 value: modeToString(mode),
511 selected: _mode == mode)..text = modeToString(mode); 572 selected: _mode == mode)..text = modeToString(mode);
512 }).toList(growable: false) 573 }).toList(growable: false)
513 ..onChange.listen((_) { 574 ..onChange.listen((_) {
514 _mode = HeapSnapshotTreeMode.values[s.selectedIndex]; 575 _mode = HeapSnapshotTreeMode.values[s.selectedIndex];
515 _r.dirty(); 576 _r.dirty();
516 }) 577 })
517 ]; 578 ];
518 } 579 }
519 } 580 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698