OLD | NEW |
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 import 'dart:async'; | 5 import 'dart:async'; |
6 import 'dart:html'; | 6 import 'dart:html'; |
7 import 'package:charted/charted.dart'; | 7 import 'package:charted/charted.dart'; |
8 import "package:charted/charts/charts.dart"; | 8 import "package:charted/charts/charts.dart"; |
9 import 'package:observatory/models.dart' as M; | 9 import 'package:observatory/models.dart' as M; |
10 import 'package:observatory/src/elements/class_ref.dart'; | 10 import 'package:observatory/src/elements/class_ref.dart'; |
(...skipping 18 matching lines...) Expand all Loading... |
29 newAccumulatedInstances, | 29 newAccumulatedInstances, |
30 newCurrentSize, | 30 newCurrentSize, |
31 newCurrentInstances, | 31 newCurrentInstances, |
32 oldAccumulatedSize, | 32 oldAccumulatedSize, |
33 oldAccumulatedInstances, | 33 oldAccumulatedInstances, |
34 oldCurrentSize, | 34 oldCurrentSize, |
35 oldCurrentInstances, | 35 oldCurrentInstances, |
36 className, | 36 className, |
37 } | 37 } |
38 | 38 |
39 enum _SortingDirection { | 39 enum _SortingDirection { ascending, descending } |
40 ascending, | |
41 descending | |
42 } | |
43 | 40 |
44 class AllocationProfileElement extends HtmlElement implements Renderable { | 41 class AllocationProfileElement extends HtmlElement implements Renderable { |
45 static const tag = const Tag<AllocationProfileElement>('allocation-profile', | 42 static const tag = const Tag<AllocationProfileElement>('allocation-profile', |
46 dependencies: const [ | 43 dependencies: const [ |
47 ClassRefElement.tag, | 44 ClassRefElement.tag, |
48 NavTopMenuElement.tag, | 45 NavTopMenuElement.tag, |
49 NavVMMenuElement.tag, | 46 NavVMMenuElement.tag, |
50 NavIsolateMenuElement.tag, | 47 NavIsolateMenuElement.tag, |
51 NavRefreshElement.tag, | 48 NavRefreshElement.tag, |
52 NavNotifyElement.tag, | 49 NavNotifyElement.tag, |
53 VirtualCollectionElement.tag | 50 VirtualCollectionElement.tag |
54 ]); | 51 ]); |
55 | 52 |
56 RenderingScheduler<AllocationProfileElement> _r; | 53 RenderingScheduler<AllocationProfileElement> _r; |
57 | 54 |
58 Stream<RenderedEvent<AllocationProfileElement>> get onRendered => | 55 Stream<RenderedEvent<AllocationProfileElement>> get onRendered => |
59 _r.onRendered; | 56 _r.onRendered; |
60 | 57 |
61 M.VM _vm; | 58 M.VM _vm; |
62 M.IsolateRef _isolate; | 59 M.IsolateRef _isolate; |
63 M.EventRepository _events; | 60 M.EventRepository _events; |
64 M.NotificationRepository _notifications; | 61 M.NotificationRepository _notifications; |
65 M.AllocationProfileRepository _repository; | 62 M.AllocationProfileRepository _repository; |
66 M.AllocationProfile _profile; | 63 M.AllocationProfile _profile; |
67 bool _autoRefresh = false; | 64 bool _autoRefresh = false; |
68 bool _isCompacted = false; | 65 bool _isCompacted = false; |
69 StreamSubscription _gcSubscription; | 66 StreamSubscription _gcSubscription; |
70 _SortingField _sortingField = | 67 _SortingField _sortingField = _SortingField.className; |
71 _SortingField.className; | 68 _SortingDirection _sortingDirection = _SortingDirection.ascending; |
72 _SortingDirection _sortingDirection = | |
73 _SortingDirection.ascending; | |
74 | 69 |
75 M.VMRef get vm => _vm; | 70 M.VMRef get vm => _vm; |
76 M.IsolateRef get isolate => _isolate; | 71 M.IsolateRef get isolate => _isolate; |
77 M.NotificationRepository get notifications => _notifications; | 72 M.NotificationRepository get notifications => _notifications; |
78 | 73 |
79 factory AllocationProfileElement(M.VM vm, M.IsolateRef isolate, | 74 factory AllocationProfileElement( |
80 M.EventRepository events, | 75 M.VM vm, |
81 M.NotificationRepository notifications, | 76 M.IsolateRef isolate, |
82 M.AllocationProfileRepository repository, | 77 M.EventRepository events, |
83 {RenderingQueue queue}) { | 78 M.NotificationRepository notifications, |
| 79 M.AllocationProfileRepository repository, |
| 80 {RenderingQueue queue}) { |
84 assert(vm != null); | 81 assert(vm != null); |
85 assert(isolate != null); | 82 assert(isolate != null); |
86 assert(events != null); | 83 assert(events != null); |
87 assert(notifications != null); | 84 assert(notifications != null); |
88 assert(repository != null); | 85 assert(repository != null); |
89 AllocationProfileElement e = document.createElement(tag.name); | 86 AllocationProfileElement e = document.createElement(tag.name); |
90 e._r = new RenderingScheduler(e, queue: queue); | 87 e._r = new RenderingScheduler(e, queue: queue); |
91 e._vm = vm; | 88 e._vm = vm; |
92 e._isolate = isolate; | 89 e._isolate = isolate; |
93 e._events = events; | 90 e._events = events; |
(...skipping 24 matching lines...) Expand all Loading... |
118 _gcSubscription.cancel(); | 115 _gcSubscription.cancel(); |
119 } | 116 } |
120 | 117 |
121 void render() { | 118 void render() { |
122 children = [ | 119 children = [ |
123 navBar([ | 120 navBar([ |
124 new NavTopMenuElement(queue: _r.queue), | 121 new NavTopMenuElement(queue: _r.queue), |
125 new NavVMMenuElement(_vm, _events, queue: _r.queue), | 122 new NavVMMenuElement(_vm, _events, queue: _r.queue), |
126 new NavIsolateMenuElement(_isolate, _events, queue: _r.queue), | 123 new NavIsolateMenuElement(_isolate, _events, queue: _r.queue), |
127 navMenu('allocation profile'), | 124 navMenu('allocation profile'), |
128 new NavRefreshElement(label: 'Download', disabled: _profile == null, | 125 new NavRefreshElement( |
129 queue: _r.queue) | 126 label: 'Download', |
130 ..onRefresh.listen((_) => _downloadCSV()), | 127 disabled: _profile == null, |
| 128 queue: _r.queue)..onRefresh.listen((_) => _downloadCSV()), |
131 new NavRefreshElement(label: 'Reset Accumulator', queue: _r.queue) | 129 new NavRefreshElement(label: 'Reset Accumulator', queue: _r.queue) |
132 ..onRefresh.listen((_) => _refresh(reset: true)), | 130 ..onRefresh.listen((_) => _refresh(reset: true)), |
133 new NavRefreshElement(label: 'GC', queue: _r.queue) | 131 new NavRefreshElement(label: 'GC', queue: _r.queue) |
134 ..onRefresh.listen((_) => _refresh(gc: true)), | 132 ..onRefresh.listen((_) => _refresh(gc: true)), |
135 new NavRefreshElement(queue: _r.queue) | 133 new NavRefreshElement(queue: _r.queue) |
136 ..onRefresh.listen((_) => _refresh()), | 134 ..onRefresh.listen((_) => _refresh()), |
137 new DivElement()..classes = ['nav-option'] | 135 new DivElement() |
| 136 ..classes = ['nav-option'] |
138 ..children = [ | 137 ..children = [ |
139 new CheckboxInputElement() | 138 new CheckboxInputElement() |
140 ..id = 'allocation-profile-auto-refresh' | 139 ..id = 'allocation-profile-auto-refresh' |
141 ..checked = _autoRefresh | 140 ..checked = _autoRefresh |
142 ..onChange.listen((_) => _autoRefresh = !_autoRefresh), | 141 ..onChange.listen((_) => _autoRefresh = !_autoRefresh), |
143 new LabelElement() | 142 new LabelElement() |
144 ..htmlFor = 'allocation-profile-auto-refresh' | 143 ..htmlFor = 'allocation-profile-auto-refresh' |
145 ..text = 'Auto-refresh on GC' | 144 ..text = 'Auto-refresh on GC' |
146 ], | 145 ], |
147 new NavNotifyElement(_notifications, queue: _r.queue) | 146 new NavNotifyElement(_notifications, queue: _r.queue) |
148 ]), | 147 ]), |
149 new DivElement()..classes = ['content-centered-big'] | 148 new DivElement() |
| 149 ..classes = ['content-centered-big'] |
150 ..children = [ | 150 ..children = [ |
151 new HeadingElement.h2()..text = 'Allocation Profile', | 151 new HeadingElement.h2()..text = 'Allocation Profile', |
152 new HRElement() | 152 new HRElement() |
153 ] | 153 ] |
154 ]; | 154 ]; |
155 if (_profile == null) { | 155 if (_profile == null) { |
156 children.addAll([ | 156 children.addAll([ |
157 new DivElement()..classes = ['content-centered-big'] | 157 new DivElement() |
158 ..children = [ | 158 ..classes = ['content-centered-big'] |
159 new HeadingElement.h2()..text = 'Loading...' | 159 ..children = [new HeadingElement.h2()..text = 'Loading...'] |
160 ] | |
161 ]); | 160 ]); |
162 } else { | 161 } else { |
163 final newChartHost = new DivElement()..classes = ['host']; | 162 final newChartHost = new DivElement()..classes = ['host']; |
164 final newChartLegend = new DivElement()..classes = ['legend']; | 163 final newChartLegend = new DivElement()..classes = ['legend']; |
165 final oldChartHost = new DivElement()..classes = ['host']; | 164 final oldChartHost = new DivElement()..classes = ['host']; |
166 final oldChartLegend = new DivElement()..classes = ['legend']; | 165 final oldChartLegend = new DivElement()..classes = ['legend']; |
167 children.addAll([ | 166 children.addAll([ |
168 new DivElement()..classes = ['content-centered-big'] | 167 new DivElement() |
169 ..children = _isCompacted ? [] : [ | 168 ..classes = ['content-centered-big'] |
170 new DivElement()..classes = ['memberList'] | 169 ..children = _isCompacted |
171 ..children = [ | 170 ? [] |
172 new DivElement()..classes = ['memberItem'] | 171 : [ |
173 ..children = [ | 172 new DivElement() |
174 new DivElement()..classes = ['memberName'] | 173 ..classes = ['memberList'] |
175 ..text = 'last forced GC at', | 174 ..children = [ |
176 new DivElement()..classes = ['memberValue'] | 175 new DivElement() |
177 ..text = _profile.lastServiceGC == null ? '---' | 176 ..classes = ['memberItem'] |
178 : '${_profile.lastServiceGC}', | 177 ..children = [ |
179 ], | 178 new DivElement() |
180 new DivElement()..classes = ['memberItem'] | 179 ..classes = ['memberName'] |
181 ..children = [ | 180 ..text = 'last forced GC at', |
182 new DivElement()..classes = ['memberName'] | 181 new DivElement() |
183 ..text = 'last accumulator reset at', | 182 ..classes = ['memberValue'] |
184 new DivElement()..classes = ['memberValue'] | 183 ..text = _profile.lastServiceGC == null |
185 ..text = _profile.lastAccumulatorReset == null ? '---' | 184 ? '---' |
186 : '${_profile.lastAccumulatorReset}', | 185 : '${_profile.lastServiceGC}', |
187 ] | 186 ], |
188 ], | 187 new DivElement() |
189 new HRElement(), | 188 ..classes = ['memberItem'] |
190 ], | 189 ..children = [ |
191 new DivElement()..classes = ['content-centered-big', 'compactable'] | 190 new DivElement() |
| 191 ..classes = ['memberName'] |
| 192 ..text = 'last accumulator reset at', |
| 193 new DivElement() |
| 194 ..classes = ['memberValue'] |
| 195 ..text = _profile.lastAccumulatorReset == null |
| 196 ? '---' |
| 197 : '${_profile.lastAccumulatorReset}', |
| 198 ] |
| 199 ], |
| 200 new HRElement(), |
| 201 ], |
| 202 new DivElement() |
| 203 ..classes = ['content-centered-big', 'compactable'] |
192 ..children = [ | 204 ..children = [ |
193 new DivElement()..classes = ['heap-space', 'left'] | 205 new DivElement() |
| 206 ..classes = ['heap-space', 'left'] |
194 ..children = _isCompacted | 207 ..children = _isCompacted |
195 ? [ | 208 ? [ |
196 new HeadingElement.h2() | 209 new HeadingElement.h2() |
197 ..text = 'New Generation ' | 210 ..text = 'New Generation ' |
198 '(${_usedCaption(_profile.newSpace)})', | 211 '(${_usedCaption(_profile.newSpace)})', |
199 ] | 212 ] |
200 : [ | 213 : [ |
201 new HeadingElement.h2()..text = 'New Generation', | 214 new HeadingElement.h2()..text = 'New Generation', |
202 new BRElement(), | 215 new BRElement(), |
203 new DivElement()..classes = ['memberList'] | 216 new DivElement() |
204 ..children = _createSpaceMembers(_profile.newSpace), | 217 ..classes = ['memberList'] |
205 new BRElement(), | 218 ..children = _createSpaceMembers(_profile.newSpace), |
206 new DivElement()..classes = ['chart'] | 219 new BRElement(), |
207 ..children = [newChartLegend, newChartHost] | 220 new DivElement() |
208 ], | 221 ..classes = ['chart'] |
209 new DivElement()..classes = ['heap-space', 'right'] | 222 ..children = [newChartLegend, newChartHost] |
| 223 ], |
| 224 new DivElement() |
| 225 ..classes = ['heap-space', 'right'] |
210 ..children = _isCompacted | 226 ..children = _isCompacted |
211 ? [ | 227 ? [ |
212 new HeadingElement.h2() | 228 new HeadingElement.h2() |
213 ..text = '(${_usedCaption(_profile.newSpace)}) ' | 229 ..text = '(${_usedCaption(_profile.newSpace)}) ' |
214 'Old Generation', | 230 'Old Generation', |
215 ] | 231 ] |
216 : [ | 232 : [ |
217 new HeadingElement.h2()..text = 'Old Generation', | 233 new HeadingElement.h2()..text = 'Old Generation', |
218 new BRElement(), | 234 new BRElement(), |
219 new DivElement()..classes = ['memberList'] | 235 new DivElement() |
220 ..children = _createSpaceMembers(_profile.oldSpace), | 236 ..classes = ['memberList'] |
221 new BRElement(), | 237 ..children = _createSpaceMembers(_profile.oldSpace), |
222 new DivElement()..classes = ['chart'] | 238 new BRElement(), |
223 ..children = [oldChartLegend, oldChartHost] | 239 new DivElement() |
224 ], | 240 ..classes = ['chart'] |
225 new ButtonElement()..classes = ['compact'] | 241 ..children = [oldChartLegend, oldChartHost] |
| 242 ], |
| 243 new ButtonElement() |
| 244 ..classes = ['compact'] |
226 ..text = _isCompacted ? 'expand â–¼' : 'compact â–²' | 245 ..text = _isCompacted ? 'expand â–¼' : 'compact â–²' |
227 ..onClick.listen((_) { | 246 ..onClick.listen((_) { |
228 _isCompacted = !_isCompacted; | 247 _isCompacted = !_isCompacted; |
229 _r.dirty(); | 248 _r.dirty(); |
230 }), | 249 }), |
231 new HRElement() | 250 new HRElement() |
232 ], | 251 ], |
233 new DivElement() | 252 new DivElement() |
234 ..classes = _isCompacted ? ['collection', 'expanded'] : ['collection'] | 253 ..classes = _isCompacted ? ['collection', 'expanded'] : ['collection'] |
235 ..children = [ | 254 ..children = [ |
236 new VirtualCollectionElement( | 255 new VirtualCollectionElement( |
237 _createCollectionLine, | 256 _createCollectionLine, _updateCollectionLine, |
238 _updateCollectionLine, | 257 createHeader: _createCollectionHeader, |
239 createHeader: _createCollectionHeader, | 258 items: _profile.members.toList()..sort(_createSorter()), |
240 items: _profile.members.toList()..sort(_createSorter()), | 259 queue: _r.queue) |
241 queue: _r.queue) | |
242 ] | 260 ] |
243 ]); | 261 ]); |
244 _renderGraph(newChartHost, newChartLegend, _profile.newSpace); | 262 _renderGraph(newChartHost, newChartLegend, _profile.newSpace); |
245 _renderGraph(oldChartHost, oldChartLegend, _profile.oldSpace); | 263 _renderGraph(oldChartHost, oldChartLegend, _profile.oldSpace); |
246 } | 264 } |
247 } | 265 } |
248 | 266 |
249 _createSorter() { | 267 _createSorter() { |
250 var getter; | 268 var getter; |
251 switch (_sortingField) { | 269 switch (_sortingField) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 break; | 308 break; |
291 } | 309 } |
292 switch (_sortingDirection) { | 310 switch (_sortingDirection) { |
293 case _SortingDirection.ascending: | 311 case _SortingDirection.ascending: |
294 return (a, b) => getter(a).compareTo(getter(b)); | 312 return (a, b) => getter(a).compareTo(getter(b)); |
295 case _SortingDirection.descending: | 313 case _SortingDirection.descending: |
296 return (a, b) => getter(b).compareTo(getter(a)); | 314 return (a, b) => getter(b).compareTo(getter(a)); |
297 } | 315 } |
298 } | 316 } |
299 | 317 |
300 static Element _createCollectionLine() => | 318 static Element _createCollectionLine() => new DivElement() |
301 new DivElement() | 319 ..classes = ['collection-item'] |
302 ..classes = ['collection-item'] | 320 ..children = [ |
303 ..children = [ | 321 new SpanElement() |
304 new SpanElement()..classes = ['bytes'] | 322 ..classes = ['bytes'] |
305 ..text = '0B', | 323 ..text = '0B', |
306 new SpanElement()..classes = ['instances'] | 324 new SpanElement() |
307 ..text = '0', | 325 ..classes = ['instances'] |
308 new SpanElement()..classes = ['bytes'] | 326 ..text = '0', |
309 ..text = '0B', | 327 new SpanElement() |
310 new SpanElement()..classes = ['instances'] | 328 ..classes = ['bytes'] |
311 ..text = '0', | 329 ..text = '0B', |
312 new SpanElement()..classes = ['bytes'] | 330 new SpanElement() |
313 ..text = '0B', | 331 ..classes = ['instances'] |
314 new SpanElement()..classes = ['instances'] | 332 ..text = '0', |
315 ..text = '0', | 333 new SpanElement() |
316 new SpanElement()..classes = ['bytes'] | 334 ..classes = ['bytes'] |
317 ..text = '0B', | 335 ..text = '0B', |
318 new SpanElement()..classes = ['instances'] | 336 new SpanElement() |
319 ..text = '0', | 337 ..classes = ['instances'] |
320 new SpanElement()..classes = ['bytes'] | 338 ..text = '0', |
321 ..text = '0B', | 339 new SpanElement() |
322 new SpanElement()..classes = ['instances'] | 340 ..classes = ['bytes'] |
323 ..text = '0', | 341 ..text = '0B', |
324 new SpanElement()..classes = ['bytes'] | 342 new SpanElement() |
325 ..text = '0B', | 343 ..classes = ['instances'] |
326 new SpanElement()..classes = ['instances'] | 344 ..text = '0', |
327 ..text = '0', | 345 new SpanElement() |
328 new SpanElement()..classes = ['name'] | 346 ..classes = ['bytes'] |
329 ]; | 347 ..text = '0B', |
| 348 new SpanElement() |
| 349 ..classes = ['instances'] |
| 350 ..text = '0', |
| 351 new SpanElement() |
| 352 ..classes = ['bytes'] |
| 353 ..text = '0B', |
| 354 new SpanElement() |
| 355 ..classes = ['instances'] |
| 356 ..text = '0', |
| 357 new SpanElement()..classes = ['name'] |
| 358 ]; |
330 | 359 |
331 Element _createCollectionHeader() => | 360 Element _createCollectionHeader() => new DivElement() |
332 new DivElement() | 361 ..children = [ |
333 ..children = [ | 362 new DivElement() |
334 new DivElement() | 363 ..classes = ['collection-item'] |
335 ..classes = ['collection-item'] | 364 ..children = [ |
336 ..children = [ | 365 new SpanElement() |
337 new SpanElement()..classes = ['group'] | 366 ..classes = ['group'] |
338 ..text = 'Accumulated', | 367 ..text = 'Accumulated', |
339 new SpanElement()..classes = ['group'] | 368 new SpanElement() |
340 ..text = 'Current', | 369 ..classes = ['group'] |
341 new SpanElement()..classes = ['group'] | 370 ..text = 'Current', |
342 ..text = '(NEW) Accumulated', | 371 new SpanElement() |
343 new SpanElement()..classes = ['group'] | 372 ..classes = ['group'] |
344 ..text = '(NEW) Current', | 373 ..text = '(NEW) Accumulated', |
345 new SpanElement()..classes = ['group'] | 374 new SpanElement() |
346 ..text = '(OLD) Accumulated', | 375 ..classes = ['group'] |
347 new SpanElement()..classes = ['group'] | 376 ..text = '(NEW) Current', |
348 ..text = '(OLD) Current', | 377 new SpanElement() |
349 ], | 378 ..classes = ['group'] |
350 new DivElement() | 379 ..text = '(OLD) Accumulated', |
351 ..classes = ['collection-item'] | 380 new SpanElement() |
352 ..children = [ | 381 ..classes = ['group'] |
353 _createHeaderButton(const ['bytes'], 'Size', | 382 ..text = '(OLD) Current', |
354 _SortingField.accumulatedSize, | 383 ], |
355 _SortingDirection.descending), | 384 new DivElement() |
356 _createHeaderButton(const ['instances'], 'Instances', | 385 ..classes = ['collection-item'] |
357 _SortingField.accumulatedInstances, | 386 ..children = [ |
358 _SortingDirection.descending), | 387 _createHeaderButton(const ['bytes'], 'Size', |
359 _createHeaderButton(const ['bytes'], 'Size', | 388 _SortingField.accumulatedSize, _SortingDirection.descending), |
360 _SortingField.currentSize, | 389 _createHeaderButton(const ['instances'], 'Instances', |
361 _SortingDirection.descending), | 390 _SortingField.accumulatedInstances, _SortingDirection.descending), |
362 _createHeaderButton(const ['instances'], 'Instances', | 391 _createHeaderButton(const ['bytes'], 'Size', |
363 _SortingField.currentInstances, | 392 _SortingField.currentSize, _SortingDirection.descending), |
364 _SortingDirection.descending), | 393 _createHeaderButton(const ['instances'], 'Instances', |
365 _createHeaderButton(const ['bytes'], 'Size', | 394 _SortingField.currentInstances, _SortingDirection.descending), |
366 _SortingField.newAccumulatedSize, | 395 _createHeaderButton(const ['bytes'], 'Size', |
367 _SortingDirection.descending), | 396 _SortingField.newAccumulatedSize, _SortingDirection.descending), |
368 _createHeaderButton(const ['instances'], 'Instances', | 397 _createHeaderButton( |
369 _SortingField.newAccumulatedInstances, | 398 const ['instances'], |
370 _SortingDirection.descending), | 399 'Instances', |
371 _createHeaderButton(const ['bytes'], 'Size', | 400 _SortingField.newAccumulatedInstances, |
372 _SortingField.newCurrentSize, | 401 _SortingDirection.descending), |
373 _SortingDirection.descending), | 402 _createHeaderButton(const ['bytes'], 'Size', |
374 _createHeaderButton(const ['instances'], 'Instances', | 403 _SortingField.newCurrentSize, _SortingDirection.descending), |
375 _SortingField.newCurrentInstances, | 404 _createHeaderButton(const ['instances'], 'Instances', |
376 _SortingDirection.descending), | 405 _SortingField.newCurrentInstances, _SortingDirection.descending), |
377 _createHeaderButton(const ['bytes'], 'Size', | 406 _createHeaderButton(const ['bytes'], 'Size', |
378 _SortingField.oldAccumulatedSize, | 407 _SortingField.oldAccumulatedSize, _SortingDirection.descending), |
379 _SortingDirection.descending), | 408 _createHeaderButton( |
380 _createHeaderButton(const ['instances'], 'Instances', | 409 const ['instances'], |
381 _SortingField.oldAccumulatedInstances, | 410 'Instances', |
382 _SortingDirection.descending), | 411 _SortingField.oldAccumulatedInstances, |
383 _createHeaderButton(const ['bytes'], 'Size', | 412 _SortingDirection.descending), |
384 _SortingField.oldCurrentSize, | 413 _createHeaderButton(const ['bytes'], 'Size', |
385 _SortingDirection.descending), | 414 _SortingField.oldCurrentSize, _SortingDirection.descending), |
386 _createHeaderButton(const ['instances'], 'Instances', | 415 _createHeaderButton(const ['instances'], 'Instances', |
387 _SortingField.oldCurrentInstances, | 416 _SortingField.oldCurrentInstances, _SortingDirection.descending), |
388 _SortingDirection.descending), | 417 _createHeaderButton(const ['name'], 'Class', _SortingField.className, |
389 _createHeaderButton(const ['name'], 'Class', | 418 _SortingDirection.ascending) |
390 _SortingField.className, | 419 ], |
391 _SortingDirection.ascending) | 420 ]; |
392 ], | |
393 ]; | |
394 | 421 |
395 ButtonElement _createHeaderButton(List<String> classes, | 422 ButtonElement _createHeaderButton(List<String> classes, String text, |
396 String text, | 423 _SortingField field, _SortingDirection direction) => |
397 _SortingField field, | 424 new ButtonElement() |
398 _SortingDirection direction) => | 425 ..classes = classes |
399 new ButtonElement()..classes = classes | 426 ..text = _sortingField != field |
400 ..text = _sortingField != field ? text : | 427 ? text |
401 _sortingDirection == _SortingDirection.ascending | 428 : _sortingDirection == _SortingDirection.ascending |
402 ? '$textâ–¼' : '$textâ–²' | 429 ? '$textâ–¼' |
403 ..onClick.listen((_) => _setSorting(field, direction)); | 430 : '$textâ–²' |
| 431 ..onClick.listen((_) => _setSorting(field, direction)); |
404 | 432 |
405 | 433 void _setSorting(_SortingField field, _SortingDirection defaultDirection) { |
406 void _setSorting(_SortingField field, | |
407 _SortingDirection defaultDirection) { | |
408 if (_sortingField == field) { | 434 if (_sortingField == field) { |
409 switch (_sortingDirection) { | 435 switch (_sortingDirection) { |
410 case _SortingDirection.descending: | 436 case _SortingDirection.descending: |
411 _sortingDirection = _SortingDirection.ascending; | 437 _sortingDirection = _SortingDirection.ascending; |
412 break; | 438 break; |
413 case _SortingDirection.ascending: | 439 case _SortingDirection.ascending: |
414 _sortingDirection = _SortingDirection.descending; | 440 _sortingDirection = _SortingDirection.descending; |
415 break; | 441 break; |
416 } | 442 } |
417 } else { | 443 } else { |
418 _sortingDirection = defaultDirection; | 444 _sortingDirection = defaultDirection; |
419 _sortingField = field; | 445 _sortingField = field; |
420 } | 446 } |
421 _r.dirty(); | 447 _r.dirty(); |
422 } | 448 } |
423 | 449 |
424 void _updateCollectionLine(Element e, M.ClassHeapStats item, | 450 void _updateCollectionLine(Element e, M.ClassHeapStats item, index) { |
425 index) { | |
426 e.children[0].text = Utils.formatSize(_getAccumulatedSize(item)); | 451 e.children[0].text = Utils.formatSize(_getAccumulatedSize(item)); |
427 e.children[1].text = '${_getAccumulatedInstances(item)}'; | 452 e.children[1].text = '${_getAccumulatedInstances(item)}'; |
428 e.children[2].text = Utils.formatSize(_getCurrentSize(item)); | 453 e.children[2].text = Utils.formatSize(_getCurrentSize(item)); |
429 e.children[3].text = '${_getCurrentInstances(item)}'; | 454 e.children[3].text = '${_getCurrentInstances(item)}'; |
430 e.children[4].text = Utils.formatSize(_getNewAccumulatedSize(item)); | 455 e.children[4].text = Utils.formatSize(_getNewAccumulatedSize(item)); |
431 e.children[5].text = '${_getNewAccumulatedInstances(item)}'; | 456 e.children[5].text = '${_getNewAccumulatedInstances(item)}'; |
432 e.children[6].text = Utils.formatSize(_getNewCurrentSize(item)); | 457 e.children[6].text = Utils.formatSize(_getNewCurrentSize(item)); |
433 e.children[7].text = '${_getNewCurrentInstances(item)}'; | 458 e.children[7].text = '${_getNewCurrentInstances(item)}'; |
434 e.children[8].text = Utils.formatSize(_getOldAccumulatedSize(item)); | 459 e.children[8].text = Utils.formatSize(_getOldAccumulatedSize(item)); |
435 e.children[9].text = '${_getOldAccumulatedInstances(item)}'; | 460 e.children[9].text = '${_getOldAccumulatedInstances(item)}'; |
436 e.children[10].text = Utils.formatSize(_getOldCurrentSize(item)); | 461 e.children[10].text = Utils.formatSize(_getOldCurrentSize(item)); |
437 e.children[11].text = '${_getOldCurrentInstances(item)}'; | 462 e.children[11].text = '${_getOldCurrentInstances(item)}'; |
438 e.children[12] = new ClassRefElement(_isolate, item.clazz, queue: _r.queue) | 463 e.children[12] = new ClassRefElement(_isolate, item.clazz, queue: _r.queue) |
439 ..classes = ['name']; | 464 ..classes = ['name']; |
440 } | 465 } |
441 | 466 |
442 static String _usedCaption(M.HeapSpace space) => | 467 static String _usedCaption(M.HeapSpace space) => |
443 '${Utils.formatSize(space.used)}' | 468 '${Utils.formatSize(space.used)}' |
444 ' of ' | 469 ' of ' |
445 '${Utils.formatSize(space.capacity)}'; | 470 '${Utils.formatSize(space.capacity)}'; |
446 | 471 |
447 static List<Element> _createSpaceMembers(M.HeapSpace space) { | 472 static List<Element> _createSpaceMembers(M.HeapSpace space) { |
448 final used = _usedCaption(space); | 473 final used = _usedCaption(space); |
449 final ext = '${Utils.formatSize(space.external)}'; | 474 final ext = '${Utils.formatSize(space.external)}'; |
450 final collections = '${space.collections}'; | 475 final collections = '${space.collections}'; |
451 final avgCollectionTime = | 476 final avgCollectionTime = |
452 '${Utils.formatDurationInMilliseconds(space.avgCollectionTime)} ms'; | 477 '${Utils.formatDurationInMilliseconds(space.avgCollectionTime)} ms'; |
453 final totalCollectionTime = | 478 final totalCollectionTime = |
454 '${Utils.formatDurationInSeconds(space.totalCollectionTime)} secs'; | 479 '${Utils.formatDurationInSeconds(space.totalCollectionTime)} secs'; |
455 final avgCollectionPeriod = | 480 final avgCollectionPeriod = |
456 '${Utils.formatDurationInMilliseconds(space.avgCollectionPeriod)} ms'; | 481 '${Utils.formatDurationInMilliseconds(space.avgCollectionPeriod)} ms'; |
457 return [ | 482 return [ |
458 new DivElement()..classes = ['memberItem'] | 483 new DivElement() |
| 484 ..classes = ['memberItem'] |
459 ..children = [ | 485 ..children = [ |
460 new DivElement()..classes = ['memberName'] | 486 new DivElement() |
| 487 ..classes = ['memberName'] |
461 ..text = 'used', | 488 ..text = 'used', |
462 new DivElement()..classes = ['memberValue'] | 489 new DivElement() |
| 490 ..classes = ['memberValue'] |
463 ..text = used | 491 ..text = used |
464 ], | 492 ], |
465 new DivElement()..classes = ['memberItem'] | 493 new DivElement() |
| 494 ..classes = ['memberItem'] |
466 ..children = [ | 495 ..children = [ |
467 new DivElement()..classes = ['memberName'] | 496 new DivElement() |
| 497 ..classes = ['memberName'] |
468 ..text = 'external', | 498 ..text = 'external', |
469 new DivElement()..classes = ['memberValue'] | 499 new DivElement() |
| 500 ..classes = ['memberValue'] |
470 ..text = ext | 501 ..text = ext |
471 ], | 502 ], |
472 new DivElement()..classes = ['memberItem'] | 503 new DivElement() |
| 504 ..classes = ['memberItem'] |
473 ..children = [ | 505 ..children = [ |
474 new DivElement()..classes = ['memberName'] | 506 new DivElement() |
475 ..text = 'collections', | 507 ..classes = ['memberName'] |
476 new DivElement()..classes = ['memberValue'] | 508 ..text = 'collections', |
| 509 new DivElement() |
| 510 ..classes = ['memberValue'] |
477 ..text = collections | 511 ..text = collections |
478 ], | 512 ], |
479 new DivElement()..classes = ['memberItem'] | 513 new DivElement() |
| 514 ..classes = ['memberItem'] |
480 ..children = [ | 515 ..children = [ |
481 new DivElement()..classes = ['memberName'] | 516 new DivElement() |
| 517 ..classes = ['memberName'] |
482 ..text = 'average collection time', | 518 ..text = 'average collection time', |
483 new DivElement()..classes = ['memberValue'] | 519 new DivElement() |
| 520 ..classes = ['memberValue'] |
484 ..text = avgCollectionTime | 521 ..text = avgCollectionTime |
485 ], | 522 ], |
486 new DivElement()..classes = ['memberItem'] | 523 new DivElement() |
| 524 ..classes = ['memberItem'] |
487 ..children = [ | 525 ..children = [ |
488 new DivElement()..classes = ['memberName'] | 526 new DivElement() |
| 527 ..classes = ['memberName'] |
489 ..text = 'cumulative collection time', | 528 ..text = 'cumulative collection time', |
490 new DivElement()..classes = ['memberValue'] | 529 new DivElement() |
| 530 ..classes = ['memberValue'] |
491 ..text = totalCollectionTime | 531 ..text = totalCollectionTime |
492 ], | 532 ], |
493 new DivElement()..classes = ['memberItem'] | 533 new DivElement() |
| 534 ..classes = ['memberItem'] |
494 ..children = [ | 535 ..children = [ |
495 new DivElement()..classes = ['memberName'] | 536 new DivElement() |
| 537 ..classes = ['memberName'] |
496 ..text = 'average time between collections', | 538 ..text = 'average time between collections', |
497 new DivElement()..classes = ['memberValue'] | 539 new DivElement() |
| 540 ..classes = ['memberValue'] |
498 ..text = avgCollectionPeriod | 541 ..text = avgCollectionPeriod |
499 ] | 542 ] |
500 ]; | 543 ]; |
501 } | 544 } |
502 | 545 |
503 static final _columns = [ | 546 static final _columns = [ |
504 new ChartColumnSpec(label: 'Type', type: ChartColumnSpec.TYPE_STRING), | 547 new ChartColumnSpec(label: 'Type', type: ChartColumnSpec.TYPE_STRING), |
505 new ChartColumnSpec(label: 'Size', formatter: (v) => v.toString()) | 548 new ChartColumnSpec(label: 'Size', formatter: (v) => v.toString()) |
506 ]; | 549 ]; |
507 | 550 |
508 static void _renderGraph(Element host, Element legend, M.HeapSpace space) { | 551 static void _renderGraph(Element host, Element legend, M.HeapSpace space) { |
509 final series = [new ChartSeries("Work", [1], new PieChartRenderer( | 552 final series = [ |
510 sortDataByValue: false | 553 new ChartSeries("Work", [1], new PieChartRenderer(sortDataByValue: false)) |
511 ))]; | 554 ]; |
512 final rect = host.getBoundingClientRect(); | 555 final rect = host.getBoundingClientRect(); |
513 final minSize = new Rect.size(rect.width, rect.height); | 556 final minSize = new Rect.size(rect.width, rect.height); |
514 final config = new ChartConfig(series, [0]) | 557 final config = new ChartConfig(series, [0]) |
515 ..minimumSize = minSize | 558 ..minimumSize = minSize |
516 ..legend = new ChartLegend(legend, showValues: true); | 559 ..legend = new ChartLegend(legend, showValues: true); |
517 final data = new ChartData(_columns, [ | 560 final data = new ChartData(_columns, [ |
518 ['Used', space.used], | 561 ['Used', space.used], |
519 ['Free', space.capacity - space.used], | 562 ['Free', space.capacity - space.used], |
520 ['External', space.external] | 563 ['External', space.external] |
521 ]); | 564 ]); |
522 | 565 |
523 new LayoutArea(host, data, config, state: new ChartState(), | 566 new LayoutArea(host, data, config, |
524 autoUpdate: true) | 567 state: new ChartState(), autoUpdate: true)..draw(); |
525 ..draw(); | |
526 } | 568 } |
527 | 569 |
528 Future _refresh({bool gc: false, bool reset: false}) async { | 570 Future _refresh({bool gc: false, bool reset: false}) async { |
529 _profile = null; | 571 _profile = null; |
530 _r.dirty(); | 572 _r.dirty(); |
531 _profile = await _repository.get(_isolate, gc: gc, reset: reset); | 573 _profile = await _repository.get(_isolate, gc: gc, reset: reset); |
532 _r.dirty(); | 574 _r.dirty(); |
533 } | 575 } |
534 | 576 |
535 void _downloadCSV() { | 577 void _downloadCSV() { |
536 assert(_profile != null); | 578 assert(_profile != null); |
537 final header = ['"Accumulator Size"', | 579 final header = [ |
538 '"Accumulator Instances"', | 580 '"Accumulator Size"', |
539 '"Current Size"', | 581 '"Accumulator Instances"', |
540 '"Current Instances"', | 582 '"Current Size"', |
541 '"(NEW) Accumulator Size"', | 583 '"Current Instances"', |
542 '"(NEW) Accumulator Instances"', | 584 '"(NEW) Accumulator Size"', |
543 '"(NEW) Current Size"', | 585 '"(NEW) Accumulator Instances"', |
544 '"(NEW) Current Instances"', | 586 '"(NEW) Current Size"', |
545 '"(OLD) Accumulator Size"', | 587 '"(NEW) Current Instances"', |
546 '"(OLD) Accumulator Instances"', | 588 '"(OLD) Accumulator Size"', |
547 '"(OLD) Current Size"', | 589 '"(OLD) Accumulator Instances"', |
548 '"(OLD) Current Instances"', | 590 '"(OLD) Current Size"', |
549 'Class' | 591 '"(OLD) Current Instances"', |
550 ].join(',') + '\n'; | 592 'Class' |
| 593 ].join(',') + |
| 594 '\n'; |
551 AnchorElement tl = document.createElement('a'); | 595 AnchorElement tl = document.createElement('a'); |
552 tl..attributes['href'] = 'data:text/plain;charset=utf-8,' + | 596 tl |
553 Uri.encodeComponent(header + | 597 ..attributes['href'] = 'data:text/plain;charset=utf-8,' + |
554 (_profile.members.toList()..sort(_createSorter())) | 598 Uri.encodeComponent(header + |
555 .map(_csvOut).join('\n')) | 599 (_profile.members.toList()..sort(_createSorter())) |
| 600 .map(_csvOut) |
| 601 .join('\n')) |
556 ..attributes['download'] = 'heap-profile.csv' | 602 ..attributes['download'] = 'heap-profile.csv' |
557 ..click(); | 603 ..click(); |
558 } | 604 } |
559 | 605 |
560 static _csvOut(M.ClassHeapStats s) { | 606 static _csvOut(M.ClassHeapStats s) { |
561 return [ | 607 return [ |
562 _getAccumulatedSize(s), | 608 _getAccumulatedSize(s), |
563 _getAccumulatedInstances(s), | 609 _getAccumulatedInstances(s), |
564 _getCurrentSize(s), | 610 _getCurrentSize(s), |
565 _getCurrentInstances(s), | 611 _getCurrentInstances(s), |
(...skipping 14 matching lines...) Expand all Loading... |
580 static int _getAccumulatedInstances(M.ClassHeapStats s) => | 626 static int _getAccumulatedInstances(M.ClassHeapStats s) => |
581 s.newSpace.accumulated.instances + s.oldSpace.accumulated.instances; | 627 s.newSpace.accumulated.instances + s.oldSpace.accumulated.instances; |
582 static int _getCurrentSize(M.ClassHeapStats s) => | 628 static int _getCurrentSize(M.ClassHeapStats s) => |
583 s.newSpace.current.bytes + s.oldSpace.current.bytes; | 629 s.newSpace.current.bytes + s.oldSpace.current.bytes; |
584 static int _getCurrentInstances(M.ClassHeapStats s) => | 630 static int _getCurrentInstances(M.ClassHeapStats s) => |
585 s.newSpace.current.instances + s.oldSpace.current.instances; | 631 s.newSpace.current.instances + s.oldSpace.current.instances; |
586 static int _getNewAccumulatedSize(M.ClassHeapStats s) => | 632 static int _getNewAccumulatedSize(M.ClassHeapStats s) => |
587 s.newSpace.accumulated.bytes; | 633 s.newSpace.accumulated.bytes; |
588 static int _getNewAccumulatedInstances(M.ClassHeapStats s) => | 634 static int _getNewAccumulatedInstances(M.ClassHeapStats s) => |
589 s.newSpace.accumulated.instances; | 635 s.newSpace.accumulated.instances; |
590 static int _getNewCurrentSize(M.ClassHeapStats s) => | 636 static int _getNewCurrentSize(M.ClassHeapStats s) => s.newSpace.current.bytes; |
591 s.newSpace.current.bytes; | |
592 static int _getNewCurrentInstances(M.ClassHeapStats s) => | 637 static int _getNewCurrentInstances(M.ClassHeapStats s) => |
593 s.newSpace.current.instances; | 638 s.newSpace.current.instances; |
594 static int _getOldAccumulatedSize(M.ClassHeapStats s) => | 639 static int _getOldAccumulatedSize(M.ClassHeapStats s) => |
595 s.oldSpace.accumulated.bytes; | 640 s.oldSpace.accumulated.bytes; |
596 static int _getOldAccumulatedInstances(M.ClassHeapStats s) => | 641 static int _getOldAccumulatedInstances(M.ClassHeapStats s) => |
597 s.oldSpace.accumulated.instances; | 642 s.oldSpace.accumulated.instances; |
598 static int _getOldCurrentSize(M.ClassHeapStats s) => | 643 static int _getOldCurrentSize(M.ClassHeapStats s) => s.oldSpace.current.bytes; |
599 s.oldSpace.current.bytes; | |
600 static int _getOldCurrentInstances(M.ClassHeapStats s) => | 644 static int _getOldCurrentInstances(M.ClassHeapStats s) => |
601 s.oldSpace.current.instances; | 645 s.oldSpace.current.instances; |
602 } | 646 } |
OLD | NEW |