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

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

Powered by Google App Engine
This is Rietveld 408576698