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

Side by Side Diff: runtime/bin/vmservice/client/lib/src/observatory_elements/heap_profile.dart

Issue 173013004: Add accumulator to allocation profiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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 library heap_profile_element; 5 library heap_profile_element;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:html'; 8 import 'dart:html';
9 import 'package:logging/logging.dart'; 9 import 'package:logging/logging.dart';
10 import 'package:polymer/polymer.dart'; 10 import 'package:polymer/polymer.dart';
11 import 'observatory_element.dart'; 11 import 'observatory_element.dart';
12 12
13 /// Displays an Error response. 13 /// Displays an Error response.
14 @CustomTag('heap-profile') 14 @CustomTag('heap-profile')
15 class HeapProfileElement extends ObservatoryElement { 15 class HeapProfileElement extends ObservatoryElement {
16 // Indexes into VM provided map. 16 // Indexes into VM provided map.
17 static const ALLOCATED_BEFORE_GC = 0; 17 static const ALLOCATED_BEFORE_GC = 0;
18 static const ALLOCATED_BEFORE_GC_SIZE = 1; 18 static const ALLOCATED_BEFORE_GC_SIZE = 1;
19 static const LIVE_AFTER_GC = 2; 19 static const LIVE_AFTER_GC = 2;
20 static const LIVE_AFTER_GC_SIZE = 3; 20 static const LIVE_AFTER_GC_SIZE = 3;
21 static const ALLOCATED_SINCE_GC = 4; 21 static const ALLOCATED_SINCE_GC = 4;
22 static const ALLOCATED_SINCE_GC_SIZE = 5; 22 static const ALLOCATED_SINCE_GC_SIZE = 5;
23 static const ACCUMULATED = 6;
24 static const ACCUMULATED_SIZE = 7;
23 25
24 var _newPieDataTable; 26 var _newPieDataTable;
25 var _newPieChart; 27 var _newPieChart;
26 28
27 var _oldPieDataTable; 29 var _oldPieDataTable;
28 var _oldPieChart; 30 var _oldPieChart;
29 31
32 var _simpleDataTable;
33 var _simpleChart;
turnidge 2014/02/27 18:29:13 Is there a better name than simpleDataTable? Tha
Cutch 2014/02/27 21:50:33 I've renamed it to "combined", which is a better n
34
30 var _tableDataTable; 35 var _tableDataTable;
31 var _tableChart; 36 var _tableChart;
32 37
33 @published Map profile; 38 @published Map profile;
34 39
35 HeapProfileElement.created() : super.created() { 40 HeapProfileElement.created() : super.created() {
36 _tableDataTable = new DataTable(); 41 _tableDataTable = new DataTable();
37 _tableDataTable.addColumn('string', 'Class'); 42 _tableDataTable.addColumn('string', 'Class');
38 _tableDataTable.addColumn('number', 'Current (new)'); 43 _tableDataTable.addColumn('number', 'Current (new)');
39 _tableDataTable.addColumn('number', 'Allocated Since GC (new)'); 44 _tableDataTable.addColumn('number', 'Allocated Since GC (new)');
40 _tableDataTable.addColumn('number', 'Total before GC (new)'); 45 _tableDataTable.addColumn('number', 'Total before GC (new)');
41 _tableDataTable.addColumn('number', 'Survivors (new)'); 46 _tableDataTable.addColumn('number', 'Survivors (new)');
42 _tableDataTable.addColumn('number', 'Current (old)'); 47 _tableDataTable.addColumn('number', 'Current (old)');
43 _tableDataTable.addColumn('number', 'Allocated Since GC (old)'); 48 _tableDataTable.addColumn('number', 'Allocated Since GC (old)');
44 _tableDataTable.addColumn('number', 'Total before GC (old)'); 49 _tableDataTable.addColumn('number', 'Total before GC (old)');
45 _tableDataTable.addColumn('number', 'Survivors (old)'); 50 _tableDataTable.addColumn('number', 'Survivors (old)');
46 _newPieDataTable = new DataTable(); 51 _newPieDataTable = new DataTable();
47 _newPieDataTable.addColumn('string', 'Type'); 52 _newPieDataTable.addColumn('string', 'Type');
48 _newPieDataTable.addColumn('number', 'Size'); 53 _newPieDataTable.addColumn('number', 'Size');
49 _oldPieDataTable = new DataTable(); 54 _oldPieDataTable = new DataTable();
50 _oldPieDataTable.addColumn('string', 'Type'); 55 _oldPieDataTable.addColumn('string', 'Type');
51 _oldPieDataTable.addColumn('number', 'Size'); 56 _oldPieDataTable.addColumn('number', 'Size');
57 _simpleDataTable = new DataTable();
58 _simpleDataTable.addColumn('string', 'Class');
59 _simpleDataTable.addColumn('number', 'Accumulator');
60 _simpleDataTable.addColumn('number', 'Accumulator Instances');
61 _simpleDataTable.addColumn('number', 'Current');
62 _simpleDataTable.addColumn('number', 'Allocated Since GC');
63 _simpleDataTable.addColumn('number', 'Total before GC');
64 _simpleDataTable.addColumn('number', 'Survivors after GC');
52 } 65 }
53 66
54 void enteredView() { 67 void enteredView() {
55 super.enteredView(); 68 super.enteredView();
56 _tableChart = new Chart('Table', 69 _tableChart = new Chart('Table',
57 shadowRoot.querySelector('#table')); 70 shadowRoot.querySelector('#table'));
58 _tableChart.options['allowHtml'] = true; 71 _tableChart.options['allowHtml'] = true;
59 _tableChart.options['sortColumn'] = 1; 72 _tableChart.options['sortColumn'] = 1;
60 _tableChart.options['sortAscending'] = false; 73 _tableChart.options['sortAscending'] = false;
61 _newPieChart = new Chart('PieChart', 74 _newPieChart = new Chart('PieChart',
62 shadowRoot.querySelector('#newPieChart')); 75 shadowRoot.querySelector('#newPieChart'));
63 _newPieChart.options['title'] = 'New Space'; 76 _newPieChart.options['title'] = 'New Space';
64 _oldPieChart = new Chart('PieChart', 77 _oldPieChart = new Chart('PieChart',
65 shadowRoot.querySelector('#oldPieChart')); 78 shadowRoot.querySelector('#oldPieChart'));
66 _oldPieChart.options['title'] = 'Old Space'; 79 _oldPieChart.options['title'] = 'Old Space';
80 _simpleChart = new Chart('Table',
81 shadowRoot.querySelector('#simpleTable'));
82 _simpleChart.options['allowHtml'] = true;
83 _simpleChart.options['sortColumn'] = 1;
84 _simpleChart.options['sortAscending'] = false;
67 _draw(); 85 _draw();
68 } 86 }
69 87
70 bool _first = true; 88 bool _first = true;
71 89
72 void _updateChartData() { 90 void _updateChartData() {
73 if ((profile == null) || (profile['members'] is! List) || 91 if ((profile == null) || (profile['members'] is! List) ||
74 (profile['members'].length == 0)) { 92 (profile['members'].length == 0)) {
75 return; 93 return;
76 } 94 }
77 assert(_tableDataTable != null); 95 assert(_tableDataTable != null);
96 assert(_simpleDataTable != null);
78 _tableDataTable.clearRows(); 97 _tableDataTable.clearRows();
98 _simpleDataTable.clearRows();
79 for (Map cls in profile['members']) { 99 for (Map cls in profile['members']) {
100 if (_shouldSkip(cls)) {
101 continue;
102 }
103 var vm_name = cls['class']['name'];
80 var url = 104 var url =
81 app.locationManager.currentIsolateRelativeLink(cls['class']['id']); 105 app.locationManager.currentIsolateRelativeLink(cls['class']['id']);
82 _tableDataTable.addRow( 106 _tableDataTable.addRow(
83 ['<a href="$url">${_columnValue(cls, 0)}</a>', 107 ['<a title="$vm_name" href="$url">${_columnValue(cls, 0)}</a>',
84 _columnValue(cls, 1), 108 _columnValue(cls, 1),
85 _columnValue(cls, 2), 109 _columnValue(cls, 2),
86 _columnValue(cls, 3), 110 _columnValue(cls, 3),
87 _columnValue(cls, 4), 111 _columnValue(cls, 4),
88 _columnValue(cls, 5), 112 _columnValue(cls, 5),
89 _columnValue(cls, 6), 113 _columnValue(cls, 6),
90 _columnValue(cls, 7), 114 _columnValue(cls, 7),
91 _columnValue(cls, 8)]); 115 _columnValue(cls, 8)]);
116 _simpleDataTable.addRow(
117 ['<a title="$vm_name" href="$url">${_simpleColumnValue(cls, 0)}</a>',
118 _simpleColumnValue(cls, 1),
119 _simpleColumnValue(cls, 2),
120 _simpleColumnValue(cls, 3),
121 _simpleColumnValue(cls, 4),
122 _simpleColumnValue(cls, 5),
123 _simpleColumnValue(cls, 6)]);
92 } 124 }
93 _newPieDataTable.clearRows(); 125 _newPieDataTable.clearRows();
94 var heap = profile['heaps']['new']; 126 var heap = profile['heaps']['new'];
95 _newPieDataTable.addRow(['Used', heap['used']]); 127 _newPieDataTable.addRow(['Used', heap['used']]);
96 _newPieDataTable.addRow(['Free', heap['capacity'] - heap['used']]); 128 _newPieDataTable.addRow(['Free', heap['capacity'] - heap['used']]);
97 _oldPieDataTable.clearRows(); 129 _oldPieDataTable.clearRows();
98 heap = profile['heaps']['old']; 130 heap = profile['heaps']['old'];
99 _oldPieDataTable.addRow(['Used', heap['used']]); 131 _oldPieDataTable.addRow(['Used', heap['used']]);
100 _oldPieDataTable.addRow(['Free', heap['capacity'] - heap['used']]); 132 _oldPieDataTable.addRow(['Free', heap['capacity'] - heap['used']]);
101 _draw(); 133 _draw();
102 } 134 }
103 135
104 void _draw() { 136 void _draw() {
105 if (_tableChart == null) { 137 if ((_tableChart == null) || (_simpleChart == null)) {
106 return; 138 return;
107 } 139 }
140 _simpleChart.refreshOptionsSortInfo();
141 _simpleChart.draw(_simpleDataTable);
142 _tableChart.refreshOptionsSortInfo();
108 _tableChart.draw(_tableDataTable); 143 _tableChart.draw(_tableDataTable);
109 _newPieChart.draw(_newPieDataTable); 144 _newPieChart.draw(_newPieDataTable);
110 _oldPieChart.draw(_oldPieDataTable); 145 _oldPieChart.draw(_oldPieDataTable);
111 } 146 }
112 147
148 bool _shouldSkip(Map v) {
turnidge 2014/02/27 18:29:13 This function is a bit cryptic. Should skip what?
Cutch 2014/02/27 21:50:33 Cleaned up. renamed to _classHasNoAllocations.
149 var n = v['new'];
150 var o = v['old'];
151 for (var i in n) {
152 if (i != 0) {
153 return false;
154 }
155 }
156 for (var i in o) {
157 if (i != 0) {
158 return false;
159 }
160 }
161 return true;
162 }
163
113 dynamic _columnValue(Map v, int index) { 164 dynamic _columnValue(Map v, int index) {
114 assert(index >= 0); 165 assert(index >= 0);
115 assert(index < 9); 166 assert(index < 9);
116 switch (index) { 167 switch (index) {
117 case 0: 168 case 0:
118 return v['class']['user_name']; 169 return v['class']['user_name'];
119 case 1: 170 case 1:
120 return v['new'][LIVE_AFTER_GC_SIZE] + v['new'][ALLOCATED_SINCE_GC_SIZE]; 171 return v['new'][LIVE_AFTER_GC_SIZE] + v['new'][ALLOCATED_SINCE_GC_SIZE];
121 case 2: 172 case 2:
122 return v['new'][ALLOCATED_SINCE_GC_SIZE]; 173 return v['new'][ALLOCATED_SINCE_GC_SIZE];
123 case 3: 174 case 3:
124 return v['new'][ALLOCATED_BEFORE_GC_SIZE]; 175 return v['new'][ALLOCATED_BEFORE_GC_SIZE];
125 case 4: 176 case 4:
126 return v['new'][LIVE_AFTER_GC_SIZE]; 177 return v['new'][LIVE_AFTER_GC_SIZE];
127 case 5: 178 case 5:
128 return v['old'][LIVE_AFTER_GC_SIZE] + v['old'][ALLOCATED_SINCE_GC_SIZE]; 179 return v['old'][LIVE_AFTER_GC_SIZE] + v['old'][ALLOCATED_SINCE_GC_SIZE];
129 case 6: 180 case 6:
130 return v['old'][ALLOCATED_SINCE_GC_SIZE]; 181 return v['old'][ALLOCATED_SINCE_GC_SIZE];
131 case 7: 182 case 7:
132 return v['old'][ALLOCATED_BEFORE_GC_SIZE]; 183 return v['old'][ALLOCATED_BEFORE_GC_SIZE];
133 case 8: 184 case 8:
134 return v['old'][LIVE_AFTER_GC_SIZE]; 185 return v['old'][LIVE_AFTER_GC_SIZE];
135 } 186 }
187 throw new FallThroughError();
188 }
189
190 dynamic _simpleColumnValue(Map v, int index) {
191 assert(index >= 0);
192 assert(index < 7);
193 switch (index) {
194 case 0:
195 return v['class']['user_name'];
196 case 1:
197 return v['new'][ACCUMULATED_SIZE] +
198 v['old'][ACCUMULATED_SIZE];
199 case 2:
200 return v['new'][ACCUMULATED] +
201 v['old'][ACCUMULATED];
202 case 3:
203 return v['new'][LIVE_AFTER_GC_SIZE] +
204 v['new'][ALLOCATED_SINCE_GC_SIZE] +
205 v['old'][LIVE_AFTER_GC_SIZE] +
206 v['old'][ALLOCATED_SINCE_GC_SIZE];
207 case 4:
208 return v['new'][ALLOCATED_SINCE_GC_SIZE] +
209 v['old'][ALLOCATED_SINCE_GC_SIZE];
210 case 5:
211 return v['new'][ALLOCATED_BEFORE_GC_SIZE] +
212 v['old'][ALLOCATED_BEFORE_GC_SIZE];
213 case 6:
214 return v['new'][LIVE_AFTER_GC_SIZE] + v['old'][LIVE_AFTER_GC_SIZE];
215 }
216 throw new FallThroughError();
136 } 217 }
137 218
138 void refreshData(Event e, var detail, Node target) { 219 void refreshData(Event e, var detail, Node target) {
139 var isolateId = app.locationManager.currentIsolateId(); 220 var isolateId = app.locationManager.currentIsolateId();
140 var isolate = app.isolateManager.getIsolate(isolateId); 221 var isolate = app.isolateManager.getIsolate(isolateId);
141 if (isolate == null) { 222 if (isolate == null) {
142 Logger.root.info('No isolate found.'); 223 Logger.root.info('No isolate found.');
143 return; 224 return;
144 } 225 }
145 var request = '/$isolateId/allocationprofile'; 226 var request = '/$isolateId/allocationprofile';
146 app.requestManager.requestMap(request).then((Map response) { 227 app.requestManager.requestMap(request).then((Map response) {
147 assert(response['type'] == 'AllocationProfile'); 228 assert(response['type'] == 'AllocationProfile');
148 profile = response; 229 profile = response;
149 }).catchError((e, st) { 230 }).catchError((e, st) {
150 Logger.root.info('$e $st'); 231 Logger.root.info('$e $st');
151 }); 232 });
152 } 233 }
153 234
235 void resetAccumulator(Event e, var detail, Node target) {
236 var isolateId = app.locationManager.currentIsolateId();
237 var isolate = app.isolateManager.getIsolate(isolateId);
238 if (isolate == null) {
239 Logger.root.info('No isolate found.');
240 return;
241 }
242 var request = '/$isolateId/allocationprofile/reset';
243 app.requestManager.requestMap(request).then((Map response) {
244 assert(response['type'] == 'AllocationProfile');
245 profile = response;
246 }).catchError((e, st) {
247 Logger.root.info('$e $st');
248 });
249 }
250
154 void profileChanged(oldValue) { 251 void profileChanged(oldValue) {
155 _updateChartData(); 252 _updateChartData();
156 notifyPropertyChange(#formattedAverage, [], formattedAverage); 253 notifyPropertyChange(#formattedAverage, [], formattedAverage);
157 notifyPropertyChange(#formattedTotalCollectionTime, [], 254 notifyPropertyChange(#formattedTotalCollectionTime, [],
158 formattedTotalCollectionTime); 255 formattedTotalCollectionTime);
159 notifyPropertyChange(#formattedCollections, [], formattedCollections); 256 notifyPropertyChange(#formattedCollections, [], formattedCollections);
160 } 257 }
161 258
162 @observable String formattedAverage(bool newSpace) { 259 @observable String formattedAverage(bool newSpace) {
163 if (profile == null) { 260 if (profile == null) {
(...skipping 16 matching lines...) Expand all
180 277
181 @observable String formattedTotalCollectionTime(bool newSpace) { 278 @observable String formattedTotalCollectionTime(bool newSpace) {
182 if (profile == null) { 279 if (profile == null) {
183 return ''; 280 return '';
184 } 281 }
185 String space = newSpace ? 'new' : 'old'; 282 String space = newSpace ? 'new' : 'old';
186 Map heap = profile['heaps'][space]; 283 Map heap = profile['heaps'][space];
187 return '${ObservatoryApplication.timeUnits(heap['time'])} secs'; 284 return '${ObservatoryApplication.timeUnits(heap['time'])} secs';
188 } 285 }
189 } 286 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698