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, ProfileTreeDirection; | |
| 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 class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable { | |
| 19 static const tag = | |
| 20 const Tag<CpuProfileVirtualTreeElement>('cpu-profile-virtual-tree'); | |
| 21 | |
| 22 RenderingScheduler<CpuProfileVirtualTreeElement> _r; | |
| 23 | |
| 24 Stream<RenderedEvent<CpuProfileVirtualTreeElement>> get onRendered => | |
| 25 _r.onRendered; | |
| 26 | |
| 27 ProfileTreeDirection _direction; | |
| 28 ProfileTreeMode _mode; | |
| 29 M.Isolate _isolate; | |
| 30 M.SampleProfile _profile; | |
| 31 M.CallTreeNodeFilter _filter; | |
| 32 | |
| 33 ProfileTreeDirection get direction => _direction; | |
| 34 ProfileTreeMode get mode => _mode; | |
| 35 M.Isolate get isolate => _isolate; | |
| 36 M.SampleProfile get profile => _profile; | |
| 37 M.CallTreeNodeFilter get filter => _filter; | |
| 38 | |
| 39 set direction(ProfileTreeDirection value) => | |
| 40 _direction = _r.checkAndReact(_direction, value); | |
| 41 set mode(ProfileTreeMode value) => _mode = _r.checkAndReact(_mode, value); | |
| 42 set filter(M.CallTreeNodeFilter value) => | |
| 43 _filter = _r.checkAndReact(_filter, value); | |
| 44 | |
| 45 factory CpuProfileVirtualTreeElement(M.IsolateRef isolate, | |
| 46 M.SampleProfile profile, {ProfileTreeMode mode: ProfileTreeMode.Function, | |
| 47 ProfileTreeDirection direction: ProfileTreeDirection.Exclusive, | |
| 48 RenderingQueue queue}) { | |
| 49 assert(isolate != null); | |
| 50 assert(profile != null); | |
| 51 assert(mode != null); | |
| 52 assert(direction != null); | |
| 53 CpuProfileVirtualTreeElement e = document.createElement(tag.name); | |
| 54 e._r = new RenderingScheduler(e, queue: queue); | |
| 55 e._isolate = isolate; | |
| 56 e._profile = profile; | |
| 57 e._mode = mode; | |
| 58 e._direction = direction; | |
| 59 return e; | |
| 60 } | |
| 61 | |
| 62 | |
| 63 CpuProfileVirtualTreeElement.created() : super.created(); | |
| 64 | |
| 65 @override | |
| 66 attached() { | |
| 67 super.attached(); | |
| 68 _r.enable(); | |
| 69 } | |
| 70 | |
| 71 @override | |
| 72 detached() { | |
| 73 super.detached(); _r.disable(notify: true); | |
| 74 children = []; | |
| 75 } | |
| 76 | |
| 77 void render() { | |
| 78 children = const []; | |
| 79 bool exclusive = direction == ProfileTreeDirection.Exclusive; | |
| 80 switch (mode) { | |
| 81 case ProfileTreeMode.Code: | |
| 82 _buildCodeTree(exclusive); | |
| 83 break; | |
| 84 case ProfileTreeMode.Function: | |
| 85 _buildFunctionTree(exclusive); | |
| 86 break; | |
| 87 default: | |
| 88 throw new Exception('Unknown ProfileTreeMode'); | |
| 89 } | |
| 90 } | |
| 91 | |
| 92 static const kHotThreshold = 0.05; // 5%. | |
| 93 static const kMediumThreshold = 0.02; // 2%. | |
| 94 | |
| 95 void _buildFunctionTree(bool exclusive) { | |
| 96 var tree = _profile.loadFunctionTree(exclusive ? 'exclusive' : 'inclusive'); | |
| 97 if (tree == null) { | |
| 98 return; | |
| 99 } | |
| 100 if (filter != null) { | |
| 101 tree = tree.filtered(filter); | |
| 102 } | |
| 103 var t; | |
| 104 children = [ | |
| 105 t = new VirtualTreeElement((toggle) { | |
|
Cutch
2016/08/02 15:52:20
could this closure be turned into a named method?
cbernaschina
2016/08/02 17:40:24
Done.
| |
| 106 return new DivElement() | |
| 107 ..classes = const ['tmp-collection-item'] | |
| 108 ..children = [ | |
| 109 new SpanElement()..classes = const ['inclusive'] | |
| 110 ..title = 'global % on stack', | |
| 111 new SpanElement()..classes = const ['exclusive'] | |
| 112 ..title = 'global % executing', | |
| 113 new SpanElement()..classes = const ['lines'], | |
| 114 new SpanElement()..classes = const ['expander'] | |
| 115 ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)), | |
| 116 new SpanElement()..classes = const ['percentage'] | |
| 117 ..title = 'tree node %', | |
| 118 new SpanElement()..classes = const ['name'] | |
| 119 ]; | |
| 120 }, (HtmlElement element, M.FunctionCallTreeNode item, int depth) { | |
| 121 element.children[0].text = Utils.formatPercentNormalized( | |
| 122 item.profileFunction.normalizedInclusiveTicks); | |
| 123 element.children[1].text = Utils.formatPercentNormalized( | |
| 124 item.profileFunction.normalizedExclusiveTicks); | |
| 125 _updateLines(element.children[2].children, depth); | |
| 126 if (item.children.isNotEmpty) { | |
| 127 element.children[3].text = t.isExpanded(item) ? '▼' : '►'; | |
| 128 } else { | |
| 129 element.children[3].text = ''; | |
| 130 } | |
| 131 element.children[4].text = Utils.formatPercentNormalized( | |
| 132 item.percentage); | |
| 133 element.children[5] = new FunctionRefElement(_isolate, | |
| 134 item.profileFunction.function, queue: _r.queue) | |
| 135 ..classes = const ['name']; | |
| 136 }, (M.FunctionCallTreeNode node) => node.children, | |
| 137 items: tree.root.children, queue: _r.queue) | |
| 138 ]; | |
| 139 if (tree.root.children.length == 1) { | |
| 140 t.expand(tree.root.children.first, autoExpandSingleChildNodes: true); | |
| 141 } | |
| 142 } | |
| 143 | |
| 144 | |
| 145 | |
| 146 void _buildCodeTree(bool exclusive) { | |
| 147 var tree = _profile.loadCodeTree(exclusive ? 'exclusive' : 'inclusive'); | |
| 148 if (tree == null) { | |
| 149 return; | |
| 150 } | |
| 151 if (filter != null) { | |
| 152 tree = tree.filtered(filter); | |
| 153 } | |
| 154 var t; | |
| 155 children = [ | |
| 156 t = new VirtualTreeElement((toggle) { | |
|
Cutch
2016/08/02 15:52:20
could this closure be turned into a named method?
cbernaschina
2016/08/02 17:40:24
Done.
| |
| 157 return new DivElement() | |
| 158 ..classes = const ['tmp-collection-item'] | |
| 159 ..children = [ | |
| 160 new SpanElement()..classes = const ['inclusive'] | |
| 161 ..title = 'global % on stack', | |
| 162 new SpanElement()..classes = const ['exclusive'] | |
| 163 ..title = 'global % executing', | |
| 164 new SpanElement()..classes = const ['lines'], | |
| 165 new SpanElement()..classes = const ['expander'] | |
| 166 ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)), | |
| 167 new SpanElement()..classes = const ['percentage'] | |
| 168 ..title = 'tree node %', | |
| 169 new AnchorElement()..classes = const ['name'] | |
| 170 ]; | |
| 171 }, (HtmlElement element, M.CodeCallTreeNode item, int depth) { | |
| 172 element.children[0].text = Utils.formatPercentNormalized( | |
| 173 item.profileCode.normalizedInclusiveTicks); | |
| 174 element.children[1].text = Utils.formatPercentNormalized( | |
| 175 item.profileCode.normalizedExclusiveTicks); | |
| 176 _updateLines(element.children[2].children, depth); | |
| 177 if (item.children.isNotEmpty) { | |
| 178 element.children[3].text = t.isExpanded(item) ? '▼' : '►'; | |
| 179 } else { | |
| 180 element.children[3].text = ''; | |
| 181 } | |
| 182 element.children[4].text = Utils.formatPercentNormalized( | |
| 183 item.percentage); | |
| 184 element.children[5] = new CodeRefElement(_isolate, | |
| 185 item.profileCode.code, queue: _r.queue) | |
| 186 ..classes = const ['name']; | |
| 187 }, (M.CodeCallTreeNode node) => node.children, | |
| 188 items: tree.root.children, queue: _r.queue) | |
| 189 ]; | |
| 190 if (tree.root.children.length == 1) { | |
| 191 t.expand(tree.root.children.first, autoExpandSingleChildNodes: true); | |
| 192 } | |
| 193 } | |
| 194 | |
| 195 static _updateLines(List<Element> lines, int n) { | |
| 196 n = Math.max(0, n); | |
| 197 while (lines.length > n) { | |
| 198 lines.removeLast(); | |
| 199 } | |
| 200 while (lines.length < n) { | |
| 201 lines.add(new SpanElement()); | |
| 202 } | |
| 203 } | |
| 204 } | |
| OLD | NEW |