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

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: 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) {
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 List<ByteData> _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 chunkIndex = event.chunkIndex;
983 var chunkCount = event.chunkCount;
984 if (_chunksInProgress == null) {
985 _chunksInProgress = new List(chunkCount);
986 }
987 _chunksInProgress[chunkIndex] = event.data;
988 _snapshotFetch.add("Receiving snapshot chunk ${chunkIndex + 1}"
989 " of $chunkCount...");
990
991 for (var i = 0; i < chunkCount; i++) {
992 if (_chunksInProgress[i] == null) return;
993 }
994
995 var loadedChunks = _chunksInProgress;
996 _chunksInProgress = null;
997
998 latestSnapshot = new HeapSnapshot(this, loadedChunks, event.nodeCount);
965 if (_snapshotFetch != null) { 999 if (_snapshotFetch != null) {
966 _snapshotFetch.complete(latestSnapshot); 1000 latestSnapshot.graph.process(_snapshotFetch).then((graph) {
1001 _snapshotFetch.add(latestSnapshot);
1002 _snapshotFetch.close();
1003 });
967 } 1004 }
968 } 1005 }
969 1006
970 Future<HeapSnapshot> fetchHeapSnapshot() { 1007 Stream fetchHeapSnapshot() {
971 if (_snapshotFetch == null || _snapshotFetch.isCompleted) { 1008 if (_snapshotFetch == null || _snapshotFetch.isClosed) {
972 _snapshotFetch = new Completer<HeapSnapshot>(); 1009 _snapshotFetch = new StreamController();
973 isolate.invokeRpcNoUpgrade('requestHeapSnapshot', {}); 1010 isolate.invokeRpcNoUpgrade('requestHeapSnapshot', {});
974 } 1011 }
975 return _snapshotFetch.future; 1012 return _snapshotFetch.stream;
976 } 1013 }
977 1014
978 void updateHeapsFromMap(ObservableMap map) { 1015 void updateHeapsFromMap(ObservableMap map) {
979 newSpace.update(map['new']); 1016 newSpace.update(map['new']);
980 oldSpace.update(map['old']); 1017 oldSpace.update(map['old']);
981 } 1018 }
982 1019
983 void _update(ObservableMap map, bool mapIsRef) { 1020 void _update(ObservableMap map, bool mapIsRef) {
984 name = map['name']; 1021 name = map['name'];
985 vmName = map['name']; 1022 vmName = map['name'];
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
1417 } 1454 }
1418 1455
1419 @observable String eventType; 1456 @observable String eventType;
1420 @observable Breakpoint breakpoint; 1457 @observable Breakpoint breakpoint;
1421 @observable ServiceMap topFrame; 1458 @observable ServiceMap topFrame;
1422 @observable ServiceMap exception; 1459 @observable ServiceMap exception;
1423 @observable ServiceObject inspectee; 1460 @observable ServiceObject inspectee;
1424 @observable ByteData data; 1461 @observable ByteData data;
1425 @observable int count; 1462 @observable int count;
1426 @observable String reason; 1463 @observable String reason;
1464 int chunkIndex, chunkCount, nodeCount;
1427 1465
1428 @observable bool get isPauseEvent { 1466 @observable bool get isPauseEvent {
1429 return (eventType == kPauseStart || 1467 return (eventType == kPauseStart ||
1430 eventType == kPauseExit || 1468 eventType == kPauseExit ||
1431 eventType == kPauseBreakpoint || 1469 eventType == kPauseBreakpoint ||
1432 eventType == kPauseInterrupted || 1470 eventType == kPauseInterrupted ||
1433 eventType == kPauseException); 1471 eventType == kPauseException);
1434 } 1472 }
1435 1473
1436 void _update(ObservableMap map, bool mapIsRef) { 1474 void _update(ObservableMap map, bool mapIsRef) {
(...skipping 12 matching lines...) Expand all
1449 } 1487 }
1450 if (map['exception'] != null) { 1488 if (map['exception'] != null) {
1451 exception = map['exception']; 1489 exception = map['exception'];
1452 } 1490 }
1453 if (map['inspectee'] != null) { 1491 if (map['inspectee'] != null) {
1454 inspectee = map['inspectee']; 1492 inspectee = map['inspectee'];
1455 } 1493 }
1456 if (map['_data'] != null) { 1494 if (map['_data'] != null) {
1457 data = map['_data']; 1495 data = map['_data'];
1458 } 1496 }
1497 if (map['chunkIndex'] != null) {
1498 chunkIndex = map['chunkIndex'];
1499 }
1500 if (map['chunkCount'] != null) {
1501 chunkCount = map['chunkCount'];
1502 }
1503 if (map['nodeCount'] != null) {
1504 nodeCount = map['nodeCount'];
1505 }
1459 if (map['count'] != null) { 1506 if (map['count'] != null) {
1460 count = map['count']; 1507 count = map['count'];
1461 } 1508 }
1462 } 1509 }
1463 1510
1464 String toString() { 1511 String toString() {
1465 if (data == null) { 1512 if (data == null) {
1466 return "ServiceEvent(owner='${owner.id}', type='${eventType}')"; 1513 return "ServiceEvent(owner='${owner.id}', type='${eventType}')";
1467 } else { 1514 } else {
1468 return "ServiceEvent(owner='${owner.id}', type='${eventType}', " 1515 return "ServiceEvent(owner='${owner.id}', type='${eventType}', "
(...skipping 1641 matching lines...) Expand 10 before | Expand all | Expand 10 after
3110 var v = list[i]; 3157 var v = list[i];
3111 if ((v is ObservableMap) && _isServiceMap(v)) { 3158 if ((v is ObservableMap) && _isServiceMap(v)) {
3112 list[i] = owner.getFromMap(v); 3159 list[i] = owner.getFromMap(v);
3113 } else if (v is ObservableList) { 3160 } else if (v is ObservableList) {
3114 _upgradeObservableList(v, owner); 3161 _upgradeObservableList(v, owner);
3115 } else if (v is ObservableMap) { 3162 } else if (v is ObservableMap) {
3116 _upgradeObservableMap(v, owner); 3163 _upgradeObservableMap(v, owner);
3117 } 3164 }
3118 } 3165 }
3119 } 3166 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698