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

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

Issue 3009743003: [observatory] Add an "ownership" analysis for the heap snapshot. (Closed)
Patch Set: . Created 3 years, 3 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
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/helpers/uris.dart';
21 import 'package:observatory/src/elements/nav/isolate_menu.dart'; 21 import 'package:observatory/src/elements/nav/isolate_menu.dart';
22 import 'package:observatory/src/elements/nav/notify.dart'; 22 import 'package:observatory/src/elements/nav/notify.dart';
23 import 'package:observatory/src/elements/nav/refresh.dart'; 23 import 'package:observatory/src/elements/nav/refresh.dart';
24 import 'package:observatory/src/elements/nav/top_menu.dart'; 24 import 'package:observatory/src/elements/nav/top_menu.dart';
25 import 'package:observatory/src/elements/nav/vm_menu.dart'; 25 import 'package:observatory/src/elements/nav/vm_menu.dart';
26 import 'package:observatory/utils.dart'; 26 import 'package:observatory/utils.dart';
27 27
28 enum HeapSnapshotTreeMode { dominatorTree, mergedDominatorTree, groupByClass } 28 enum HeapSnapshotTreeMode {
29 dominatorTree,
30 mergedDominatorTree,
31 ownershipTable,
32 groupByClass
33 }
29 34
30 class HeapSnapshotElement extends HtmlElement implements Renderable { 35 class HeapSnapshotElement extends HtmlElement implements Renderable {
31 static const tag = 36 static const tag =
32 const Tag<HeapSnapshotElement>('heap-snapshot', dependencies: const [ 37 const Tag<HeapSnapshotElement>('heap-snapshot', dependencies: const [
33 ClassRefElement.tag, 38 ClassRefElement.tag,
34 NavTopMenuElement.tag, 39 NavTopMenuElement.tag,
35 NavVMMenuElement.tag, 40 NavVMMenuElement.tag,
36 NavIsolateMenuElement.tag, 41 NavIsolateMenuElement.tag,
37 NavRefreshElement.tag, 42 NavRefreshElement.tag,
38 NavNotifyElement.tag, 43 NavNotifyElement.tag,
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 final text = 'A heap dominator tree, where siblings with the same class' 292 final text = 'A heap dominator tree, where siblings with the same class'
288 ' have been merged into a single node.'; 293 ' have been merged into a single node.';
289 report.addAll([ 294 report.addAll([
290 new DivElement() 295 new DivElement()
291 ..classes = ['content-centered-big', 'explanation'] 296 ..classes = ['content-centered-big', 'explanation']
292 ..text = text 297 ..text = text
293 ..title = text, 298 ..title = text,
294 _tree 299 _tree
295 ]); 300 ]);
296 break; 301 break;
302 case HeapSnapshotTreeMode.ownershipTable:
303 final items = _snapshot.ownershipClasses.toList();
304 items.sort((a, b) => b.size - a.size);
305 _tree = new VirtualTreeElement(_createOwnershipClass,
306 _updateOwnershipClass, _getChildrenOwnershipClass,
307 items: items, queue: _r.queue);
308 _tree.expand(_snapshot.dominatorTree);
309 report.add(_tree);
310 break;
297 case HeapSnapshotTreeMode.groupByClass: 311 case HeapSnapshotTreeMode.groupByClass:
298 final items = _snapshot.classReferences.toList(); 312 final items = _snapshot.classReferences.toList();
299 items.sort((a, b) => b.shallowSize - a.shallowSize); 313 items.sort((a, b) => b.shallowSize - a.shallowSize);
300 _tree = new VirtualTreeElement( 314 _tree = new VirtualTreeElement(
301 _createGroup, _updateGroup, _getChildrenGroup, 315 _createGroup, _updateGroup, _getChildrenGroup,
302 items: items, queue: _r.queue); 316 items: items, queue: _r.queue);
303 _tree.expand(_snapshot.dominatorTree); 317 _tree.expand(_snapshot.dominatorTree);
304 report.add(_tree); 318 report.add(_tree);
305 break; 319 break;
306 default: 320 default:
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 new ButtonElement() 370 new ButtonElement()
357 ..classes = ['expander'] 371 ..classes = ['expander']
358 ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)), 372 ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
359 new SpanElement() 373 new SpanElement()
360 ..classes = ['count'] 374 ..classes = ['count']
361 ..title = 'shallow size', 375 ..title = 'shallow size',
362 new SpanElement()..classes = ['name'] 376 new SpanElement()..classes = ['name']
363 ]; 377 ];
364 } 378 }
365 379
380 static Element _createOwnershipClass(toggle) {
381 return new DivElement()
382 ..classes = ['tree-item']
383 ..children = [
384 new SpanElement()
385 ..classes = ['size']
386 ..title = 'size',
387 new SpanElement()..classes = ['name']
388 ];
389 }
390
366 static const int kMaxChildren = 100; 391 static const int kMaxChildren = 100;
367 static const int kMinRetainedSize = 4096; 392 static const int kMinRetainedSize = 4096;
368 393
369 static _getChildrenDominator(M.HeapSnapshotDominatorNode node) { 394 static _getChildrenDominator(M.HeapSnapshotDominatorNode node) {
370 final list = node.children.toList(); 395 final list = node.children.toList();
371 list.sort((a, b) => b.retainedSize - a.retainedSize); 396 list.sort((a, b) => b.retainedSize - a.retainedSize);
372 return list 397 return list
373 .where((child) => child.retainedSize >= kMinRetainedSize) 398 .where((child) => child.retainedSize >= kMinRetainedSize)
374 .take(kMaxChildren); 399 .take(kMaxChildren);
375 } 400 }
(...skipping 10 matching lines...) Expand all
386 if (item is M.HeapSnapshotClassReferences) { 411 if (item is M.HeapSnapshotClassReferences) {
387 if (item.inbounds.isNotEmpty || item.outbounds.isNotEmpty) { 412 if (item.inbounds.isNotEmpty || item.outbounds.isNotEmpty) {
388 return [item.inbounds, item.outbounds]; 413 return [item.inbounds, item.outbounds];
389 } 414 }
390 } else if (item is Iterable) { 415 } else if (item is Iterable) {
391 return item.toList()..sort((a, b) => b.shallowSize - a.shallowSize); 416 return item.toList()..sort((a, b) => b.shallowSize - a.shallowSize);
392 } 417 }
393 return const []; 418 return const [];
394 } 419 }
395 420
421 static _getChildrenOwnershipClass(item) {
422 return const [];
423 }
424
396 void _updateDominator( 425 void _updateDominator(
397 HtmlElement element, M.HeapSnapshotDominatorNode node, int depth) { 426 HtmlElement element, M.HeapSnapshotDominatorNode node, int depth) {
398 element.children[0].text = Utils.formatSize(node.retainedSize); 427 element.children[0].text = Utils.formatSize(node.retainedSize);
399 _updateLines(element.children[1].children, depth); 428 _updateLines(element.children[1].children, depth);
400 if (_getChildrenDominator(node).isNotEmpty) { 429 if (_getChildrenDominator(node).isNotEmpty) {
401 element.children[2].text = _tree.isExpanded(node) ? '▼' : '►'; 430 element.children[2].text = _tree.isExpanded(node) ? '▼' : '►';
402 } else { 431 } else {
403 element.children[2].text = ''; 432 element.children[2].text = '';
404 } 433 }
405 element.children[3].text = 434 element.children[3].text =
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 ]; 532 ];
504 } else if (item is M.HeapSnapshotClassOutbound) { 533 } else if (item is M.HeapSnapshotClassOutbound) {
505 element.children[3]..text = '${item.count} references to instances of '; 534 element.children[3]..text = '${item.count} references to instances of ';
506 element.children[4].children = [ 535 element.children[4].children = [
507 new ClassRefElement(_isolate, item.target, queue: _r.queue) 536 new ClassRefElement(_isolate, item.target, queue: _r.queue)
508 ]; 537 ];
509 } 538 }
510 } 539 }
511 } 540 }
512 541
542 void _updateOwnershipClass(HtmlElement element, item, int depth) {
543 _updateLines(element.children[1].children, depth);
544 element.children[0].text = Utils.formatSize(item.size);
545 element.children[1] =
546 new ClassRefElement(_isolate, item.clazz, queue: _r.queue)
547 ..classes = ['name'];
548 }
549
513 static _updateLines(List<Element> lines, int n) { 550 static _updateLines(List<Element> lines, int n) {
514 n = Math.max(0, n); 551 n = Math.max(0, n);
515 while (lines.length > n) { 552 while (lines.length > n) {
516 lines.removeLast(); 553 lines.removeLast();
517 } 554 }
518 while (lines.length < n) { 555 while (lines.length < n) {
519 lines.add(new SpanElement()); 556 lines.add(new SpanElement());
520 } 557 }
521 } 558 }
522 559
(...skipping 24 matching lines...) Expand all
547 }) 584 })
548 ]; 585 ];
549 } 586 }
550 587
551 static String modeToString(HeapSnapshotTreeMode mode) { 588 static String modeToString(HeapSnapshotTreeMode mode) {
552 switch (mode) { 589 switch (mode) {
553 case HeapSnapshotTreeMode.dominatorTree: 590 case HeapSnapshotTreeMode.dominatorTree:
554 return 'Dominator tree'; 591 return 'Dominator tree';
555 case HeapSnapshotTreeMode.mergedDominatorTree: 592 case HeapSnapshotTreeMode.mergedDominatorTree:
556 return 'Dominator tree (merged siblings by class)'; 593 return 'Dominator tree (merged siblings by class)';
594 case HeapSnapshotTreeMode.ownershipTable:
595 return 'Ownership table';
557 case HeapSnapshotTreeMode.groupByClass: 596 case HeapSnapshotTreeMode.groupByClass:
558 return 'Group by class'; 597 return 'Group by class';
559 } 598 }
560 throw new Exception('Unknown HeapSnapshotTreeMode'); 599 throw new Exception('Unknown HeapSnapshotTreeMode');
561 } 600 }
562 601
563 List<Element> _createModeSelect() { 602 List<Element> _createModeSelect() {
564 var s; 603 var s;
565 return [ 604 return [
566 s = new SelectElement() 605 s = new SelectElement()
567 ..classes = ['analysis-select'] 606 ..classes = ['analysis-select']
568 ..value = modeToString(_mode) 607 ..value = modeToString(_mode)
569 ..children = HeapSnapshotTreeMode.values.map((mode) { 608 ..children = HeapSnapshotTreeMode.values.map((mode) {
570 return new OptionElement( 609 return new OptionElement(
571 value: modeToString(mode), selected: _mode == mode) 610 value: modeToString(mode), selected: _mode == mode)
572 ..text = modeToString(mode); 611 ..text = modeToString(mode);
573 }).toList(growable: false) 612 }).toList(growable: false)
574 ..onChange.listen((_) { 613 ..onChange.listen((_) {
575 _mode = HeapSnapshotTreeMode.values[s.selectedIndex]; 614 _mode = HeapSnapshotTreeMode.values[s.selectedIndex];
576 _r.dirty(); 615 _r.dirty();
577 }) 616 })
578 ]; 617 ];
579 } 618 }
580 } 619 }
OLDNEW
« no previous file with comments | « runtime/observatory/lib/object_graph.dart ('k') | runtime/observatory/lib/src/heap_snapshot/heap_snapshot.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698