OLD | NEW |
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 library cpu_profile_table_element; | 5 library cpu_profile_table_element; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:html'; | 8 import 'dart:html'; |
9 import 'package:observatory/models.dart' as M; | 9 import 'package:observatory/models.dart' as M; |
10 import 'package:observatory/src/elements/containers/virtual_collection.dart'; | 10 import 'package:observatory/src/elements/containers/virtual_collection.dart'; |
11 import 'package:observatory/src/elements/cpu_profile/virtual_tree.dart'; | 11 import 'package:observatory/src/elements/cpu_profile/virtual_tree.dart'; |
12 import 'package:observatory/src/elements/function_ref.dart'; | 12 import 'package:observatory/src/elements/function_ref.dart'; |
13 import 'package:observatory/src/elements/helpers/nav_bar.dart'; | 13 import 'package:observatory/src/elements/helpers/nav_bar.dart'; |
14 import 'package:observatory/src/elements/helpers/nav_menu.dart'; | 14 import 'package:observatory/src/elements/helpers/nav_menu.dart'; |
15 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; | 15 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; |
16 import 'package:observatory/src/elements/helpers/tag.dart'; | 16 import 'package:observatory/src/elements/helpers/tag.dart'; |
17 import 'package:observatory/src/elements/nav/isolate_menu.dart'; | 17 import 'package:observatory/src/elements/nav/isolate_menu.dart'; |
18 import 'package:observatory/src/elements/nav/notify.dart'; | 18 import 'package:observatory/src/elements/nav/notify.dart'; |
19 import 'package:observatory/src/elements/nav/refresh.dart'; | 19 import 'package:observatory/src/elements/nav/refresh.dart'; |
20 import 'package:observatory/src/elements/nav/top_menu.dart'; | 20 import 'package:observatory/src/elements/nav/top_menu.dart'; |
21 import 'package:observatory/src/elements/nav/vm_menu.dart'; | 21 import 'package:observatory/src/elements/nav/vm_menu.dart'; |
22 import 'package:observatory/src/elements/sample_buffer_control.dart'; | 22 import 'package:observatory/src/elements/sample_buffer_control.dart'; |
23 import 'package:observatory/src/elements/stack_trace_tree_config.dart'; | 23 import 'package:observatory/src/elements/stack_trace_tree_config.dart'; |
24 import 'package:observatory/utils.dart'; | 24 import 'package:observatory/utils.dart'; |
25 | 25 |
26 enum _Table { | 26 enum _Table { functions, caller, callee } |
27 functions, | |
28 caller, | |
29 callee | |
30 } | |
31 | 27 |
32 enum _SortingField { | 28 enum _SortingField { exclusive, inclusive, caller, callee, method } |
33 exclusive, | |
34 inclusive, | |
35 caller, | |
36 callee, | |
37 method | |
38 } | |
39 | 29 |
40 enum _SortingDirection { | 30 enum _SortingDirection { ascending, descending } |
41 ascending, | |
42 descending | |
43 } | |
44 | 31 |
45 class CpuProfileTableElement extends HtmlElement implements Renderable { | 32 class CpuProfileTableElement extends HtmlElement implements Renderable { |
46 static const tag = const Tag<CpuProfileTableElement>('cpu-profile-table', | 33 static const tag = const Tag<CpuProfileTableElement>('cpu-profile-table', |
47 dependencies: const [ | 34 dependencies: const [ |
48 FunctionRefElement.tag, | 35 FunctionRefElement.tag, |
49 NavTopMenuElement.tag, | 36 NavTopMenuElement.tag, |
50 NavVMMenuElement.tag, | 37 NavVMMenuElement.tag, |
51 NavIsolateMenuElement.tag, | 38 NavIsolateMenuElement.tag, |
52 NavRefreshElement.tag, | 39 NavRefreshElement.tag, |
53 NavNotifyElement.tag, | 40 NavNotifyElement.tag, |
54 SampleBufferControlElement.tag, | 41 SampleBufferControlElement.tag, |
55 StackTraceTreeConfigElement.tag, | 42 StackTraceTreeConfigElement.tag, |
56 CpuProfileVirtualTreeElement.tag, | 43 CpuProfileVirtualTreeElement.tag, |
57 VirtualCollectionElement.tag | 44 VirtualCollectionElement.tag |
58 ]); | 45 ]); |
59 | 46 |
60 RenderingScheduler<CpuProfileTableElement> _r; | 47 RenderingScheduler<CpuProfileTableElement> _r; |
61 | 48 |
62 Stream<RenderedEvent<CpuProfileTableElement>> get onRendered => _r.onRendered; | 49 Stream<RenderedEvent<CpuProfileTableElement>> get onRendered => _r.onRendered; |
63 | 50 |
64 M.VM _vm; | 51 M.VM _vm; |
65 M.IsolateRef _isolate; | 52 M.IsolateRef _isolate; |
66 M.EventRepository _events; | 53 M.EventRepository _events; |
67 M.NotificationRepository _notifications; | 54 M.NotificationRepository _notifications; |
68 M.IsolateSampleProfileRepository _profiles; | 55 M.IsolateSampleProfileRepository _profiles; |
69 Stream<M.SampleProfileLoadingProgressEvent> _progressStream; | 56 Stream<M.SampleProfileLoadingProgressEvent> _progressStream; |
70 M.SampleProfileLoadingProgress _progress; | 57 M.SampleProfileLoadingProgress _progress; |
71 final _sortingField = <_Table, _SortingField>{ | 58 final _sortingField = <_Table, _SortingField>{ |
72 _Table.functions : _SortingField.exclusive, | 59 _Table.functions: _SortingField.exclusive, |
73 _Table.caller : _SortingField.caller, | 60 _Table.caller: _SortingField.caller, |
74 _Table.callee : _SortingField.callee, | 61 _Table.callee: _SortingField.callee, |
75 }; | 62 }; |
76 final _sortingDirection = <_Table, _SortingDirection>{ | 63 final _sortingDirection = <_Table, _SortingDirection>{ |
77 _Table.functions : _SortingDirection.descending, | 64 _Table.functions: _SortingDirection.descending, |
78 _Table.caller : _SortingDirection.descending, | 65 _Table.caller: _SortingDirection.descending, |
79 _Table.callee : _SortingDirection.descending, | 66 _Table.callee: _SortingDirection.descending, |
80 }; | 67 }; |
81 String _filter = ''; | 68 String _filter = ''; |
82 | 69 |
83 | |
84 M.IsolateRef get isolate => _isolate; | 70 M.IsolateRef get isolate => _isolate; |
85 M.NotificationRepository get notifications => _notifications; | 71 M.NotificationRepository get notifications => _notifications; |
86 M.IsolateSampleProfileRepository get profiles => _profiles; | 72 M.IsolateSampleProfileRepository get profiles => _profiles; |
87 M.VMRef get vm => _vm; | 73 M.VMRef get vm => _vm; |
88 | 74 |
89 factory CpuProfileTableElement(M.VM vm, M.IsolateRef isolate, | 75 factory CpuProfileTableElement( |
90 M.EventRepository events, | 76 M.VM vm, |
91 M.NotificationRepository notifications, | 77 M.IsolateRef isolate, |
92 M.IsolateSampleProfileRepository profiles, | 78 M.EventRepository events, |
93 {RenderingQueue queue}) { | 79 M.NotificationRepository notifications, |
| 80 M.IsolateSampleProfileRepository profiles, |
| 81 {RenderingQueue queue}) { |
94 assert(vm != null); | 82 assert(vm != null); |
95 assert(isolate != null); | 83 assert(isolate != null); |
96 assert(events != null); | 84 assert(events != null); |
97 assert(notifications != null); | 85 assert(notifications != null); |
98 assert(profiles != null); | 86 assert(profiles != null); |
99 CpuProfileTableElement e = document.createElement(tag.name); | 87 CpuProfileTableElement e = document.createElement(tag.name); |
100 e._r = new RenderingScheduler(e, queue: queue); | 88 e._r = new RenderingScheduler(e, queue: queue); |
101 e._vm = vm; | 89 e._vm = vm; |
102 e._isolate = isolate; | 90 e._isolate = isolate; |
103 e._events = events; | 91 e._events = events; |
(...skipping 18 matching lines...) Expand all Loading... |
122 children = []; | 110 children = []; |
123 } | 111 } |
124 | 112 |
125 void render() { | 113 void render() { |
126 var content = [ | 114 var content = [ |
127 navBar([ | 115 navBar([ |
128 new NavTopMenuElement(queue: _r.queue), | 116 new NavTopMenuElement(queue: _r.queue), |
129 new NavVMMenuElement(_vm, _events, queue: _r.queue), | 117 new NavVMMenuElement(_vm, _events, queue: _r.queue), |
130 new NavIsolateMenuElement(_isolate, _events, queue: _r.queue), | 118 new NavIsolateMenuElement(_isolate, _events, queue: _r.queue), |
131 navMenu('cpu profile (table)'), | 119 navMenu('cpu profile (table)'), |
132 new NavRefreshElement(queue: _r.queue) | 120 new NavRefreshElement(queue: _r.queue)..onRefresh.listen(_refresh), |
133 ..onRefresh.listen(_refresh), | |
134 new NavRefreshElement(label: 'Clear', queue: _r.queue) | 121 new NavRefreshElement(label: 'Clear', queue: _r.queue) |
135 ..onRefresh.listen(_clearCpuProfile), | 122 ..onRefresh.listen(_clearCpuProfile), |
136 new NavNotifyElement(_notifications, queue: _r.queue) | 123 new NavNotifyElement(_notifications, queue: _r.queue) |
137 ]), | 124 ]), |
138 ]; | 125 ]; |
139 if (_progress == null) { | 126 if (_progress == null) { |
140 children = content; | 127 children = content; |
141 return; | 128 return; |
142 } | 129 } |
143 content.add(new SampleBufferControlElement(_progress, _progressStream, | 130 content.add(new SampleBufferControlElement(_progress, _progressStream, |
144 showTag: false, queue: _r.queue)); | 131 showTag: false, queue: _r.queue)); |
145 if (_progress.status == M.SampleProfileLoadingStatus.loaded) { | 132 if (_progress.status == M.SampleProfileLoadingStatus.loaded) { |
146 content.add(new BRElement()); | 133 content.add(new BRElement()); |
147 content.addAll(_createTables()); | 134 content.addAll(_createTables()); |
148 content.add(new BRElement()); | 135 content.add(new BRElement()); |
149 content.addAll(_createTree()); | 136 content.addAll(_createTree()); |
150 } | 137 } |
151 children = content; | 138 children = content; |
152 } | 139 } |
153 | 140 |
154 M.ProfileFunction _selected; | 141 M.ProfileFunction _selected; |
155 VirtualCollectionElement _functions; | 142 VirtualCollectionElement _functions; |
156 VirtualCollectionElement _callers; | 143 VirtualCollectionElement _callers; |
157 VirtualCollectionElement _callees; | 144 VirtualCollectionElement _callees; |
158 | 145 |
159 List<Element> _createTables() { | 146 List<Element> _createTables() { |
160 _functions = _functions ?? new VirtualCollectionElement( | 147 _functions = _functions ?? |
161 _createFunction, | 148 new VirtualCollectionElement(_createFunction, _updateFunction, |
162 _updateFunction, | 149 createHeader: _createFunctionHeader, queue: _r.queue); |
163 createHeader: _createFunctionHeader, | |
164 queue: _r.queue | |
165 ); | |
166 _functions.items = _progress.profile.functions.toList() | 150 _functions.items = _progress.profile.functions.toList() |
167 ..sort(_createSorter(_Table.functions)); | 151 ..sort(_createSorter(_Table.functions)); |
168 _functions.takeIntoView(_selected); | 152 _functions.takeIntoView(_selected); |
169 _callers = _callers ?? new VirtualCollectionElement( | 153 _callers = _callers ?? |
170 _createCaller, | 154 new VirtualCollectionElement(_createCaller, _updateCaller, |
171 _updateCaller, | 155 createHeader: _createCallerHeader, queue: _r.queue); |
172 createHeader: _createCallerHeader, | 156 _callees = _callees ?? |
173 queue: _r.queue | 157 new VirtualCollectionElement(_createCallee, _updateCallee, |
174 ); | 158 createHeader: _createCalleeHeader, queue: _r.queue); |
175 _callees = _callees ?? new VirtualCollectionElement( | |
176 _createCallee, | |
177 _updateCallee, | |
178 createHeader: _createCalleeHeader, | |
179 queue: _r.queue | |
180 ); | |
181 if (_selected != null) { | 159 if (_selected != null) { |
182 _callers.items = _selected.callers.keys.toList() | 160 _callers.items = _selected.callers.keys.toList() |
183 ..sort(_createSorter(_Table.caller)); | 161 ..sort(_createSorter(_Table.caller)); |
184 _callees.items = _selected.callees.keys.toList() | 162 _callees.items = _selected.callees.keys.toList() |
185 ..sort(_createSorter(_Table.callee)); | 163 ..sort(_createSorter(_Table.callee)); |
186 } else { | 164 } else { |
187 _callers.items = const []; | 165 _callers.items = const []; |
188 _callees.items = const []; | 166 _callees.items = const []; |
189 } | 167 } |
190 return [ | 168 return [ |
191 new DivElement()..classes = ['profile-trees'] | 169 new DivElement() |
| 170 ..classes = ['profile-trees'] |
192 ..children = [ | 171 ..children = [ |
193 new DivElement()..classes = ['profile-trees-all'] | 172 new DivElement() |
| 173 ..classes = ['profile-trees-all'] |
194 ..children = [_functions], | 174 ..children = [_functions], |
195 new DivElement()..classes = ['profile-trees-current'] | 175 new DivElement() |
| 176 ..classes = ['profile-trees-current'] |
196 ..children = [ | 177 ..children = [ |
197 new DivElement()..classes = ['profile-trees-caller'] | 178 new DivElement() |
| 179 ..classes = ['profile-trees-caller'] |
198 ..children = [_callers], | 180 ..children = [_callers], |
199 new DivElement()..classes = ['profile-trees-selected'] | 181 new DivElement() |
| 182 ..classes = ['profile-trees-selected'] |
200 ..children = _selected == null | 183 ..children = _selected == null |
201 ? [new SpanElement()..text = 'No element selected'] | 184 ? [new SpanElement()..text = 'No element selected'] |
202 : [new FunctionRefElement(_isolate, _selected.function, | 185 : [ |
203 queue : _r.queue)], | 186 new FunctionRefElement(_isolate, _selected.function, |
204 new DivElement()..classes = ['profile-trees-callee'] | 187 queue: _r.queue) |
| 188 ], |
| 189 new DivElement() |
| 190 ..classes = ['profile-trees-callee'] |
205 ..children = [_callees] | 191 ..children = [_callees] |
206 ] | 192 ] |
207 ] | 193 ] |
208 ]; | 194 ]; |
209 } | 195 } |
210 | 196 |
211 Element _createFunction() { | 197 Element _createFunction() { |
212 final element = new DivElement() | 198 final element = new DivElement() |
213 ..classes = ['function-item'] | 199 ..classes = ['function-item'] |
214 ..children = [ | 200 ..children = [ |
215 new SpanElement()..classes = ['exclusive'] | 201 new SpanElement() |
| 202 ..classes = ['exclusive'] |
216 ..text = '0%', | 203 ..text = '0%', |
217 new SpanElement()..classes = ['inclusive'] | 204 new SpanElement() |
| 205 ..classes = ['inclusive'] |
218 ..text = '0%', | 206 ..text = '0%', |
219 new SpanElement()..classes = ['name'] | 207 new SpanElement()..classes = ['name'] |
220 ]; | 208 ]; |
221 element.onClick.listen((e) { | 209 element.onClick.listen((e) { |
222 if (e.target is AnchorElement) { | 210 if (e.target is AnchorElement) { |
223 return; | 211 return; |
224 } | 212 } |
225 _selected = _functions.getItemFromElement(element); | 213 _selected = _functions.getItemFromElement(element); |
226 _r.dirty(); | 214 _r.dirty(); |
227 }); | 215 }); |
228 return element; | 216 return element; |
229 } | 217 } |
230 | 218 |
231 void _updateFunction(Element e, M.ProfileFunction item, int index) { | 219 void _updateFunction(Element e, M.ProfileFunction item, int index) { |
232 if (item == _selected) { | 220 if (item == _selected) { |
233 e.classes = ['function-item', 'selected']; | 221 e.classes = ['function-item', 'selected']; |
234 } else { | 222 } else { |
235 e.classes = ['function-item']; | 223 e.classes = ['function-item']; |
236 } | 224 } |
237 e.children[0].text = Utils.formatPercentNormalized(_getExclusiveT(item)); | 225 e.children[0].text = Utils.formatPercentNormalized(_getExclusiveT(item)); |
238 e.children[1].text = Utils.formatPercentNormalized(_getInclusiveT(item)); | 226 e.children[1].text = Utils.formatPercentNormalized(_getInclusiveT(item)); |
239 e.children[2] = new FunctionRefElement(_isolate, item.function, | 227 e.children[2] = new FunctionRefElement(_isolate, item.function, |
240 queue: _r.queue)..classes = ['name']; | 228 queue: _r.queue)..classes = ['name']; |
241 } | 229 } |
242 | 230 |
243 Element _createFunctionHeader() => | 231 Element _createFunctionHeader() => new DivElement() |
244 new DivElement() | 232 ..classes = ['function-item'] |
245 ..classes = ['function-item'] | 233 ..children = [ |
246 ..children = [ | 234 _createHeaderButton(const ['exclusive'], 'Execution(%)', _Table.functions, |
247 _createHeaderButton(const ['exclusive'], 'Execution(%)', | 235 _SortingField.exclusive, _SortingDirection.descending), |
248 _Table.functions, | 236 _createHeaderButton(const ['inclusive'], 'Stack(%)', _Table.functions, |
249 _SortingField.exclusive, | 237 _SortingField.inclusive, _SortingDirection.descending), |
250 _SortingDirection.descending), | 238 _createHeaderButton(const ['name'], 'Method', _Table.functions, |
251 _createHeaderButton(const ['inclusive'], 'Stack(%)', | 239 _SortingField.method, _SortingDirection.ascending), |
252 _Table.functions, | 240 ]; |
253 _SortingField.inclusive, | |
254 _SortingDirection.descending), | |
255 _createHeaderButton(const ['name'], 'Method', | |
256 _Table.functions, | |
257 _SortingField.method, | |
258 _SortingDirection.ascending), | |
259 ]; | |
260 | 241 |
261 void _setSorting(_Table table, | 242 void _setSorting( |
262 _SortingField field, | 243 _Table table, _SortingField field, _SortingDirection defaultDirection) { |
263 _SortingDirection defaultDirection) { | 244 if (_sortingField[table] == field) { |
264 if (_sortingField[table] == field) { | 245 switch (_sortingDirection[table]) { |
265 switch (_sortingDirection[table]) { | 246 case _SortingDirection.descending: |
266 case _SortingDirection.descending: | 247 _sortingDirection[table] = _SortingDirection.ascending; |
267 _sortingDirection[table] = _SortingDirection.ascending; | 248 break; |
268 break; | 249 case _SortingDirection.ascending: |
269 case _SortingDirection.ascending: | 250 _sortingDirection[table] = _SortingDirection.descending; |
270 _sortingDirection[table] = _SortingDirection.descending; | 251 break; |
271 break; | |
272 } | |
273 } else { | |
274 _sortingDirection[table] = defaultDirection; | |
275 _sortingField[table] = field; | |
276 } | 252 } |
277 _r.dirty(); | 253 } else { |
| 254 _sortingDirection[table] = defaultDirection; |
| 255 _sortingField[table] = field; |
278 } | 256 } |
| 257 _r.dirty(); |
| 258 } |
279 | 259 |
280 Element _createCallee() { | 260 Element _createCallee() { |
281 final element = new DivElement() | 261 final element = new DivElement() |
282 ..classes = ['function-item'] | 262 ..classes = ['function-item'] |
283 ..children = [ | 263 ..children = [ |
284 new SpanElement()..classes = ['inclusive'] | 264 new SpanElement() |
| 265 ..classes = ['inclusive'] |
285 ..text = '0%', | 266 ..text = '0%', |
286 new SpanElement()..classes = ['name'] | 267 new SpanElement()..classes = ['name'] |
287 ]; | 268 ]; |
288 element.onClick.listen((e) { | 269 element.onClick.listen((e) { |
289 if (e.target is AnchorElement) { | 270 if (e.target is AnchorElement) { |
290 return; | 271 return; |
291 } | 272 } |
292 _selected = _callees.getItemFromElement(element); | 273 _selected = _callees.getItemFromElement(element); |
293 _r.dirty(); | 274 _r.dirty(); |
294 }); | 275 }); |
295 return element; | 276 return element; |
296 } | 277 } |
297 | 278 |
298 void _updateCallee(Element e, item, int index) { | 279 void _updateCallee(Element e, item, int index) { |
299 e.children[0].text = Utils.formatPercentNormalized(_getCalleeT(item)); | 280 e.children[0].text = Utils.formatPercentNormalized(_getCalleeT(item)); |
300 e.children[1] = new FunctionRefElement(_isolate, item.function, | 281 e.children[1] = new FunctionRefElement(_isolate, item.function, |
301 queue: _r.queue)..classes = ['name']; | 282 queue: _r.queue)..classes = ['name']; |
302 } | 283 } |
303 | 284 |
304 Element _createCalleeHeader() => | 285 Element _createCalleeHeader() => new DivElement() |
305 new DivElement() | 286 ..classes = ['function-item'] |
306 ..classes = ['function-item'] | 287 ..children = [ |
307 ..children = [ | 288 _createHeaderButton(const ['inclusive'], 'Callees(%)', _Table.callee, |
308 _createHeaderButton(const ['inclusive'], 'Callees(%)', | 289 _SortingField.callee, _SortingDirection.descending), |
309 _Table.callee, | 290 _createHeaderButton(const ['name'], 'Method', _Table.callee, |
310 _SortingField.callee, | 291 _SortingField.method, _SortingDirection.ascending), |
311 _SortingDirection.descending), | 292 ]; |
312 _createHeaderButton(const ['name'], 'Method', | |
313 _Table.callee, | |
314 _SortingField.method, | |
315 _SortingDirection.ascending), | |
316 ]; | |
317 | 293 |
318 Element _createCaller() { | 294 Element _createCaller() { |
319 final element = new DivElement() | 295 final element = new DivElement() |
320 ..classes = ['function-item'] | 296 ..classes = ['function-item'] |
321 ..children = [ | 297 ..children = [ |
322 new SpanElement()..classes = ['inclusive'] | 298 new SpanElement() |
| 299 ..classes = ['inclusive'] |
323 ..text = '0%', | 300 ..text = '0%', |
324 new SpanElement()..classes = ['name'] | 301 new SpanElement()..classes = ['name'] |
325 ]; | 302 ]; |
326 element.onClick.listen((e) { | 303 element.onClick.listen((e) { |
327 if (e.target is AnchorElement) { | 304 if (e.target is AnchorElement) { |
328 return; | 305 return; |
329 } | 306 } |
330 _selected = _callers.getItemFromElement(element); | 307 _selected = _callers.getItemFromElement(element); |
331 _r.dirty(); | 308 _r.dirty(); |
332 }); | 309 }); |
333 return element; | 310 return element; |
334 } | 311 } |
335 | 312 |
336 void _updateCaller(Element e, item, int index) { | 313 void _updateCaller(Element e, item, int index) { |
337 e.children[0].text = Utils.formatPercentNormalized(_getCallerT(item)); | 314 e.children[0].text = Utils.formatPercentNormalized(_getCallerT(item)); |
338 e.children[1] = new FunctionRefElement(_isolate, item.function, | 315 e.children[1] = new FunctionRefElement(_isolate, item.function, |
339 queue: _r.queue)..classes = ['name']; | 316 queue: _r.queue)..classes = ['name']; |
340 } | 317 } |
341 | 318 |
342 Element _createCallerHeader() => | 319 Element _createCallerHeader() => new DivElement() |
343 new DivElement() | 320 ..classes = ['function-item'] |
344 ..classes = ['function-item'] | 321 ..children = [ |
345 ..children = [ | 322 _createHeaderButton(const ['inclusive'], 'Callers(%)', _Table.caller, |
346 _createHeaderButton(const ['inclusive'], 'Callers(%)', | 323 _SortingField.caller, _SortingDirection.descending), |
347 _Table.caller, | 324 _createHeaderButton(const ['name'], 'Method', _Table.caller, |
348 _SortingField.caller, | 325 _SortingField.method, _SortingDirection.ascending), |
349 _SortingDirection.descending), | 326 ]; |
350 _createHeaderButton(const ['name'], 'Method', | |
351 _Table.caller, | |
352 _SortingField.method, | |
353 _SortingDirection.ascending), | |
354 ]; | |
355 | 327 |
356 ButtonElement _createHeaderButton(List<String> classes, | 328 ButtonElement _createHeaderButton(List<String> classes, String text, |
357 String text, | 329 _Table table, _SortingField field, _SortingDirection direction) => |
358 _Table table, | 330 new ButtonElement() |
359 _SortingField field, | 331 ..classes = classes |
360 _SortingDirection direction) => | 332 ..text = _sortingField[table] != field |
361 new ButtonElement()..classes = classes | 333 ? text |
362 ..text = _sortingField[table] != field ? text : | 334 : _sortingDirection[table] == _SortingDirection.ascending |
363 _sortingDirection[table] == _SortingDirection.ascending | 335 ? '$text▼' |
364 ? '$text▼' : '$text▲' | 336 : '$text▲' |
365 ..onClick.listen((_) => _setSorting(table, field, direction)); | 337 ..onClick.listen((_) => _setSorting(table, field, direction)); |
366 | 338 |
367 List<Element> _createTree() { | 339 List<Element> _createTree() { |
368 CpuProfileVirtualTreeElement tree; | 340 CpuProfileVirtualTreeElement tree; |
369 return [ | 341 return [ |
370 new StackTraceTreeConfigElement(showMode: false, | 342 new StackTraceTreeConfigElement( |
371 showDirection: false, mode: ProfileTreeMode.function, | 343 showMode: false, |
372 direction: M.ProfileTreeDirection.exclusive, filter: _filter, | 344 showDirection: false, |
373 queue: _r.queue) | 345 mode: ProfileTreeMode.function, |
| 346 direction: M.ProfileTreeDirection.exclusive, |
| 347 filter: _filter, |
| 348 queue: _r.queue) |
374 ..onFilterChange.listen((e) { | 349 ..onFilterChange.listen((e) { |
375 _filter = e.element.filter.trim(); | 350 _filter = e.element.filter.trim(); |
376 tree.filters = _filter.isNotEmpty | 351 tree.filters = _filter.isNotEmpty |
377 ? [_filterTree, (node) { return node.name.contains(_filter); }] | 352 ? [ |
378 : [_filterTree]; | 353 _filterTree, |
| 354 (node) { |
| 355 return node.name.contains(_filter); |
| 356 } |
| 357 ] |
| 358 : [_filterTree]; |
379 }), | 359 }), |
380 new BRElement(), | 360 new BRElement(), |
381 tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile, | 361 tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile, |
382 mode: ProfileTreeMode.function, | 362 mode: ProfileTreeMode.function, |
383 direction: M.ProfileTreeDirection.exclusive, | 363 direction: M.ProfileTreeDirection.exclusive, |
384 queue: _r.queue) | 364 queue: _r.queue) |
385 ..filters = _filter.isNotEmpty | 365 ..filters = _filter.isNotEmpty |
386 ? [_filterTree, (node) { return node.name.contains(_filter); }] | 366 ? [ |
| 367 _filterTree, |
| 368 (node) { |
| 369 return node.name.contains(_filter); |
| 370 } |
| 371 ] |
387 : [_filterTree] | 372 : [_filterTree] |
388 ]; | 373 ]; |
389 } | 374 } |
390 | 375 |
391 bool _filterTree(M.FunctionCallTreeNode node) => | 376 bool _filterTree(M.FunctionCallTreeNode node) => |
392 node.profileFunction == _selected; | 377 node.profileFunction == _selected; |
393 | 378 |
394 Future _request({bool clear: false, bool forceFetch: false}) async { | 379 Future _request({bool clear: false, bool forceFetch: false}) async { |
395 _progress = null; | 380 _progress = null; |
396 _progressStream = _profiles.get(isolate, M.SampleProfileTag.none, | 381 _progressStream = _profiles.get(isolate, M.SampleProfileTag.none, |
(...skipping 28 matching lines...) Expand all Loading... |
425 case _SortingField.inclusive: | 410 case _SortingField.inclusive: |
426 getter = _getInclusiveT; | 411 getter = _getInclusiveT; |
427 break; | 412 break; |
428 case _SortingField.callee: | 413 case _SortingField.callee: |
429 getter = _getCalleeT; | 414 getter = _getCalleeT; |
430 break; | 415 break; |
431 case _SortingField.caller: | 416 case _SortingField.caller: |
432 getter = _getCallerT; | 417 getter = _getCallerT; |
433 break; | 418 break; |
434 case _SortingField.method: | 419 case _SortingField.method: |
435 getter = (M.ProfileFunction s) => | 420 getter = (M.ProfileFunction s) => M.getFunctionFullName(s.function); |
436 M.getFunctionFullName(s.function); | |
437 break; | 421 break; |
438 } | 422 } |
439 switch (_sortingDirection[table]) { | 423 switch (_sortingDirection[table]) { |
440 case _SortingDirection.ascending: | 424 case _SortingDirection.ascending: |
441 return (a, b) => getter(a).compareTo(getter(b)); | 425 return (a, b) => getter(a).compareTo(getter(b)); |
442 case _SortingDirection.descending: | 426 case _SortingDirection.descending: |
443 return (a, b) => getter(b).compareTo(getter(a)); | 427 return (a, b) => getter(b).compareTo(getter(a)); |
444 } | 428 } |
445 } | 429 } |
446 | 430 |
447 static double _getExclusiveT(M.ProfileFunction f) => | 431 static double _getExclusiveT(M.ProfileFunction f) => |
448 f.normalizedExclusiveTicks; | 432 f.normalizedExclusiveTicks; |
449 static double _getInclusiveT(M.ProfileFunction f) => | 433 static double _getInclusiveT(M.ProfileFunction f) => |
450 f.normalizedInclusiveTicks; | 434 f.normalizedInclusiveTicks; |
451 double _getCalleeT(M.ProfileFunction f) => | 435 double _getCalleeT(M.ProfileFunction f) => |
452 _selected.callees[f] / _selected.callees.values.reduce((a, b) => a + b); | 436 _selected.callees[f] / _selected.callees.values.reduce((a, b) => a + b); |
453 double _getCallerT(M.ProfileFunction f) => | 437 double _getCallerT(M.ProfileFunction f) => |
454 _selected.callers[f] / _selected.callers.values.reduce((a, b) => a + b); | 438 _selected.callers[f] / _selected.callers.values.reduce((a, b) => a + b); |
455 } | 439 } |
OLD | NEW |