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

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 809 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 totalCollectionTimeInSeconds = heapMap['time']; 820 totalCollectionTimeInSeconds = heapMap['time'];
821 averageCollectionPeriodInMillis = heapMap['avgCollectionPeriodMillis']; 821 averageCollectionPeriodInMillis = heapMap['avgCollectionPeriodMillis'];
822 } 822 }
823 } 823 }
824 824
825 class HeapSnapshot { 825 class HeapSnapshot {
826 final ObjectGraph graph; 826 final ObjectGraph graph;
827 final DateTime timeStamp; 827 final DateTime timeStamp;
828 final Isolate isolate; 828 final Isolate isolate;
829 829
830 HeapSnapshot(this.isolate, ByteData data) : 830 HeapSnapshot(this.isolate, chunks, nodeCount) :
831 graph = new ObjectGraph(new ReadStream(data)), 831 graph = new ObjectGraph(chunks, nodeCount),
832 timeStamp = new DateTime.now() { 832 timeStamp = new DateTime.now();
833 }
834 833
835 List<Future<ServiceObject>> getMostRetained({int classId, int limit}) { 834 List<Future<ServiceObject>> getMostRetained({int classId, int limit}) {
836 var result = []; 835 var result = [];
837 for (var v in graph.getMostRetained(classId: classId, limit: limit)) { 836 for (var v in graph.getMostRetained(classId: classId, limit: limit)) {
838 var address = v.addressForWordSize(isolate.vm.architectureBits ~/ 8); 837 var address = v.addressForWordSize(isolate.vm.architectureBits ~/ 8);
839 result.add(isolate.getObjectByAddress(address.toRadixString(16)).then((obj ) { 838 result.add(isolate.getObjectByAddress(address.toRadixString(16)).then((obj ) {
840 obj.retainedSize = v.retainedSize; 839 obj.retainedSize = v.retainedSize;
841 return new Future(() => obj); 840 return new Future(() => obj);
842 })); 841 }));
843 } 842 }
844 return result; 843 return result;
845 } 844 }
846
847
848 } 845 }
849 846
850 /// State for a running isolate. 847 /// State for a running isolate.
851 class Isolate extends ServiceObjectOwner with Coverage { 848 class Isolate extends ServiceObjectOwner with Coverage {
852 @reflectable VM get vm => owner; 849 @reflectable VM get vm => owner;
853 @reflectable Isolate get isolate => this; 850 @reflectable Isolate get isolate => this;
854 @observable int number; 851 @observable int number;
855 @observable DateTime startTime; 852 @observable DateTime startTime;
856 @observable Duration get upTime => 853 @observable Duration get upTime =>
857 (new DateTime.now().difference(startTime)); 854 (new DateTime.now().difference(startTime));
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
898 } 895 }
899 896
900 /// Fetches and builds the class hierarchy for this isolate. Returns the 897 /// Fetches and builds the class hierarchy for this isolate. Returns the
901 /// Object class object. 898 /// Object class object.
902 Future<Class> getClassHierarchy() { 899 Future<Class> getClassHierarchy() {
903 return invokeRpc('getClassList', {}) 900 return invokeRpc('getClassList', {})
904 .then(_loadClasses) 901 .then(_loadClasses)
905 .then(_buildClassHierarchy); 902 .then(_buildClassHierarchy);
906 } 903 }
907 904
905 Future<List<Class>> getClassRefs() async {
906 ServiceMap classList = await invokeRpc('getClassList', {});
907 assert(classList.type == 'ClassList');
908 var classRefs = [];
909 for (var cls in classList['classes']) {
910 // Skip over non-class classes.
911 if (cls is Class) {
912 _classesByCid[cls.vmCid] = cls;
913 classRefs.add(cls);
914 }
915 }
916 return classRefs;
917 }
918
908 /// Given the class list, loads each class. 919 /// Given the class list, loads each class.
909 Future<List<Class>> _loadClasses(ServiceMap classList) { 920 Future<List<Class>> _loadClasses(ServiceMap classList) {
910 assert(classList.type == 'ClassList'); 921 assert(classList.type == 'ClassList');
911 var futureClasses = []; 922 var futureClasses = [];
912 for (var cls in classList['classes']) { 923 for (var cls in classList['classes']) {
913 // Skip over non-class classes. 924 // Skip over non-class classes.
914 if (cls is Class) { 925 if (cls is Class) {
926 _classesByCid[cls.vmCid] = cls;
915 futureClasses.add(cls.load()); 927 futureClasses.add(cls.load());
916 } 928 }
917 } 929 }
918 return Future.wait(futureClasses); 930 return Future.wait(futureClasses);
919 } 931 }
920 932
921 /// Builds the class hierarchy and returns the Object class. 933 /// Builds the class hierarchy and returns the Object class.
922 Future<Class> _buildClassHierarchy(List<Class> classes) { 934 Future<Class> _buildClassHierarchy(List<Class> classes) {
923 rootClasses.clear(); 935 rootClasses.clear();
924 objectClass = null; 936 objectClass = null;
925 for (var cls in classes) { 937 for (var cls in classes) {
926 if (cls.superclass == null) { 938 if (cls.superclass == null) {
927 rootClasses.add(cls); 939 rootClasses.add(cls);
928 } 940 }
929 if ((cls.vmName == 'Object') && (cls.isPatch == false)) { 941 if ((cls.vmName == 'Object') && (cls.isPatch == false)) {
930 objectClass = cls; 942 objectClass = cls;
931 } 943 }
932 } 944 }
933 assert(objectClass != null); 945 assert(objectClass != null);
934 return new Future.value(objectClass); 946 return new Future.value(objectClass);
935 } 947 }
936 948
949 Class getClassByCid(int cid) => _classesByCid[cid];
950
937 ServiceObject getFromMap(ObservableMap map) { 951 ServiceObject getFromMap(ObservableMap map) {
938 if (map == null) { 952 if (map == null) {
939 return null; 953 return null;
940 } 954 }
941 var mapType = _stripRef(map['type']); 955 var mapType = _stripRef(map['type']);
942 if (mapType == 'Isolate') { 956 if (mapType == 'Isolate') {
943 // There are sometimes isolate refs in ServiceEvents. 957 // There are sometimes isolate refs in ServiceEvents.
944 return vm.getFromMap(map); 958 return vm.getFromMap(map);
945 } 959 }
946 String mapId = map['id']; 960 String mapId = map['id'];
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
979 }; 993 };
980 return isolate.invokeRpc('getObject', params); 994 return isolate.invokeRpc('getObject', params);
981 } 995 }
982 996
983 Future<ObservableMap> _fetchDirect() { 997 Future<ObservableMap> _fetchDirect() {
984 return invokeRpcNoUpgrade('getIsolate', {}); 998 return invokeRpcNoUpgrade('getIsolate', {});
985 } 999 }
986 1000
987 @observable Class objectClass; 1001 @observable Class objectClass;
988 @observable final rootClasses = new ObservableList<Class>(); 1002 @observable final rootClasses = new ObservableList<Class>();
1003 Map<int, Class> _classesByCid = new Map<int, Class>();
989 1004
990 @observable Library rootLibrary; 1005 @observable Library rootLibrary;
991 @observable ObservableList<Library> libraries = 1006 @observable ObservableList<Library> libraries =
992 new ObservableList<Library>(); 1007 new ObservableList<Library>();
993 @observable ObservableMap topFrame; 1008 @observable ObservableMap topFrame;
994 1009
995 @observable String name; 1010 @observable String name;
996 @observable String vmName; 1011 @observable String vmName;
997 @observable ServiceFunction entry; 1012 @observable ServiceFunction entry;
998 1013
999 @observable final Map<String, double> timers = 1014 @observable final Map<String, double> timers =
1000 toObservable(new Map<String, double>()); 1015 toObservable(new Map<String, double>());
1001 1016
1002 final HeapSpace newSpace = new HeapSpace(); 1017 final HeapSpace newSpace = new HeapSpace();
1003 final HeapSpace oldSpace = new HeapSpace(); 1018 final HeapSpace oldSpace = new HeapSpace();
1004 1019
1005 @observable String fileAndLine; 1020 @observable String fileAndLine;
1006 1021
1007 @observable DartError error; 1022 @observable DartError error;
1008 @observable HeapSnapshot latestSnapshot; 1023 @observable HeapSnapshot latestSnapshot;
1009 Completer<HeapSnapshot> _snapshotFetch; 1024 StreamController _snapshotFetch;
1025
1026 List<ByteData> _chunksInProgress;
1010 1027
1011 void _loadHeapSnapshot(ServiceEvent event) { 1028 void _loadHeapSnapshot(ServiceEvent event) {
1012 latestSnapshot = new HeapSnapshot(this, event.data); 1029 if (_snapshotFetch == null || _snapshotFetch.isClosed) {
1030 // No outstanding snapshot request. Presumably another client asked for a
1031 // snapshot.
1032 Logger.root.info("Dropping unsolicited heap snapshot chunk");
1033 return;
1034 }
1035
1036 // Occasionally these actually arrive out of order.
1037 var chunkIndex = event.chunkIndex;
1038 var chunkCount = event.chunkCount;
1039 if (_chunksInProgress == null) {
1040 _chunksInProgress = new List(chunkCount);
1041 }
1042 _chunksInProgress[chunkIndex] = event.data;
1043 _snapshotFetch.add("Receiving snapshot chunk ${chunkIndex + 1}"
1044 " of $chunkCount...");
1045
1046 for (var i = 0; i < chunkCount; i++) {
1047 if (_chunksInProgress[i] == null) return;
1048 }
1049
1050 var loadedChunks = _chunksInProgress;
1051 _chunksInProgress = null;
1052
1053 latestSnapshot = new HeapSnapshot(this, loadedChunks, event.nodeCount);
1013 if (_snapshotFetch != null) { 1054 if (_snapshotFetch != null) {
1014 _snapshotFetch.complete(latestSnapshot); 1055 latestSnapshot.graph.process(_snapshotFetch).then((graph) {
1056 _snapshotFetch.add(latestSnapshot);
1057 _snapshotFetch.close();
1058 });
1015 } 1059 }
1016 } 1060 }
1017 1061
1018 Future<HeapSnapshot> fetchHeapSnapshot() { 1062 Stream fetchHeapSnapshot() {
1019 if (_snapshotFetch == null || _snapshotFetch.isCompleted) { 1063 if (_snapshotFetch == null || _snapshotFetch.isClosed) {
1020 _snapshotFetch = new Completer<HeapSnapshot>(); 1064 _snapshotFetch = new StreamController();
1065 isolate.vm.streamListen('_Graph');
1021 isolate.invokeRpcNoUpgrade('requestHeapSnapshot', {}); 1066 isolate.invokeRpcNoUpgrade('requestHeapSnapshot', {});
1022 } 1067 }
1023 return _snapshotFetch.future; 1068 return _snapshotFetch.stream;
1024 } 1069 }
1025 1070
1026 void updateHeapsFromMap(ObservableMap map) { 1071 void updateHeapsFromMap(ObservableMap map) {
1027 newSpace.update(map['new']); 1072 newSpace.update(map['new']);
1028 oldSpace.update(map['old']); 1073 oldSpace.update(map['old']);
1029 } 1074 }
1030 1075
1031 void _update(ObservableMap map, bool mapIsRef) { 1076 void _update(ObservableMap map, bool mapIsRef) {
1032 name = map['name']; 1077 name = map['name'];
1033 vmName = map['name']; 1078 vmName = map['name'];
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
1451 } 1496 }
1452 1497
1453 @observable String eventType; 1498 @observable String eventType;
1454 @observable Breakpoint breakpoint; 1499 @observable Breakpoint breakpoint;
1455 @observable ServiceMap topFrame; 1500 @observable ServiceMap topFrame;
1456 @observable ServiceMap exception; 1501 @observable ServiceMap exception;
1457 @observable ServiceObject inspectee; 1502 @observable ServiceObject inspectee;
1458 @observable ByteData data; 1503 @observable ByteData data;
1459 @observable int count; 1504 @observable int count;
1460 @observable String reason; 1505 @observable String reason;
1506 int chunkIndex, chunkCount, nodeCount;
1461 1507
1462 @observable bool get isPauseEvent { 1508 @observable bool get isPauseEvent {
1463 return (eventType == kPauseStart || 1509 return (eventType == kPauseStart ||
1464 eventType == kPauseExit || 1510 eventType == kPauseExit ||
1465 eventType == kPauseBreakpoint || 1511 eventType == kPauseBreakpoint ||
1466 eventType == kPauseInterrupted || 1512 eventType == kPauseInterrupted ||
1467 eventType == kPauseException); 1513 eventType == kPauseException);
1468 } 1514 }
1469 1515
1470 void _update(ObservableMap map, bool mapIsRef) { 1516 void _update(ObservableMap map, bool mapIsRef) {
(...skipping 12 matching lines...) Expand all
1483 } 1529 }
1484 if (map['exception'] != null) { 1530 if (map['exception'] != null) {
1485 exception = map['exception']; 1531 exception = map['exception'];
1486 } 1532 }
1487 if (map['inspectee'] != null) { 1533 if (map['inspectee'] != null) {
1488 inspectee = map['inspectee']; 1534 inspectee = map['inspectee'];
1489 } 1535 }
1490 if (map['_data'] != null) { 1536 if (map['_data'] != null) {
1491 data = map['_data']; 1537 data = map['_data'];
1492 } 1538 }
1539 if (map['chunkIndex'] != null) {
1540 chunkIndex = map['chunkIndex'];
1541 }
1542 if (map['chunkCount'] != null) {
1543 chunkCount = map['chunkCount'];
1544 }
1545 if (map['nodeCount'] != null) {
1546 nodeCount = map['nodeCount'];
1547 }
1493 if (map['count'] != null) { 1548 if (map['count'] != null) {
1494 count = map['count']; 1549 count = map['count'];
1495 } 1550 }
1496 } 1551 }
1497 1552
1498 String toString() { 1553 String toString() {
1499 if (data == null) { 1554 if (data == null) {
1500 return "ServiceEvent(owner='${owner.id}', type='${eventType}')"; 1555 return "ServiceEvent(owner='${owner.id}', type='${eventType}')";
1501 } else { 1556 } else {
1502 return "ServiceEvent(owner='${owner.id}', type='${eventType}', " 1557 return "ServiceEvent(owner='${owner.id}', type='${eventType}', "
(...skipping 1641 matching lines...) Expand 10 before | Expand all | Expand 10 after
3144 var v = list[i]; 3199 var v = list[i];
3145 if ((v is ObservableMap) && _isServiceMap(v)) { 3200 if ((v is ObservableMap) && _isServiceMap(v)) {
3146 list[i] = owner.getFromMap(v); 3201 list[i] = owner.getFromMap(v);
3147 } else if (v is ObservableList) { 3202 } else if (v is ObservableList) {
3148 _upgradeObservableList(v, owner); 3203 _upgradeObservableList(v, owner);
3149 } else if (v is ObservableMap) { 3204 } else if (v is ObservableMap) {
3150 _upgradeObservableMap(v, owner); 3205 _upgradeObservableMap(v, owner);
3151 } 3206 }
3152 } 3207 }
3153 } 3208 }
OLDNEW
« no previous file with comments | « runtime/observatory/lib/src/elements/service_view.html ('k') | runtime/observatory/observatory_sources.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698