Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 import 'dart:async'; | |
| 6 import 'dart:html'; | |
| 7 import 'dart:math' as Math; | |
| 8 import 'package:observatory/models.dart' as M; | |
| 9 import 'package:observatory/src/elements/stack_trace_tree_config.dart' | |
| 10 show ProfileTreeMode; | |
| 11 import 'package:observatory/src/elements/code_ref.dart'; | |
| 12 import 'package:observatory/src/elements/containers/virtual_tree.dart'; | |
| 13 import 'package:observatory/src/elements/function_ref.dart'; | |
| 14 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; | |
| 15 import 'package:observatory/src/elements/helpers/tag.dart'; | |
| 16 import 'package:observatory/utils.dart'; | |
| 17 | |
| 18 export 'package:observatory/src/elements/stack_trace_tree_config.dart' | |
| 19 show ProfileTreeMode; | |
| 20 | |
| 21 class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable { | |
| 22 static const tag = | |
| 23 const Tag<CpuProfileVirtualTreeElement>('cpu-profile-virtual-tree'); | |
| 24 | |
| 25 RenderingScheduler<CpuProfileVirtualTreeElement> _r; | |
| 26 | |
| 27 Stream<RenderedEvent<CpuProfileVirtualTreeElement>> get onRendered => | |
| 28 _r.onRendered; | |
| 29 | |
| 30 M.ProfileTreeDirection _direction; | |
| 31 ProfileTreeMode _mode; | |
| 32 M.IsolateRef _isolate; | |
| 33 M.SampleProfile _profile; | |
| 34 M.CallTreeNodeFilter _filter; | |
| 35 | |
| 36 M.ProfileTreeDirection get direction => _direction; | |
| 37 ProfileTreeMode get mode => _mode; | |
| 38 M.IsolateRef get isolate => _isolate; | |
| 39 M.SampleProfile get profile => _profile; | |
| 40 M.CallTreeNodeFilter get filter => _filter; | |
| 41 | |
| 42 set direction(M.ProfileTreeDirection value) => | |
| 43 _direction = _r.checkAndReact(_direction, value); | |
| 44 set mode(ProfileTreeMode value) => _mode = _r.checkAndReact(_mode, value); | |
| 45 set filter(M.CallTreeNodeFilter value) => | |
| 46 _filter = _r.checkAndReact(_filter, value); | |
| 47 | |
| 48 factory CpuProfileVirtualTreeElement(M.IsolateRef isolate, | |
| 49 M.SampleProfile profile, {ProfileTreeMode mode: ProfileTreeMode.function, | |
| 50 M.ProfileTreeDirection direction: M.ProfileTreeDirection.exclusive, | |
| 51 RenderingQueue queue}) { | |
| 52 assert(isolate != null); | |
| 53 assert(profile != null); | |
| 54 assert(mode != null); | |
| 55 assert(direction != null); | |
| 56 CpuProfileVirtualTreeElement e = document.createElement(tag.name); | |
| 57 e._r = new RenderingScheduler(e, queue: queue); | |
| 58 e._isolate = isolate; | |
| 59 e._profile = profile; | |
| 60 e._mode = mode; | |
| 61 e._direction = direction; | |
| 62 return e; | |
| 63 } | |
| 64 | |
| 65 | |
| 66 CpuProfileVirtualTreeElement.created() : super.created(); | |
| 67 | |
| 68 @override | |
| 69 attached() { | |
| 70 super.attached(); | |
| 71 _r.enable(); | |
| 72 } | |
| 73 | |
| 74 @override | |
| 75 detached() { | |
| 76 super.detached(); _r.disable(notify: true); | |
| 77 children = []; | |
| 78 } | |
| 79 | |
| 80 VirtualTreeElement _tree; | |
| 81 | |
| 82 void render() { | |
| 83 var tree; | |
| 84 var update; | |
| 85 switch (mode) { | |
| 86 case ProfileTreeMode.code: | |
| 87 tree = _profile.loadCodeTree(_direction); | |
| 88 update = _updateCodeRow; | |
| 89 break; | |
| 90 case ProfileTreeMode.function: | |
| 91 tree = _profile.loadFunctionTree(_direction); | |
| 92 update = _updateFunctionRow; | |
| 93 break; | |
| 94 default: | |
| 95 throw new Exception('Unknown ProfileTreeMode'); | |
|
rmacnak
2016/08/09 20:51:06
'Unknown ProfileTreeMode: $mode'
cbernaschina
2016/08/09 21:16:54
Done.
| |
| 96 } | |
| 97 if (tree == null) { | |
| 98 children = [ | |
| 99 new HeadingElement.h1()..text = 'No Results' | |
| 100 ]; | |
| 101 return; | |
| 102 } | |
| 103 if (filter != null) { | |
| 104 tree = tree.filtered(filter); | |
| 105 } | |
| 106 _tree = new VirtualTreeElement(_createRow, update, _getChildren, | |
| 107 items: tree.root.children, queue: _r.queue); | |
| 108 if (tree.root.children.length == 1) { | |
| 109 _tree.expand(tree.root.children.first, autoExpandSingleChildNodes: true); | |
| 110 } | |
| 111 children = [_tree]; | |
| 112 } | |
| 113 | |
| 114 static Element _createRow(toggle) { | |
| 115 return new DivElement() | |
| 116 ..classes = const ['tree-item'] | |
| 117 ..children = [ | |
| 118 new SpanElement()..classes = const ['inclusive'] | |
| 119 ..title = 'global % on stack', | |
| 120 new SpanElement()..classes = const ['exclusive'] | |
| 121 ..title = 'global % executing', | |
| 122 new SpanElement()..classes = const ['lines'], | |
| 123 new ButtonElement()..classes = const ['expander'] | |
| 124 ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)), | |
| 125 new SpanElement()..classes = const ['percentage'] | |
| 126 ..title = 'tree node %', | |
| 127 new SpanElement()..classes = const ['name'] | |
| 128 ]; | |
| 129 } | |
| 130 | |
| 131 static _getChildren(M.CallTreeNode node) => node.children; | |
| 132 | |
| 133 void _updateFunctionRow(HtmlElement element, M.FunctionCallTreeNode item, | |
| 134 int depth) { | |
| 135 element.children[0].text = Utils.formatPercentNormalized( | |
| 136 item.profileFunction.normalizedInclusiveTicks); | |
| 137 element.children[1].text = Utils.formatPercentNormalized( | |
| 138 item.profileFunction.normalizedExclusiveTicks); | |
| 139 _updateLines(element.children[2].children, depth); | |
| 140 if (item.children.isNotEmpty) { | |
| 141 element.children[3].text = _tree.isExpanded(item) ? '▼' : '►'; | |
| 142 } else { | |
| 143 element.children[3].text = ''; | |
| 144 } | |
| 145 element.children[4].text = Utils.formatPercentNormalized( | |
| 146 item.percentage); | |
| 147 element.children[5] = new FunctionRefElement(_isolate, | |
| 148 item.profileFunction.function, queue: _r.queue) | |
| 149 ..classes = const ['name']; | |
| 150 } | |
| 151 | |
| 152 void _updateCodeRow(HtmlElement element, M.CodeCallTreeNode item, int depth) { | |
| 153 element.children[0].text = Utils.formatPercentNormalized( | |
| 154 item.profileCode.normalizedInclusiveTicks); | |
| 155 element.children[1].text = Utils.formatPercentNormalized( | |
| 156 item.profileCode.normalizedExclusiveTicks); | |
| 157 _updateLines(element.children[2].children, depth); | |
| 158 if (item.children.isNotEmpty) { | |
| 159 element.children[3].text = _tree.isExpanded(item) ? '▼' : '►'; | |
| 160 } else { | |
| 161 element.children[3].text = ''; | |
| 162 } | |
| 163 element.children[4].text = Utils.formatPercentNormalized( | |
| 164 item.percentage); | |
| 165 element.children[5] = new CodeRefElement(_isolate, | |
| 166 item.profileCode.code, queue: _r.queue) | |
| 167 ..classes = const ['name']; | |
| 168 } | |
| 169 | |
| 170 static _updateLines(List<Element> lines, int n) { | |
| 171 n = Math.max(0, n); | |
| 172 while (lines.length > n) { | |
| 173 lines.removeLast(); | |
| 174 } | |
| 175 while (lines.length < n) { | |
| 176 lines.add(new SpanElement()); | |
| 177 } | |
| 178 } | |
| 179 } | |
| OLD | NEW |