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

Side by Side Diff: runtime/observatory/lib/src/service/object.dart

Issue 1124153006: Heap snapshot visualizations (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: sync Created 5 years, 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 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 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 part of service; 5 part of service;
6 6
7 /// An RpcException represents an exceptional event that happened 7 /// An RpcException represents an exceptional event that happened
8 /// while invoking an rpc. 8 /// while invoking an rpc.
9 abstract class RpcException implements Exception { 9 abstract class RpcException implements Exception {
10 RpcException(this.message); 10 RpcException(this.message);
(...skipping 761 matching lines...) Expand 10 before | Expand all | Expand 10 after
772 totalCollectionTimeInSeconds = heapMap['time']; 772 totalCollectionTimeInSeconds = heapMap['time'];
773 averageCollectionPeriodInMillis = heapMap['avgCollectionPeriodMillis']; 773 averageCollectionPeriodInMillis = heapMap['avgCollectionPeriodMillis'];
774 } 774 }
775 } 775 }
776 776
777 class HeapSnapshot { 777 class HeapSnapshot {
778 final ObjectGraph graph; 778 final ObjectGraph graph;
779 final DateTime timeStamp; 779 final DateTime timeStamp;
780 final Isolate isolate; 780 final Isolate isolate;
781 781
782 HeapSnapshot(this.isolate, ByteData data) : 782 HeapSnapshot(this.isolate, chunks, nodeCount) :
783 graph = new ObjectGraph(new ReadStream(data)), 783 graph = new ObjectGraph(chunks, nodeCount),
784 timeStamp = new DateTime.now() { 784 timeStamp = new DateTime.now();
785 }
786 785
787 List<Future<ServiceObject>> getMostRetained({int classId, int limit}) { 786 List<Future<ServiceObject>> getMostRetained({int classId, int limit}) {
788 var result = []; 787 var result = [];
789 for (var v in graph.getMostRetained(classId: classId, limit: limit)) { 788 for (var v in graph.getMostRetained(classId: classId, limit: limit)) {
790 var address = v.addressForWordSize(isolate.vm.architectureBits ~/ 8); 789 var address = v.addressForWordSize(isolate.vm.architectureBits ~/ 8);
791 result.add(isolate.getObjectByAddress(address.toRadixString(16)).then((obj ) { 790 result.add(isolate.getObjectByAddress(address.toRadixString(16)).then((obj ) {
792 obj.retainedSize = v.retainedSize; 791 obj.retainedSize = v.retainedSize;
793 return new Future(() => obj); 792 return new Future(() => obj);
794 })); 793 }));
795 } 794 }
796 return result; 795 return result;
797 } 796 }
798
799
800 } 797 }
801 798
802 /// State for a running isolate. 799 /// State for a running isolate.
803 class Isolate extends ServiceObjectOwner with Coverage { 800 class Isolate extends ServiceObjectOwner with Coverage {
804 @reflectable VM get vm => owner; 801 @reflectable VM get vm => owner;
805 @reflectable Isolate get isolate => this; 802 @reflectable Isolate get isolate => this;
806 @observable int number; 803 @observable int number;
807 @observable DateTime startTime; 804 @observable DateTime startTime;
808 @observable Duration get upTime => 805 @observable Duration get upTime =>
809 (new DateTime.now().difference(startTime)); 806 (new DateTime.now().difference(startTime));
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
850 } 847 }
851 848
852 /// Fetches and builds the class hierarchy for this isolate. Returns the 849 /// Fetches and builds the class hierarchy for this isolate. Returns the
853 /// Object class object. 850 /// Object class object.
854 Future<Class> getClassHierarchy() { 851 Future<Class> getClassHierarchy() {
855 return invokeRpc('getClassList', {}) 852 return invokeRpc('getClassList', {})
856 .then(_loadClasses) 853 .then(_loadClasses)
857 .then(_buildClassHierarchy); 854 .then(_buildClassHierarchy);
858 } 855 }
859 856
857 Future<List<Class>> getClassRefs() async {
858 ServiceMap classList = await invokeRpc('getClassList', {});
859 assert(classList.type == 'ClassList');
860 var classRefs = [];
861 for (var cls in classList['classes']) {
862 // Skip over non-class classes.
863 if (cls is Class) {
864 _classesByCid[cls.vmCid] = cls;
865 classRefs.add(cls);
866 }
867 }
868 return classRefs;
869 }
870
860 /// Given the class list, loads each class. 871 /// Given the class list, loads each class.
861 Future<List<Class>> _loadClasses(ServiceMap classList) { 872 Future<List<Class>> _loadClasses(ServiceMap classList) {
koda 2015/05/19 20:12:35 Is this one still needed?
rmacnak 2015/05/19 22:16:08 Used by getClassHierarchy.
862 assert(classList.type == 'ClassList'); 873 assert(classList.type == 'ClassList');
863 var futureClasses = []; 874 var futureClasses = [];
864 for (var cls in classList['classes']) { 875 for (var cls in classList['classes']) {
865 // Skip over non-class classes. 876 // Skip over non-class classes.
866 if (cls is Class) { 877 if (cls is Class) {
878 _classesByCid[cls.vmCid] = cls;
867 futureClasses.add(cls.load()); 879 futureClasses.add(cls.load());
868 } 880 }
869 } 881 }
870 return Future.wait(futureClasses); 882 return Future.wait(futureClasses);
871 } 883 }
872 884
873 /// Builds the class hierarchy and returns the Object class. 885 /// Builds the class hierarchy and returns the Object class.
874 Future<Class> _buildClassHierarchy(List<Class> classes) { 886 Future<Class> _buildClassHierarchy(List<Class> classes) {
875 rootClasses.clear(); 887 rootClasses.clear();
876 objectClass = null; 888 objectClass = null;
877 for (var cls in classes) { 889 for (var cls in classes) {
878 if (cls.superclass == null) { 890 if (cls.superclass == null) {
879 rootClasses.add(cls); 891 rootClasses.add(cls);
880 } 892 }
881 if ((cls.vmName == 'Object') && (cls.isPatch == false)) { 893 if ((cls.vmName == 'Object') && (cls.isPatch == false)) {
882 objectClass = cls; 894 objectClass = cls;
883 } 895 }
884 } 896 }
885 assert(objectClass != null); 897 assert(objectClass != null);
886 return new Future.value(objectClass); 898 return new Future.value(objectClass);
887 } 899 }
888 900
901 Class getClassByCid(int cid) => _classesByCid[cid];
902
889 ServiceObject getFromMap(ObservableMap map) { 903 ServiceObject getFromMap(ObservableMap map) {
890 if (map == null) { 904 if (map == null) {
891 return null; 905 return null;
892 } 906 }
893 var mapType = _stripRef(map['type']); 907 var mapType = _stripRef(map['type']);
894 if (mapType == 'Isolate') { 908 if (mapType == 'Isolate') {
895 // There are sometimes isolate refs in ServiceEvents. 909 // There are sometimes isolate refs in ServiceEvents.
896 return vm.getFromMap(map); 910 return vm.getFromMap(map);
897 } 911 }
898 String mapId = map['id']; 912 String mapId = map['id'];
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
931 }; 945 };
932 return isolate.invokeRpc('getObject', params); 946 return isolate.invokeRpc('getObject', params);
933 } 947 }
934 948
935 Future<ObservableMap> _fetchDirect() { 949 Future<ObservableMap> _fetchDirect() {
936 return invokeRpcNoUpgrade('getIsolate', {}); 950 return invokeRpcNoUpgrade('getIsolate', {});
937 } 951 }
938 952
939 @observable Class objectClass; 953 @observable Class objectClass;
940 @observable final rootClasses = new ObservableList<Class>(); 954 @observable final rootClasses = new ObservableList<Class>();
955 Map<int, Class> _classesByCid = new Map<int, Class>();
941 956
942 @observable Library rootLibrary; 957 @observable Library rootLibrary;
943 @observable ObservableList<Library> libraries = 958 @observable ObservableList<Library> libraries =
944 new ObservableList<Library>(); 959 new ObservableList<Library>();
945 @observable ObservableMap topFrame; 960 @observable ObservableMap topFrame;
946 961
947 @observable String name; 962 @observable String name;
948 @observable String vmName; 963 @observable String vmName;
949 @observable ServiceFunction entry; 964 @observable ServiceFunction entry;
950 965
951 @observable final Map<String, double> timers = 966 @observable final Map<String, double> timers =
952 toObservable(new Map<String, double>()); 967 toObservable(new Map<String, double>());
953 968
954 final HeapSpace newSpace = new HeapSpace(); 969 final HeapSpace newSpace = new HeapSpace();
955 final HeapSpace oldSpace = new HeapSpace(); 970 final HeapSpace oldSpace = new HeapSpace();
956 971
957 @observable String fileAndLine; 972 @observable String fileAndLine;
958 973
959 @observable DartError error; 974 @observable DartError error;
960 @observable HeapSnapshot latestSnapshot; 975 @observable HeapSnapshot latestSnapshot;
961 Completer<HeapSnapshot> _snapshotFetch; 976 StreamController _snapshotFetch;
977
978 var chunksInProgress;
962 979
963 void _loadHeapSnapshot(ServiceEvent event) { 980 void _loadHeapSnapshot(ServiceEvent event) {
964 latestSnapshot = new HeapSnapshot(this, event.data); 981 // Occasionally these actually arrive out of order.
982 var i = event.i;
983 var n = event.n;
984 if (chunksInProgress == null) {
985 chunksInProgress = new List(n);
986 }
987 chunksInProgress[i] = event.data;
988 _snapshotFetch.add("Receiving snapshot chunk ${i + 1} of $n...");
989
990 for (i = 0; i < n; i++) {
991 if (chunksInProgress[i] == null) return;
992 }
993
994 var chunks = chunksInProgress;
995 chunksInProgress = null;
996
997 latestSnapshot = new HeapSnapshot(this, chunks, event.nodeCount);
965 if (_snapshotFetch != null) { 998 if (_snapshotFetch != null) {
966 _snapshotFetch.complete(latestSnapshot); 999 latestSnapshot.graph.process(_snapshotFetch).then((graph) {
1000 _snapshotFetch.add(latestSnapshot);
1001 _snapshotFetch.close();
1002 });
967 } 1003 }
968 } 1004 }
969 1005
970 Future<HeapSnapshot> fetchHeapSnapshot() { 1006 Stream fetchHeapSnapshot() {
971 if (_snapshotFetch == null || _snapshotFetch.isCompleted) { 1007 if (_snapshotFetch == null || _snapshotFetch.isClosed) {
972 _snapshotFetch = new Completer<HeapSnapshot>(); 1008 _snapshotFetch = new StreamController();
973 isolate.invokeRpcNoUpgrade('requestHeapSnapshot', {}); 1009 isolate.invokeRpcNoUpgrade('requestHeapSnapshot', {});
974 } 1010 }
975 return _snapshotFetch.future; 1011 return _snapshotFetch.stream;
976 } 1012 }
977 1013
978 void updateHeapsFromMap(ObservableMap map) { 1014 void updateHeapsFromMap(ObservableMap map) {
979 newSpace.update(map['new']); 1015 newSpace.update(map['new']);
980 oldSpace.update(map['old']); 1016 oldSpace.update(map['old']);
981 } 1017 }
982 1018
983 void _update(ObservableMap map, bool mapIsRef) { 1019 void _update(ObservableMap map, bool mapIsRef) {
984 name = map['name']; 1020 name = map['name'];
985 vmName = map['name']; 1021 vmName = map['name'];
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
1417 } 1453 }
1418 1454
1419 @observable String eventType; 1455 @observable String eventType;
1420 @observable Breakpoint breakpoint; 1456 @observable Breakpoint breakpoint;
1421 @observable ServiceMap topFrame; 1457 @observable ServiceMap topFrame;
1422 @observable ServiceMap exception; 1458 @observable ServiceMap exception;
1423 @observable ServiceObject inspectee; 1459 @observable ServiceObject inspectee;
1424 @observable ByteData data; 1460 @observable ByteData data;
1425 @observable int count; 1461 @observable int count;
1426 @observable String reason; 1462 @observable String reason;
1463 int i, n, nodeCount;
koda 2015/05/19 20:12:35 Consider more descriptive names.
1427 1464
1428 @observable bool get isPauseEvent { 1465 @observable bool get isPauseEvent {
1429 return (eventType == kPauseStart || 1466 return (eventType == kPauseStart ||
1430 eventType == kPauseExit || 1467 eventType == kPauseExit ||
1431 eventType == kPauseBreakpoint || 1468 eventType == kPauseBreakpoint ||
1432 eventType == kPauseInterrupted || 1469 eventType == kPauseInterrupted ||
1433 eventType == kPauseException); 1470 eventType == kPauseException);
1434 } 1471 }
1435 1472
1436 void _update(ObservableMap map, bool mapIsRef) { 1473 void _update(ObservableMap map, bool mapIsRef) {
(...skipping 12 matching lines...) Expand all
1449 } 1486 }
1450 if (map['exception'] != null) { 1487 if (map['exception'] != null) {
1451 exception = map['exception']; 1488 exception = map['exception'];
1452 } 1489 }
1453 if (map['inspectee'] != null) { 1490 if (map['inspectee'] != null) {
1454 inspectee = map['inspectee']; 1491 inspectee = map['inspectee'];
1455 } 1492 }
1456 if (map['_data'] != null) { 1493 if (map['_data'] != null) {
1457 data = map['_data']; 1494 data = map['_data'];
1458 } 1495 }
1496 if (map['i'] != null) {
1497 i = map['i'];
1498 }
1499 if (map['n'] != null) {
1500 n = map['n'];
1501 }
1502 if (map['nodeCount'] != null) {
1503 nodeCount = map['nodeCount'];
1504 }
1459 if (map['count'] != null) { 1505 if (map['count'] != null) {
1460 count = map['count']; 1506 count = map['count'];
1461 } 1507 }
1462 } 1508 }
1463 1509
1464 String toString() { 1510 String toString() {
1465 if (data == null) { 1511 if (data == null) {
1466 return "ServiceEvent(owner='${owner.id}', type='${eventType}')"; 1512 return "ServiceEvent(owner='${owner.id}', type='${eventType}')";
1467 } else { 1513 } else {
1468 return "ServiceEvent(owner='${owner.id}', type='${eventType}', " 1514 return "ServiceEvent(owner='${owner.id}', type='${eventType}', "
(...skipping 1641 matching lines...) Expand 10 before | Expand all | Expand 10 after
3110 var v = list[i]; 3156 var v = list[i];
3111 if ((v is ObservableMap) && _isServiceMap(v)) { 3157 if ((v is ObservableMap) && _isServiceMap(v)) {
3112 list[i] = owner.getFromMap(v); 3158 list[i] = owner.getFromMap(v);
3113 } else if (v is ObservableList) { 3159 } else if (v is ObservableList) {
3114 _upgradeObservableList(v, owner); 3160 _upgradeObservableList(v, owner);
3115 } else if (v is ObservableMap) { 3161 } else if (v is ObservableMap) {
3116 _upgradeObservableMap(v, owner); 3162 _upgradeObservableMap(v, owner);
3117 } 3163 }
3118 } 3164 }
3119 } 3165 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698