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

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

Issue 2771293003: Resubmission of native memory allocation info surfacing in Observatory. Fixed crashing tests and st… (Closed)
Patch Set: Added page to Observatory to display native memory allocation information. Created 3 years, 8 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;
(...skipping 11 matching lines...) Expand all
22 static const tag = 22 static const tag =
23 const Tag<CpuProfileVirtualTreeElement>('cpu-profile-virtual-tree'); 23 const Tag<CpuProfileVirtualTreeElement>('cpu-profile-virtual-tree');
24 24
25 RenderingScheduler<CpuProfileVirtualTreeElement> _r; 25 RenderingScheduler<CpuProfileVirtualTreeElement> _r;
26 26
27 Stream<RenderedEvent<CpuProfileVirtualTreeElement>> get onRendered => 27 Stream<RenderedEvent<CpuProfileVirtualTreeElement>> get onRendered =>
28 _r.onRendered; 28 _r.onRendered;
29 29
30 M.ProfileTreeDirection _direction; 30 M.ProfileTreeDirection _direction;
31 ProfileTreeMode _mode; 31 ProfileTreeMode _mode;
32 M.SampleProfileType _type;
32 M.IsolateRef _isolate; 33 M.IsolateRef _isolate;
33 M.SampleProfile _profile; 34 M.SampleProfile _profile;
34 Iterable<M.CallTreeNodeFilter> _filters; 35 Iterable<M.CallTreeNodeFilter> _filters;
35 36
36 M.ProfileTreeDirection get direction => _direction; 37 M.ProfileTreeDirection get direction => _direction;
37 ProfileTreeMode get mode => _mode; 38 ProfileTreeMode get mode => _mode;
39 M.SampleProfileType get type => _type;
38 M.IsolateRef get isolate => _isolate; 40 M.IsolateRef get isolate => _isolate;
39 M.SampleProfile get profile => _profile; 41 M.SampleProfile get profile => _profile;
40 Iterable<M.CallTreeNodeFilter> get filters => _filters; 42 Iterable<M.CallTreeNodeFilter> get filters => _filters;
41 43
42 set direction(M.ProfileTreeDirection value) => 44 set direction(M.ProfileTreeDirection value) =>
43 _direction = _r.checkAndReact(_direction, value); 45 _direction = _r.checkAndReact(_direction, value);
44 set mode(ProfileTreeMode value) => _mode = _r.checkAndReact(_mode, value); 46 set mode(ProfileTreeMode value) => _mode = _r.checkAndReact(_mode, value);
45 set filters(Iterable<M.CallTreeNodeFilter> value) { 47 set filters(Iterable<M.CallTreeNodeFilter> value) {
46 _filters = new List.unmodifiable(value); 48 _filters = new List.unmodifiable(value);
47 _r.dirty(); 49 _r.dirty();
48 } 50 }
49 51
50 factory CpuProfileVirtualTreeElement( 52 factory CpuProfileVirtualTreeElement(
51 M.IsolateRef isolate, M.SampleProfile profile, 53 M.IsolateRef isolate, M.SampleProfile profile,
52 {ProfileTreeMode mode: ProfileTreeMode.function, 54 {ProfileTreeMode mode: ProfileTreeMode.function,
55 M.SampleProfileType type: M.SampleProfileType.cpu,
53 M.ProfileTreeDirection direction: M.ProfileTreeDirection.exclusive, 56 M.ProfileTreeDirection direction: M.ProfileTreeDirection.exclusive,
54 RenderingQueue queue}) { 57 RenderingQueue queue}) {
55 assert(isolate != null);
56 assert(profile != null); 58 assert(profile != null);
57 assert(mode != null); 59 assert(mode != null);
58 assert(direction != null); 60 assert(direction != null);
59 CpuProfileVirtualTreeElement e = document.createElement(tag.name); 61 CpuProfileVirtualTreeElement e = document.createElement(tag.name);
60 e._r = new RenderingScheduler(e, queue: queue); 62 e._r = new RenderingScheduler(e, queue: queue);
61 e._isolate = isolate; 63 e._isolate = isolate;
62 e._profile = profile; 64 e._profile = profile;
63 e._mode = mode; 65 e._mode = mode;
66 e._type = type;
64 e._direction = direction; 67 e._direction = direction;
65 return e; 68 return e;
66 } 69 }
67 70
68 CpuProfileVirtualTreeElement.created() : super.created(); 71 CpuProfileVirtualTreeElement.created() : super.created();
69 72
70 @override 73 @override
71 attached() { 74 attached() {
72 super.attached(); 75 super.attached();
73 _r.enable(); 76 _r.enable();
74 } 77 }
75 78
76 @override 79 @override
77 detached() { 80 detached() {
78 super.detached(); 81 super.detached();
79 _r.disable(notify: true); 82 _r.disable(notify: true);
80 children = []; 83 children = [];
81 } 84 }
82 85
83 VirtualTreeElement _tree; 86 VirtualTreeElement _tree;
84 87
85 void render() { 88 void render() {
86 var tree; 89 var tree;
90 var create;
87 var update; 91 var update;
88 switch (mode) { 92
89 case ProfileTreeMode.code: 93 switch (type) {
90 tree = _profile.loadCodeTree(_direction); 94 case M.SampleProfileType.cpu:
91 update = _updateCodeRow; 95 create = _createCpuRow;
96 if (mode == ProfileTreeMode.code) {
97 update = _updateCpuCodeRow;
98 tree = _profile.loadCodeTree(_direction);
99 } else if (mode == ProfileTreeMode.function) {
100 update = _updateCpuFunctionRow;
101 tree = _profile.loadFunctionTree(_direction);
102 } else {
103 throw new Exception('Unknown ProfileTreeMode: $mode');
104 }
92 break; 105 break;
93 case ProfileTreeMode.function: 106 case M.SampleProfileType.memory:
94 tree = _profile.loadFunctionTree(_direction); 107 create = _createMemoryRow;
95 update = _updateFunctionRow; 108 if (mode == ProfileTreeMode.code) {
109 update = _updateMemoryCodeRow;
110 tree = _profile.loadCodeTree(_direction);
111 } else if (mode == ProfileTreeMode.function) {
112 update = _updateMemoryFunctionRow;
113 tree = _profile.loadFunctionTree(_direction);
114 } else {
115 throw new Exception('Unknown ProfileTreeMode: $mode');
116 }
96 break; 117 break;
97 default: 118 default:
98 throw new Exception('Unknown ProfileTreeMode: $mode'); 119 throw new Exception('Unknown SampleProfileType: $type');
120 break;
99 } 121 }
100 if (filters != null) { 122 if (filters != null) {
101 tree = filters.fold(tree, (tree, filter) { 123 tree = filters.fold(tree, (tree, filter) {
102 return tree?.filtered(filter); 124 return tree?.filtered(filter);
103 }); 125 });
104 } 126 }
105 if (tree == null) { 127 if (tree == null) {
106 children = [new HeadingElement.h1()..text = 'No Results']; 128 children = [new HeadingElement.h1()..text = 'No Results'];
107 return; 129 return;
108 } 130 }
109 _tree = new VirtualTreeElement(_createRow, update, _getChildren, 131 _tree = new VirtualTreeElement(create, update, _getChildren,
110 items: tree.root.children, queue: _r.queue); 132 items: tree.root.children, queue: _r.queue);
111 if (tree.root.children.length == 1) { 133 if (tree.root.children.length == 1) {
112 _tree.expand(tree.root.children.first, autoExpandSingleChildNodes: true); 134 _tree.expand(tree.root.children.first, autoExpandSingleChildNodes: true);
113 } 135 }
114 children = [_tree]; 136 children = [_tree];
115 } 137 }
116 138
117 static Element _createRow(toggle) { 139 static Element _createCpuRow(toggle) {
118 return new DivElement() 140 return new DivElement()
119 ..classes = ['tree-item'] 141 ..classes = ['tree-item']
120 ..children = [ 142 ..children = [
121 new SpanElement() 143 new SpanElement()
122 ..classes = ['inclusive'] 144 ..classes = ['inclusive']
123 ..title = 'global % on stack', 145 ..title = 'global % on stack',
124 new SpanElement() 146 new SpanElement()
125 ..classes = ['exclusive'] 147 ..classes = ['exclusive']
126 ..title = 'global % executing', 148 ..title = 'global % executing',
127 new SpanElement()..classes = ['lines'], 149 new SpanElement()..classes = ['lines'],
128 new ButtonElement() 150 new ButtonElement()
129 ..classes = ['expander'] 151 ..classes = ['expander']
130 ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)), 152 ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
131 new SpanElement() 153 new SpanElement()
132 ..classes = ['percentage'] 154 ..classes = ['percentage']
133 ..title = 'tree node %', 155 ..title = 'tree node %',
134 new SpanElement()..classes = ['name'] 156 new SpanElement()..classes = ['name']
135 ]; 157 ];
136 } 158 }
137 159
160 static Element _createMemoryRow(toggle) {
161 return new DivElement()
162 ..classes = ['tree-item']
163 ..children = [
164 new SpanElement()
165 ..classes = ['inclusive']
166 ..title = 'memory allocated from resulting calls: ',
167 new SpanElement()
168 ..classes = ['exclusive']
169 ..title = 'memory allocated during execution: ',
170 new SpanElement()..classes = ['lines'],
171 new ButtonElement()
172 ..classes = ['expander']
173 ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
174 new SpanElement()
175 ..classes = ['percentage']
176 ..title = 'tree node %',
177 new SpanElement()..classes = ['name']
178 ];
179 }
180
138 static _getChildren(M.CallTreeNode node) => node.children; 181 static _getChildren(M.CallTreeNode node) => node.children;
139 182
140 void _updateFunctionRow( 183 static const String _expandedIcon = '▼';
184 static const String _collapsedIcon = '►';
185
186 void _updateCpuFunctionRow(
141 HtmlElement element, M.FunctionCallTreeNode item, int depth) { 187 HtmlElement element, M.FunctionCallTreeNode item, int depth) {
142 element.children[0].text = Utils 188 element.children[0].text = Utils
143 .formatPercentNormalized(item.profileFunction.normalizedInclusiveTicks); 189 .formatPercentNormalized(item.profileFunction.normalizedInclusiveTicks);
144 element.children[1].text = Utils 190 element.children[1].text = Utils
145 .formatPercentNormalized(item.profileFunction.normalizedExclusiveTicks); 191 .formatPercentNormalized(item.profileFunction.normalizedExclusiveTicks);
146 _updateLines(element.children[2].children, depth); 192 _updateLines(element.children[2].children, depth);
147 if (item.children.isNotEmpty) { 193 if (item.children.isNotEmpty) {
148 element.children[3].text = _tree.isExpanded(item) ? '▼' : '►'; 194 element.children[3].text =
195 _tree.isExpanded(item) ? _expandedIcon : _collapsedIcon;
149 } else { 196 } else {
150 element.children[3].text = ''; 197 element.children[3].text = '';
151 } 198 }
152 element.children[4].text = Utils.formatPercentNormalized(item.percentage); 199 element.children[4].text = Utils.formatPercentNormalized(item.percentage);
153 element.children[5] = new FunctionRefElement( 200 element.children[5] = new FunctionRefElement(
154 _isolate, item.profileFunction.function, queue: _r.queue) 201 _isolate, item.profileFunction.function, queue: _r.queue)
155 ..classes = ['name']; 202 ..classes = ['name'];
156 } 203 }
157 204
158 void _updateCodeRow(HtmlElement element, M.CodeCallTreeNode item, int depth) { 205 void _updateMemoryFunctionRow(
206 HtmlElement element, M.FunctionCallTreeNode item, int depth) {
207 element.children[0].text =
208 Utils.formatSize(item.inclusiveNativeAllocations);
209 element.children[0].title = 'memory allocated from resulting calls: ' +
210 '${item.inclusiveNativeAllocations}B';
211 element.children[1].text =
212 Utils.formatSize(item.exclusiveNativeAllocations);
213 element.children[1].title = 'memory allocated during execution: ' +
214 '${item.exclusiveNativeAllocations}B';
215 _updateLines(element.children[2].children, depth);
216 if (item.children.isNotEmpty) {
217 element.children[3].text =
218 _tree.isExpanded(item) ? _expandedIcon : _collapsedIcon;
219 } else {
220 element.children[3].text = '';
221 }
222 element.children[4].text = Utils.formatPercentNormalized(item.percentage);
223 element.children[5] = new FunctionRefElement(
224 null, item.profileFunction.function, queue: _r.queue)
225 ..classes = ['name'];
226 }
227
228 void _updateCpuCodeRow(
229 HtmlElement element, M.CodeCallTreeNode item, int depth) {
159 element.children[0].text = Utils 230 element.children[0].text = Utils
160 .formatPercentNormalized(item.profileCode.normalizedInclusiveTicks); 231 .formatPercentNormalized(item.profileCode.normalizedInclusiveTicks);
161 element.children[1].text = Utils 232 element.children[1].text = Utils
162 .formatPercentNormalized(item.profileCode.normalizedExclusiveTicks); 233 .formatPercentNormalized(item.profileCode.normalizedExclusiveTicks);
163 _updateLines(element.children[2].children, depth); 234 _updateLines(element.children[2].children, depth);
164 if (item.children.isNotEmpty) { 235 if (item.children.isNotEmpty) {
165 element.children[3].text = _tree.isExpanded(item) ? '▼' : '►'; 236 element.children[3].text =
237 _tree.isExpanded(item) ? _expandedIcon : _collapsedIcon;
166 } else { 238 } else {
167 element.children[3].text = ''; 239 element.children[3].text = '';
168 } 240 }
169 element.children[4].text = Utils.formatPercentNormalized(item.percentage); 241 element.children[4].text = Utils.formatPercentNormalized(item.percentage);
170 element.children[5] = new CodeRefElement(_isolate, item.profileCode.code, 242 element.children[5] = new CodeRefElement(_isolate, item.profileCode.code,
171 queue: _r.queue)..classes = ['name']; 243 queue: _r.queue)..classes = ['name'];
172 } 244 }
173 245
246 void _updateMemoryCodeRow(
247 HtmlElement element, M.CodeCallTreeNode item, int depth) {
248 element.children[0].text =
249 Utils.formatSize(item.inclusiveNativeAllocations);
250 element.children[0].title = 'memory allocated from resulting calls: ' +
251 '${item.inclusiveNativeAllocations}B';
252 element.children[1].text =
253 Utils.formatSize(item.exclusiveNativeAllocations);
254 element.children[1].title = 'memory allocated during execution: ' +
255 '${item.exclusiveNativeAllocations}B';
256 _updateLines(element.children[2].children, depth);
257 if (item.children.isNotEmpty) {
258 element.children[3].text =
259 _tree.isExpanded(item) ? _expandedIcon : _collapsedIcon;
260 } else {
261 element.children[3].text = '';
262 }
263 element.children[4].text = Utils.formatPercentNormalized(item.percentage);
264 element.children[5] = new CodeRefElement(null, item.profileCode.code,
265 queue: _r.queue)..classes = ['name'];
266 }
267
174 static _updateLines(List<Element> lines, int n) { 268 static _updateLines(List<Element> lines, int n) {
175 n = Math.max(0, n); 269 n = Math.max(0, n);
176 while (lines.length > n) { 270 while (lines.length > n) {
177 lines.removeLast(); 271 lines.removeLast();
178 } 272 }
179 while (lines.length < n) { 273 while (lines.length < n) {
180 lines.add(new SpanElement()); 274 lines.add(new SpanElement());
181 } 275 }
182 } 276 }
183 } 277 }
OLDNEW
« no previous file with comments | « runtime/observatory/lib/src/elements/code_ref.dart ('k') | runtime/observatory/lib/src/elements/function_ref.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698