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

Side by Side Diff: runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart

Issue 2748403002: Added page to Observatory to display native memory allocation information. (Closed)
Patch Set: Added page to Observatory to display native memory allocation information. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 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 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 'dart:math' as Math; 7 import 'dart:math' as Math;
8 import 'package:observatory/models.dart' as M; 8 import 'package:observatory/models.dart' as M;
9 import 'package:observatory/src/elements/stack_trace_tree_config.dart' 9 import 'package:observatory/src/elements/stack_trace_tree_config.dart'
10 show ProfileTreeMode; 10 show ProfileTreeMode,
11 ProfileTreeType;
11 import 'package:observatory/src/elements/code_ref.dart'; 12 import 'package:observatory/src/elements/code_ref.dart';
12 import 'package:observatory/src/elements/containers/virtual_tree.dart'; 13 import 'package:observatory/src/elements/containers/virtual_tree.dart';
13 import 'package:observatory/src/elements/function_ref.dart'; 14 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/rendering_scheduler.dart';
15 import 'package:observatory/src/elements/helpers/tag.dart'; 16 import 'package:observatory/src/elements/helpers/tag.dart';
16 import 'package:observatory/utils.dart'; 17 import 'package:observatory/utils.dart';
17 18
18 export 'package:observatory/src/elements/stack_trace_tree_config.dart' 19 export 'package:observatory/src/elements/stack_trace_tree_config.dart'
19 show ProfileTreeMode; 20 show ProfileTreeMode,
21 ProfileTreeType;
20 22
21 class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable { 23 class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable {
22 static const tag = 24 static const tag =
23 const Tag<CpuProfileVirtualTreeElement>('cpu-profile-virtual-tree'); 25 const Tag<CpuProfileVirtualTreeElement>('cpu-profile-virtual-tree');
24 26
25 RenderingScheduler<CpuProfileVirtualTreeElement> _r; 27 RenderingScheduler<CpuProfileVirtualTreeElement> _r;
26 28
27 Stream<RenderedEvent<CpuProfileVirtualTreeElement>> get onRendered => 29 Stream<RenderedEvent<CpuProfileVirtualTreeElement>> get onRendered =>
28 _r.onRendered; 30 _r.onRendered;
29 31
30 M.ProfileTreeDirection _direction; 32 M.ProfileTreeDirection _direction;
31 ProfileTreeMode _mode; 33 ProfileTreeMode _mode;
34 ProfileTreeType _type;
32 M.IsolateRef _isolate; 35 M.IsolateRef _isolate;
33 M.SampleProfile _profile; 36 M.SampleProfile _profile;
34 Iterable<M.CallTreeNodeFilter> _filters; 37 Iterable<M.CallTreeNodeFilter> _filters;
35 38
36 M.ProfileTreeDirection get direction => _direction; 39 M.ProfileTreeDirection get direction => _direction;
37 ProfileTreeMode get mode => _mode; 40 ProfileTreeMode get mode => _mode;
41 ProfileTreeType get type => _type;
38 M.IsolateRef get isolate => _isolate; 42 M.IsolateRef get isolate => _isolate;
39 M.SampleProfile get profile => _profile; 43 M.SampleProfile get profile => _profile;
40 Iterable<M.CallTreeNodeFilter> get filters => _filters; 44 Iterable<M.CallTreeNodeFilter> get filters => _filters;
41 45
42 set direction(M.ProfileTreeDirection value) => 46 set direction(M.ProfileTreeDirection value) =>
43 _direction = _r.checkAndReact(_direction, value); 47 _direction = _r.checkAndReact(_direction, value);
44 set mode(ProfileTreeMode value) => _mode = _r.checkAndReact(_mode, value); 48 set mode(ProfileTreeMode value) => _mode = _r.checkAndReact(_mode, value);
45 set filters(Iterable<M.CallTreeNodeFilter> value) { 49 set filters(Iterable<M.CallTreeNodeFilter> value) {
46 _filters = new List.unmodifiable(value); 50 _filters = new List.unmodifiable(value);
47 _r.dirty(); 51 _r.dirty();
48 } 52 }
49 53
50 factory CpuProfileVirtualTreeElement( 54 factory CpuProfileVirtualTreeElement(
51 M.IsolateRef isolate, M.SampleProfile profile, 55 M.IsolateRef isolate, M.SampleProfile profile,
52 {ProfileTreeMode mode: ProfileTreeMode.function, 56 {ProfileTreeMode mode: ProfileTreeMode.function,
57 ProfileTreeType type: ProfileTreeType.cpu,
53 M.ProfileTreeDirection direction: M.ProfileTreeDirection.exclusive, 58 M.ProfileTreeDirection direction: M.ProfileTreeDirection.exclusive,
54 RenderingQueue queue}) { 59 RenderingQueue queue}) {
55 assert(isolate != null);
56 assert(profile != null); 60 assert(profile != null);
57 assert(mode != null); 61 assert(mode != null);
58 assert(direction != null); 62 assert(direction != null);
59 CpuProfileVirtualTreeElement e = document.createElement(tag.name); 63 CpuProfileVirtualTreeElement e = document.createElement(tag.name);
60 e._r = new RenderingScheduler(e, queue: queue); 64 e._r = new RenderingScheduler(e, queue: queue);
61 e._isolate = isolate; 65 e._isolate = isolate;
62 e._profile = profile; 66 e._profile = profile;
63 e._mode = mode; 67 e._mode = mode;
68 e._type = type;
64 e._direction = direction; 69 e._direction = direction;
65 return e; 70 return e;
66 } 71 }
67 72
68 CpuProfileVirtualTreeElement.created() : super.created(); 73 CpuProfileVirtualTreeElement.created() : super.created();
69 74
70 @override 75 @override
71 attached() { 76 attached() {
72 super.attached(); 77 super.attached();
73 _r.enable(); 78 _r.enable();
74 } 79 }
75 80
76 @override 81 @override
77 detached() { 82 detached() {
78 super.detached(); 83 super.detached();
79 _r.disable(notify: true); 84 _r.disable(notify: true);
80 children = []; 85 children = [];
81 } 86 }
82 87
83 VirtualTreeElement _tree; 88 VirtualTreeElement _tree;
84 89
85 void render() { 90 void render() {
86 var tree; 91 var tree;
92 var create;
87 var update; 93 var update;
94
95 if (type == ProfileTreeType.cpu) {
96 create = _createCpuRow;
97 } else {
98 create = _createMemoryRow;
99 }
100
88 switch (mode) { 101 switch (mode) {
89 case ProfileTreeMode.code: 102 case ProfileTreeMode.code:
90 tree = _profile.loadCodeTree(_direction); 103 tree = _profile.loadCodeTree(_direction);
91 update = _updateCodeRow; 104 if (type == ProfileTreeType.cpu) {
105 update = _updateCpuCodeRow;
106 } else {
Cutch 2017/03/21 20:27:10 } else if (type == ProfileTreeType.memory) { } els
bkonyi 2017/03/22 21:25:21 Done in the check above so we don't have to do it
107 update = _updateMemoryCodeRow;
108 }
92 break; 109 break;
93 case ProfileTreeMode.function: 110 case ProfileTreeMode.function:
94 tree = _profile.loadFunctionTree(_direction); 111 tree = _profile.loadFunctionTree(_direction);
95 update = _updateFunctionRow; 112 if (type == ProfileTreeType.cpu) {
113 update = _updateCpuFunctionRow;
114 } else {
115 update = _updateMemoryFunctionRow;
Cutch 2017/03/21 20:27:10 ditto
bkonyi 2017/03/22 21:25:21 See above response.
116 }
96 break; 117 break;
97 default: 118 default:
98 throw new Exception('Unknown ProfileTreeMode: $mode'); 119 throw new Exception('Unknown ProfileTreeMode: $mode');
99 } 120 }
100 if (filters != null) { 121 if (filters != null) {
101 tree = filters.fold(tree, (tree, filter) { 122 tree = filters.fold(tree, (tree, filter) {
102 return tree?.filtered(filter); 123 return tree?.filtered(filter);
103 }); 124 });
104 } 125 }
105 if (tree == null) { 126 if (tree == null) {
106 children = [new HeadingElement.h1()..text = 'No Results']; 127 children = [new HeadingElement.h1()..text = 'No Results'];
107 return; 128 return;
108 } 129 }
109 _tree = new VirtualTreeElement(_createRow, update, _getChildren, 130 _tree = new VirtualTreeElement(create, update, _getChildren,
110 items: tree.root.children, queue: _r.queue); 131 items: tree.root.children, queue: _r.queue);
111 if (tree.root.children.length == 1) { 132 if (tree.root.children.length == 1) {
112 _tree.expand(tree.root.children.first, autoExpandSingleChildNodes: true); 133 _tree.expand(tree.root.children.first, autoExpandSingleChildNodes: true);
113 } 134 }
114 children = [_tree]; 135 children = [_tree];
115 } 136 }
116 137
117 static Element _createRow(toggle) { 138 static Element _createCpuRow(toggle) {
118 return new DivElement() 139 return new DivElement()
119 ..classes = ['tree-item'] 140 ..classes = ['tree-item']
120 ..children = [ 141 ..children = [
121 new SpanElement() 142 new SpanElement()
122 ..classes = ['inclusive'] 143 ..classes = ['inclusive']
123 ..title = 'global % on stack', 144 ..title = 'global % on stack',
124 new SpanElement() 145 new SpanElement()
125 ..classes = ['exclusive'] 146 ..classes = ['exclusive']
126 ..title = 'global % executing', 147 ..title = 'global % executing',
127 new SpanElement()..classes = ['lines'], 148 new SpanElement()..classes = ['lines'],
128 new ButtonElement() 149 new ButtonElement()
129 ..classes = ['expander'] 150 ..classes = ['expander']
130 ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)), 151 ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
131 new SpanElement() 152 new SpanElement()
132 ..classes = ['percentage'] 153 ..classes = ['percentage']
133 ..title = 'tree node %', 154 ..title = 'tree node %',
134 new SpanElement()..classes = ['name'] 155 new SpanElement()..classes = ['name']
135 ]; 156 ];
136 } 157 }
137 158
159 static Element _createMemoryRow(toggle) {
160 return new DivElement()
161 ..classes = ['tree-item']
162 ..children = [
163 new SpanElement()
164 ..classes = ['inclusive']
165 ..title = 'memory allocated from resulting calls: ',
166 new SpanElement()
167 ..classes = ['exclusive']
168 ..title = 'memory allocated during execution: ',
169 new SpanElement()..classes = ['lines'],
170 new ButtonElement()
171 ..classes = ['expander']
172 ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
173 new SpanElement()
174 ..classes = ['percentage']
175 ..title = 'tree node %',
176 new SpanElement()..classes = ['name']
177 ];
178 }
179
138 static _getChildren(M.CallTreeNode node) => node.children; 180 static _getChildren(M.CallTreeNode node) => node.children;
139 181
140 void _updateFunctionRow( 182 void _updateCpuFunctionRow(
141 HtmlElement element, M.FunctionCallTreeNode item, int depth) { 183 HtmlElement element, M.FunctionCallTreeNode item, int depth) {
142 element.children[0].text = Utils 184 element.children[0].text = Utils
143 .formatPercentNormalized(item.profileFunction.normalizedInclusiveTicks); 185 .formatPercentNormalized(item.profileFunction.normalizedInclusiveTicks);
144 element.children[1].text = Utils 186 element.children[1].text = Utils
145 .formatPercentNormalized(item.profileFunction.normalizedExclusiveTicks); 187 .formatPercentNormalized(item.profileFunction.normalizedExclusiveTicks);
146 _updateLines(element.children[2].children, depth); 188 _updateLines(element.children[2].children, depth);
147 if (item.children.isNotEmpty) { 189 if (item.children.isNotEmpty) {
148 element.children[3].text = _tree.isExpanded(item) ? '▼' : '►'; 190 element.children[3].text = _tree.isExpanded(item) ? '▼' : '►';
Cutch 2017/03/21 20:27:10 factor these strings into named constants and use
149 } else { 191 } else {
150 element.children[3].text = ''; 192 element.children[3].text = '';
151 } 193 }
152 element.children[4].text = Utils.formatPercentNormalized(item.percentage); 194 element.children[4].text = Utils.formatPercentNormalized(item.percentage);
153 element.children[5] = new FunctionRefElement( 195 element.children[5] = new FunctionRefElement(
154 _isolate, item.profileFunction.function, queue: _r.queue) 196 _isolate, item.profileFunction.function, queue: _r.queue)
155 ..classes = ['name']; 197 ..classes = ['name'];
156 } 198 }
157 199
158 void _updateCodeRow(HtmlElement element, M.CodeCallTreeNode item, int depth) { 200 void _updateMemoryFunctionRow(
201 HtmlElement element, M.FunctionCallTreeNode item, int depth) {
202 element.children[0].text = Utils
203 .formatSize(item.inclusiveNativeAllocations);
204 element.children[0].title = 'memory allocated from resulting calls: ' +
205 '${item.inclusiveNativeAllocations}B';
206 element.children[1].text = Utils
207 .formatSize(item.exclusiveNativeAllocations);
208 element.children[1].title = 'memory allocated during execution: ' +
209 '${item.exclusiveNativeAllocations}B';
210 _updateLines(element.children[2].children, depth);
211 if (item.children.isNotEmpty) {
212 element.children[3].text = _tree.isExpanded(item) ? '▼' : '►';
213 } else {
214 element.children[3].text = '';
215 }
216 element.children[4].text =
217 Utils.formatPercentNormalized(item.percentage);
218 element.children[5] = new FunctionRefElement(
219 null, item.profileFunction.function, queue: _r.queue)
220 ..classes = ['name'];
221 }
222
223 void _updateCpuCodeRow(HtmlElement element, M.CodeCallTreeNode item, int depth ) {
159 element.children[0].text = Utils 224 element.children[0].text = Utils
160 .formatPercentNormalized(item.profileCode.normalizedInclusiveTicks); 225 .formatPercentNormalized(item.profileCode.normalizedInclusiveTicks);
161 element.children[1].text = Utils 226 element.children[1].text = Utils
162 .formatPercentNormalized(item.profileCode.normalizedExclusiveTicks); 227 .formatPercentNormalized(item.profileCode.normalizedExclusiveTicks);
163 _updateLines(element.children[2].children, depth); 228 _updateLines(element.children[2].children, depth);
164 if (item.children.isNotEmpty) { 229 if (item.children.isNotEmpty) {
165 element.children[3].text = _tree.isExpanded(item) ? '▼' : '►'; 230 element.children[3].text = _tree.isExpanded(item) ? '▼' : '►';
166 } else { 231 } else {
167 element.children[3].text = ''; 232 element.children[3].text = '';
168 } 233 }
169 element.children[4].text = Utils.formatPercentNormalized(item.percentage); 234 element.children[4].text = Utils.formatPercentNormalized(item.percentage);
170 element.children[5] = new CodeRefElement(_isolate, item.profileCode.code, 235 element.children[5] = new CodeRefElement(_isolate, item.profileCode.code,
171 queue: _r.queue)..classes = ['name']; 236 queue: _r.queue)..classes = ['name'];
172 } 237 }
173 238
239 void _updateMemoryCodeRow(HtmlElement element, M.CodeCallTreeNode item, int de pth) {
Cutch 2017/03/21 20:27:10 long line..
bkonyi 2017/03/22 21:25:21 Done.
240 element.children[0].text = Utils
241 .formatSize(item.inclusiveNativeAllocations);
242 element.children[0].title = 'memory allocated from resulting calls: ' +
243 '${item.inclusiveNativeAllocations}B';
244 element.children[1].text = Utils
245 .formatSize(item.exclusiveNativeAllocations);
246 element.children[1].title = 'memory allocated during execution: ' +
247 '${item.exclusiveNativeAllocations}B';
248 _updateLines(element.children[2].children, depth);
249 if (item.children.isNotEmpty) {
250 element.children[3].text = _tree.isExpanded(item) ? '▼' : '►';
251 } else {
252 element.children[3].text = '';
253 }
254 element.children[4].text =
255 Utils.formatPercentNormalized(item.percentage);
256 element.children[5] = new CodeRefElement(null, item.profileCode.code,
257 queue: _r.queue)..classes = ['name'];
258 }
259
174 static _updateLines(List<Element> lines, int n) { 260 static _updateLines(List<Element> lines, int n) {
175 n = Math.max(0, n); 261 n = Math.max(0, n);
176 while (lines.length > n) { 262 while (lines.length > n) {
177 lines.removeLast(); 263 lines.removeLast();
178 } 264 }
179 while (lines.length < n) { 265 while (lines.length < n) {
180 lines.add(new SpanElement()); 266 lines.add(new SpanElement());
181 } 267 }
182 } 268 }
183 } 269 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698