| 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 |