Chromium Code Reviews| Index: runtime/observatory/lib/src/elements/cpu_profile_table.dart |
| diff --git a/runtime/observatory/lib/src/elements/cpu_profile.dart b/runtime/observatory/lib/src/elements/cpu_profile_table.dart |
| similarity index 55% |
| copy from runtime/observatory/lib/src/elements/cpu_profile.dart |
| copy to runtime/observatory/lib/src/elements/cpu_profile_table.dart |
| index 82f479d00e370e27122b69741a7412bd50061b6b..d9663db64e658ca47d14c8bc69eb4477c338cf83 100644 |
| --- a/runtime/observatory/lib/src/elements/cpu_profile.dart |
| +++ b/runtime/observatory/lib/src/elements/cpu_profile_table.dart |
| @@ -2,16 +2,20 @@ |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| -library cpu_profile_element; |
| +library cpu_profile_table_element; |
| import 'dart:async'; |
| import 'dart:html'; |
| import 'observatory_element.dart'; |
| -import 'package:observatory/models.dart' as M; |
| +import 'sample_buffer_control.dart'; |
| +import 'stack_trace_tree_config.dart'; |
| +import 'cpu_profile/virtual_tree.dart'; |
| import 'package:observatory/service.dart'; |
| import 'package:observatory/app.dart'; |
| import 'package:observatory/cpu_profile.dart'; |
| import 'package:observatory/elements.dart'; |
| +import 'package:observatory/models.dart' as M; |
| +import 'package:observatory/repositories.dart'; |
| import 'package:polymer/polymer.dart'; |
| List<String> sorted(Set<String> attributes) { |
| @@ -435,467 +439,6 @@ class FunctionProfileTreeRow extends ProfileTreeRow<FunctionCallTreeNode> { |
| } |
| } |
| -@CustomTag('sample-buffer-control') |
| -class SampleBufferControlElement extends ObservatoryElement { |
| - SampleBufferControlElement.created() : super.created() { |
| - _stopWatch.start(); |
| - } |
| - |
| - Future<CpuProfile> reload(Isolate isolate) async { |
| - profile.clear(); |
| - if (isolate == null) { |
| - _update(profile); |
| - // Notify listener. |
| - onSampleBufferUpdate(profile); |
| - return profile; |
| - } |
| - profileVM = isolate.vm.profileVM; |
| - if (tagSelector == null) { |
| - // Set default value. |
| - tagSelector = profileVM ? 'UserVM' : 'None'; |
| - } |
| - await _changeState(kFetchingState); |
| - try { |
| - var response; |
| - if (allocationProfileClass != null) { |
| - response = |
| - await allocationProfileClass.getAllocationSamples(tagSelector); |
| - } else { |
| - var params = { 'tags': tagSelector }; |
| - response = await isolate.invokeRpc('_getCpuProfile', params); |
| - } |
| - await _changeState(kLoadingState); |
| - profile.load(isolate, response); |
| - profile.buildFunctionCallerAndCallees(); |
| - _update(profile); |
| - await _changeState(kLoadedState); |
| - // Notify listener. |
| - onSampleBufferUpdate(profile); |
| - return profile; |
| - } catch (e, st) { |
| - if (e is ServerRpcException) { |
| - ServerRpcException se = e; |
| - if (se.code == ServerRpcException.kFeatureDisabled) { |
| - await _changeState(kDisabledState); |
| - return profile; |
| - } |
| - } |
| - await _changeState(kExceptionState, e, st); |
| - rethrow; |
| - } |
| - } |
| - |
| - Future _changeState(String newState, [exception, stackTrace]) { |
| - if ((newState == kDisabledState) || |
| - (newState == kFetchingState) || |
| - (newState == kExceptionState)) { |
| - loadTime = ''; |
| - fetchTime = ''; |
| - } else if (newState == kLoadingState) { |
| - fetchTime = formatTimeMilliseconds(_stopWatch.elapsedMilliseconds); |
| - loadTime = ''; |
| - } else if (newState == kLoadedState) { |
| - loadTime = formatTimeMilliseconds(_stopWatch.elapsedMilliseconds); |
| - } |
| - state = newState; |
| - this.exception = exception; |
| - this.stackTrace = stackTrace; |
| - _stopWatch.reset(); |
| - return window.animationFrame; |
| - } |
| - |
| - _update(CpuProfile sampleBuffer) { |
| - sampleCount = profile.sampleCount.toString(); |
| - refreshTime = new DateTime.now().toString(); |
| - stackDepth = profile.stackDepth.toString(); |
| - sampleRate = profile.sampleRate.toStringAsFixed(0); |
| - if (profile.sampleCount == 0) { |
| - timeSpan = '0s'; |
| - } else { |
| - timeSpan = formatTime(profile.timeSpan); |
| - } |
| - } |
| - |
| - void tagSelectorChanged(oldValue) { |
| - reload(profile.isolate); |
| - } |
| - |
| - Function onSampleBufferUpdate; |
| - @observable bool showTagSelector = true; |
| - @observable bool profileVM = false; |
| - @observable String sampleCount = ''; |
| - @observable String refreshTime = ''; |
| - @observable String sampleRate = ''; |
| - @observable String stackDepth = ''; |
| - @observable String timeSpan = ''; |
| - @observable String fetchTime = ''; |
| - @observable String loadTime = ''; |
| - @observable String tagSelector; |
| - @observable String state = kFetchingState; |
| - @observable var exception; |
| - @observable var stackTrace; |
| - |
| - static const kDisabledState = 'kDisabled'; |
| - static const kExceptionState = 'Exception'; |
| - static const kFetchingState = 'kFetching'; |
| - static const kLoadedState = 'kLoaded'; |
| - static const kLoadingState = 'kLoading'; |
| - static const kNotLoadedState = 'kNotLoaded'; |
| - |
| - Isolate isolate; |
| - Class allocationProfileClass; |
| - |
| - final CpuProfile profile = new CpuProfile(); |
| - final Stopwatch _stopWatch = new Stopwatch(); |
| -} |
| - |
| -@CustomTag('stack-trace-tree-config') |
| -class StackTraceTreeConfigElement extends ObservatoryElement { |
| - StackTraceTreeConfigElement.created() : super.created(); |
| - |
| - attached() { |
| - super.attached(); |
| - var filterElement = shadowRoot.querySelector('#filterInput'); |
| - keyDownSubscription = filterElement.onKeyDown.listen(_onKeyDown); |
| - blurSubscription = filterElement.onBlur.listen(_onBlur); |
| - } |
| - |
| - detached() { |
| - super.detached(); |
| - keyDownSubscription?.cancel(); |
| - blurSubscription?.cancel(); |
| - } |
| - |
| - void _onKeyDown(KeyboardEvent keyEvent) { |
| - if (keyEvent.keyCode == 13) { |
| - // On enter, update the filter string. |
| - filterString = |
| - (shadowRoot.querySelector('#filterInput') as InputElement).value; |
| - if (onTreeConfigChange == null) { |
| - return; |
| - } |
| - onTreeConfigChange(modeSelector, directionSelector, filterString); |
| - } |
| - } |
| - |
| - void _onBlur(Event event) { |
| - // Input box has lost focus, update the display to match the active |
| - // filter string. |
| - (shadowRoot.querySelector('#filterInput') as InputElement).value = |
| - filterString; |
| - } |
| - |
| - void modeSelectorChanged(oldValue) { |
| - if (onTreeConfigChange == null) { |
| - return; |
| - } |
| - onTreeConfigChange(modeSelector, directionSelector, filterString); |
| - } |
| - |
| - void directionSelectorChanged(oldValue) { |
| - if (onTreeConfigChange == null) { |
| - return; |
| - } |
| - onTreeConfigChange(modeSelector, directionSelector, filterString); |
| - } |
| - |
| - Function onTreeConfigChange; |
| - StreamSubscription keyDownSubscription; |
| - StreamSubscription blurSubscription; |
| - @observable bool show = true; |
| - @observable bool showModeSelector = true; |
| - @observable bool showDirectionSelector = true; |
| - @observable bool showFilter = true; |
| - @observable String modeSelector = 'Function'; |
| - @observable String directionSelector = 'Up'; |
| - @observable String filterString; |
| -} |
| - |
| -class FunctionCallTreeNodeRow extends VirtualTreeRow { |
| - final CpuProfile profile; |
| - final FunctionCallTreeNode node; |
| - String selfPercent; |
| - String totalPercent; |
| - String percent; |
| - |
| - static const kHotThreshold = 0.05; // 5%. |
| - static const kMediumThreshold = 0.02; // 2%. |
| - |
| - double _percent(bool self) { |
| - if (self) { |
| - return node.profileFunction.normalizedExclusiveTicks; |
| - } else { |
| - return node.profileFunction.normalizedInclusiveTicks; |
| - } |
| - } |
| - |
| - bool isHot(bool self) => _percent(self) > kHotThreshold; |
| - bool isMedium(bool self) => _percent(self) > kMediumThreshold; |
| - |
| - String rowClass(bool self) { |
| - if (isHot(self)) { |
| - return 'hotProfile'; |
| - } else if (isMedium(self)) { |
| - return 'mediumProfile'; |
| - } else { |
| - return 'coldProfile'; |
| - } |
| - } |
| - |
| - FunctionCallTreeNodeRow(VirtualTree tree, |
| - int depth, |
| - this.profile, |
| - FunctionCallTreeNode node) |
| - : node = node, |
| - super(tree, depth) { |
| - if ((node.profileFunction.function.kind == M.FunctionKind.tag) && |
| - (node.profileFunction.normalizedExclusiveTicks == 0) && |
| - (node.profileFunction.normalizedInclusiveTicks == 0)) { |
| - selfPercent = ''; |
| - totalPercent = ''; |
| - } else { |
| - selfPercent = Utils.formatPercentNormalized( |
| - node.profileFunction.normalizedExclusiveTicks); |
| - totalPercent = Utils.formatPercentNormalized( |
| - node.profileFunction.normalizedInclusiveTicks); |
| - } |
| - percent = Utils.formatPercentNormalized(node.percentage); |
| - } |
| - |
| - void onRender(DivElement rowDiv) { |
| - rowDiv.children.add(makeGap(ems:0.1)); |
| - rowDiv.children.add( |
| - makeText(totalPercent, |
| - toolTip: 'global % on stack')); |
| - rowDiv.children.add(makeGap()); |
| - rowDiv.children.add( |
| - makeText(selfPercent, |
| - toolTip: 'global % executing')); |
| - rowDiv.children.add(makeGap()); |
| - rowDiv.children.add(makeIndenter(depth, colored: false)); |
| - rowDiv.children.add(makeColorBar(depth)); |
| - rowDiv.children.add(makeGap(ems: 1.0)); |
| - rowDiv.children.add(makeExpander()); |
| - rowDiv.children.add( |
| - makeText(percent, toolTip: 'tree node %', flexBasis: null)); |
| - rowDiv.children.add(makeGap(ems: 0.5)); |
| - functionRef.ref = node.profileFunction.function; |
| - rowDiv.children.add(functionRef); |
| - } |
| - |
| - var functionRef = new Element.tag('function-ref'); |
| - |
| - int get childCount => node.children.length; |
| - |
| - void onShow() { |
| - if (children.length > 0) { |
| - return; |
| - } |
| - for (var childNode in node.children) { |
| - var row = new FunctionCallTreeNodeRow(tree, depth + 1, profile, childNode); |
| - children.add(row); |
| - } |
| - } |
| -} |
| - |
| - |
| -class CodeCallTreeNodeRow extends VirtualTreeRow { |
| - final CpuProfile profile; |
| - final CodeCallTreeNode node; |
| - String selfPercent; |
| - String totalPercent; |
| - String percent; |
| - |
| - static const kHotThreshold = 0.05; // 5%. |
| - static const kMediumThreshold = 0.02; // 2%. |
| - |
| - double _percent(bool self) { |
| - if (self) { |
| - return node.profileCode.normalizedExclusiveTicks; |
| - } else { |
| - return node.profileCode.normalizedInclusiveTicks; |
| - } |
| - } |
| - |
| - bool isHot(bool self) => _percent(self) > kHotThreshold; |
| - bool isMedium(bool self) => _percent(self) > kMediumThreshold; |
| - |
| - String rowClass(bool self) { |
| - if (isHot(self)) { |
| - return 'hotProfile'; |
| - } else if (isMedium(self)) { |
| - return 'mediumProfile'; |
| - } else { |
| - return 'coldProfile'; |
| - } |
| - } |
| - |
| - CodeCallTreeNodeRow(VirtualTree tree, |
| - int depth, |
| - this.profile, |
| - CodeCallTreeNode node) |
| - : node = node, |
| - super(tree, depth) { |
| - if ((node.profileCode.code.kind == M.CodeKind.tag) && |
| - (node.profileCode.normalizedExclusiveTicks == 0) && |
| - (node.profileCode.normalizedInclusiveTicks == 0)) { |
| - selfPercent = ''; |
| - totalPercent = ''; |
| - } else { |
| - selfPercent = Utils.formatPercentNormalized( |
| - node.profileCode.normalizedExclusiveTicks); |
| - totalPercent = Utils.formatPercentNormalized( |
| - node.profileCode.normalizedInclusiveTicks); |
| - } |
| - percent = Utils.formatPercentNormalized(node.percentage); |
| - } |
| - |
| - void onRender(DivElement rowDiv) { |
| - rowDiv.children.add(makeGap(ems:0.1)); |
| - rowDiv.children.add( |
| - makeText(totalPercent, |
| - toolTip: 'global % on stack')); |
| - rowDiv.children.add(makeGap()); |
| - rowDiv.children.add( |
| - makeText(selfPercent, |
| - toolTip: 'global % executing')); |
| - rowDiv.children.add(makeGap()); |
| - rowDiv.children.add(makeIndenter(depth, colored: false)); |
| - rowDiv.children.add(makeColorBar(depth)); |
| - rowDiv.children.add(makeGap(ems: 1.0)); |
| - rowDiv.children.add(makeExpander()); |
| - rowDiv.children.add( |
| - makeText(percent, toolTip: 'tree node %', flexBasis: null)); |
| - rowDiv.children.add(makeGap(ems: 0.5)); |
| - codeRef.ref = node.profileCode.code; |
| - rowDiv.children.add(codeRef); |
| - } |
| - |
| - var codeRef = new Element.tag('code-ref'); |
| - |
| - int get childCount => node.children.length; |
| - |
| - void onShow() { |
| - if (children.length > 0) { |
| - return; |
| - } |
| - for (var childNode in node.children) { |
| - var row = new CodeCallTreeNodeRow(tree, depth + 1, profile, childNode); |
| - children.add(row); |
| - } |
| - } |
| -} |
| - |
| -/// Displays a CpuProfile |
| -@CustomTag('cpu-profile') |
| -class CpuProfileElement extends ObservatoryElement { |
| - CpuProfileElement.created() : super.created() { |
| - _updateTask = new Task(update); |
| - _renderTask = new Task(render); |
| - } |
| - |
| - attached() { |
| - super.attached(); |
| - sampleBufferControlElement = |
| - shadowRoot.querySelector('#sampleBufferControl'); |
| - assert(sampleBufferControlElement != null); |
| - sampleBufferControlElement.onSampleBufferUpdate = onSampleBufferChange; |
| - stackTraceTreeConfigElement = |
| - shadowRoot.querySelector('#stackTraceTreeConfig'); |
| - assert(stackTraceTreeConfigElement != null); |
| - stackTraceTreeConfigElement.onTreeConfigChange = onTreeConfigChange; |
| - cpuProfileVirtualTreeElement = shadowRoot.querySelector('#cpuProfileVirtualTree'); |
| - assert(cpuProfileVirtualTreeElement != null); |
| - cpuProfileVirtualTreeElement.profile = sampleBufferControlElement.profile; |
| - _resizeSubscription = window.onResize.listen((_) => _updateSize()); |
| - _updateTask.queue(); |
| - _updateSize(); |
| - } |
| - |
| - detached() { |
| - super.detached(); |
| - if (_resizeSubscription != null) { |
| - _resizeSubscription.cancel(); |
| - } |
| - } |
| - |
| - _updateSize() { |
| - var applySize = (e) { |
| - Rectangle rect = e.getBoundingClientRect(); |
| - final totalHeight = window.innerHeight; |
| - final bottomMargin = 200; |
| - final mainHeight = totalHeight - bottomMargin; |
| - e.style.setProperty('height', '${mainHeight}px'); |
| - }; |
| - HtmlElement e2 = $['cpuProfileVirtualTree']; |
| - applySize(e2); |
| - } |
| - |
| - isolateChanged(oldValue) { |
| - _updateTask.queue(); |
| - } |
| - |
| - update() { |
| - if (sampleBufferControlElement != null) { |
| - sampleBufferControlElement.reload(isolate); |
| - } |
| - } |
| - |
| - onSampleBufferChange(CpuProfile sampleBuffer) { |
| - _renderTask.queue(); |
| - } |
| - |
| - onTreeConfigChange(String modeSelector, |
| - String directionSelector, |
| - String filterString) { |
| - ProfileTreeDirection direction = ProfileTreeDirection.Exclusive; |
| - if (directionSelector != 'Up') { |
| - direction = ProfileTreeDirection.Inclusive; |
| - } |
| - ProfileTreeMode mode = ProfileTreeMode.Function; |
| - if (modeSelector == 'Code') { |
| - mode = ProfileTreeMode.Code; |
| - } |
| - // Clear the filter. |
| - cpuProfileVirtualTreeElement.filter = null; |
| - if (filterString != null) { |
| - filterString = filterString.trim(); |
| - if (filterString.isNotEmpty) { |
| - cpuProfileVirtualTreeElement.filter = (CallTreeNode node) { |
| - return node.name.contains(filterString); |
| - }; |
| - } |
| - } |
| - cpuProfileVirtualTreeElement.direction = direction; |
| - cpuProfileVirtualTreeElement.mode = mode; |
| - _renderTask.queue(); |
| - } |
| - |
| - Future clearCpuProfile() async { |
| - await isolate.invokeRpc('_clearCpuProfile', { }); |
| - _updateTask.queue(); |
| - return new Future.value(null); |
| - } |
| - |
| - Future refresh() { |
| - _updateTask.queue(); |
| - return new Future.value(null); |
| - } |
| - |
| - render() { |
| - cpuProfileVirtualTreeElement.render(); |
| - } |
| - |
| - @published Isolate isolate; |
| - |
| - StreamSubscription _resizeSubscription; |
| - Task _updateTask; |
| - Task _renderTask; |
| - SampleBufferControlElement sampleBufferControlElement; |
| - StackTraceTreeConfigElement stackTraceTreeConfigElement; |
| - CpuProfileVirtualTreeElement cpuProfileVirtualTreeElement; |
| -} |
| - |
| class NameSortedTable extends SortedTable { |
| NameSortedTable(columns) : super(columns); |
| @override |
| @@ -1006,6 +549,8 @@ class NameSortedTable extends SortedTable { |
| @CustomTag('cpu-profile-table') |
| class CpuProfileTableElement extends ObservatoryElement { |
| + |
| + |
| CpuProfileTableElement.created() : super.created() { |
| _updateTask = new Task(update); |
| _renderTask = new Task(render); |
| @@ -1038,24 +583,6 @@ class CpuProfileTableElement extends ObservatoryElement { |
| attached() { |
| super.attached(); |
| - sampleBufferControlElement = |
| - shadowRoot.querySelector('#sampleBufferControl'); |
| - assert(sampleBufferControlElement != null); |
| - sampleBufferControlElement.onSampleBufferUpdate = onSampleBufferChange; |
| - // Disable the tag selector- we always want no tags. |
| - sampleBufferControlElement.tagSelector = 'None'; |
| - sampleBufferControlElement.showTagSelector = false; |
| - stackTraceTreeConfigElement = |
| - shadowRoot.querySelector('#stackTraceTreeConfig'); |
| - assert(stackTraceTreeConfigElement != null); |
| - stackTraceTreeConfigElement.onTreeConfigChange = onTreeConfigChange; |
| - stackTraceTreeConfigElement.modeSelector = 'Function'; |
| - stackTraceTreeConfigElement.showModeSelector = false; |
| - stackTraceTreeConfigElement.directionSelector = 'Down'; |
| - stackTraceTreeConfigElement.showDirectionSelector = false; |
| - cpuProfileTreeElement = shadowRoot.querySelector('#cpuProfileTree'); |
| - assert(cpuProfileTreeElement != null); |
| - cpuProfileTreeElement.profile = sampleBufferControlElement.profile; |
| _updateTask.queue(); |
| _resizeSubscription = window.onResize.listen((_) => _updateSize()); |
| _updateSize(); |
| @@ -1081,30 +608,39 @@ class CpuProfileTableElement extends ObservatoryElement { |
| _updateTask.queue(); |
| } |
| - update() { |
| + update() async { |
| _clearView(); |
| - if (sampleBufferControlElement != null) { |
| - sampleBufferControlElement.reload(isolate).whenComplete(checkParameters); |
| - } |
| - } |
| - |
| - onSampleBufferChange(CpuProfile sampleBuffer) { |
| - _renderTask.queue(); |
| - } |
| - |
| - onTreeConfigChange(String modeSelector, |
| - String directionSelector, |
| - String filterString) { |
| - ProfileTreeDirection direction = ProfileTreeDirection.Exclusive; |
| - if (directionSelector != 'Up') { |
| - direction = ProfileTreeDirection.Inclusive; |
| + if (isolate == null) { |
| + return; |
| } |
| - ProfileTreeMode mode = ProfileTreeMode.Function; |
| - if (modeSelector == 'Code') { |
| - mode = ProfileTreeMode.Code; |
| + final progress = _repository.get(isolate, M.SampleProfileTag.None); |
| + shadowRoot.querySelector('#sampleBufferControl').children = [ |
| + sampleBufferControlElement = |
| + new SampleBufferControlElement(progress, showTag: false, |
| + selectedTag: M.SampleProfileTag.None, queue: app.queue) |
| + ]; |
| + await progress.onProgress.last; |
| + if (progress.status == M.SampleProfileLoadingStatus.Loaded) { |
| + _profile = progress.profile; |
| + shadowRoot.querySelector('#stackTraceTreeConfig').children = [ |
| + stackTraceTreeConfigElement = |
| + new StackTraceTreeConfigElement(showMode: false, showDirection: false, |
|
Cutch
2016/08/02 15:52:20
fix long lines
cbernaschina
2016/08/02 17:40:24
Done.
|
| + mode: ProfileTreeMode.Function, |
| + direction: ProfileTreeDirection.Exclusive, queue: app.queue) |
| + ..onModeChange.listen((e) { |
| + cpuProfileTreeElement.mode = e.element.mode; _renderTask.queue(); |
| + }) |
| + ..onDirectionChange.listen((e) { |
| + cpuProfileTreeElement.mode = e.element.mode; _renderTask.queue(); |
| + }) |
| + ..onFilterChange.listen((e) =>_renderTask.queue()) |
| + ]; |
| + shadowRoot.querySelector('#cpuProfileTree').children = [ |
| + cpuProfileTreeElement = |
| + new CpuProfileVirtualTreeElement(isolate, _profile, |
| + queue: app.queue) |
| + ]; |
| } |
| - cpuProfileTreeElement.direction = direction; |
| - cpuProfileTreeElement.mode = mode; |
| _renderTask.queue(); |
| } |
| @@ -1190,7 +726,7 @@ class CpuProfileTableElement extends ObservatoryElement { |
| } |
| ServiceFunction _findFunction(String functionName) { |
| - for (var func in profile.functions) { |
| + for (var func in _profile.functions) { |
| if (func.function.name == functionName) { |
| return func.function; |
| } |
| @@ -1250,7 +786,7 @@ class CpuProfileTableElement extends ObservatoryElement { |
| } |
| _buildFunctionTable() { |
| - for (var func in profile.functions) { |
| + for (var func in _profile.functions) { |
| if ((func.exclusiveTicks == 0) && (func.inclusiveTicks == 0)) { |
| // Skip. |
| continue; |
| @@ -1359,10 +895,10 @@ class CpuProfileTableElement extends ObservatoryElement { |
| /// |
| TableTree functionTree; |
| _updateFunctionTreeView() { |
| + if (cpuProfileTreeElement == null) { return; } |
| cpuProfileTreeElement.filter = (FunctionCallTreeNode node) { |
| return node.profileFunction.function == focusedFunction; |
| }; |
| - cpuProfileTreeElement.render(); |
| } |
| @published Isolate isolate; |
| @@ -1377,200 +913,10 @@ class CpuProfileTableElement extends ObservatoryElement { |
| Task _updateTask; |
| Task _renderTask; |
| - CpuProfile get profile => sampleBufferControlElement.profile; |
| + IsolateSampleProfileRepository _repository = |
| + new IsolateSampleProfileRepository(); |
| + CpuProfile _profile; |
| SampleBufferControlElement sampleBufferControlElement; |
| StackTraceTreeConfigElement stackTraceTreeConfigElement; |
| CpuProfileVirtualTreeElement cpuProfileTreeElement; |
| } |
| - |
| -enum ProfileTreeDirection { |
| - Exclusive, |
| - Inclusive |
| -} |
| - |
| -enum ProfileTreeMode { |
| - Code, |
| - Function, |
| -} |
| - |
| -@CustomTag('cpu-profile-virtual-tree') |
| -class CpuProfileVirtualTreeElement extends ObservatoryElement { |
| - ProfileTreeDirection direction = ProfileTreeDirection.Exclusive; |
| - ProfileTreeMode mode = ProfileTreeMode.Function; |
| - CpuProfile profile; |
| - VirtualTree virtualTree; |
| - CallTreeNodeFilter filter; |
| - StreamSubscription _resizeSubscription; |
| - @observable bool show = true; |
| - |
| - CpuProfileVirtualTreeElement.created() : super.created(); |
| - |
| - attached() { |
| - super.attached(); |
| - _resizeSubscription = window.onResize.listen((_) => _updateSize()); |
| - } |
| - |
| - detached() { |
| - super.detached(); |
| - _resizeSubscription?.cancel(); |
| - } |
| - |
| - void render() { |
| - _updateView(); |
| - } |
| - |
| - showChanged(oldValue) { |
| - if (show) { |
| - virtualTree?.root?.style?.display = 'block'; |
| - } else { |
| - virtualTree?.root?.style?.display = 'none'; |
| - } |
| - } |
| - |
| - void _updateView() { |
| - _updateSize(); |
| - virtualTree?.clear(); |
| - virtualTree?.uninstall(); |
| - virtualTree = null; |
| - bool exclusive = direction == ProfileTreeDirection.Exclusive; |
| - if (mode == ProfileTreeMode.Code) { |
| - _buildCodeTree(exclusive); |
| - } else { |
| - assert(mode == ProfileTreeMode.Function); |
| - _buildFunctionTree(exclusive); |
| - } |
| - virtualTree?.refresh(); |
| - } |
| - |
| - void _updateSize() { |
| - var treeBody = shadowRoot.querySelector('#tree'); |
| - assert(treeBody != null); |
| - int windowHeight = window.innerHeight - 32; |
| - treeBody.style.height = '${windowHeight}px'; |
| - } |
| - |
| - void _buildFunctionTree(bool exclusive) { |
| - var treeBody = shadowRoot.querySelector('#tree'); |
| - assert(treeBody != null); |
| - virtualTree = new VirtualTree(32, treeBody); |
| - if (profile == null) { |
| - return; |
| - } |
| - var tree = profile.loadFunctionTree(exclusive ? 'exclusive' : 'inclusive'); |
| - if (tree == null) { |
| - return; |
| - } |
| - if (filter != null) { |
| - tree = tree.filtered(filter); |
| - } |
| - for (var child in tree.root.children) { |
| - virtualTree.rows.add( |
| - new FunctionCallTreeNodeRow(virtualTree, 0, profile, child)); |
| - } |
| - if (virtualTree.rows.length == 1) { |
| - virtualTree.rows[0].expanded = true; |
| - } |
| - } |
| - |
| - void _buildCodeTree(bool exclusive) { |
| - var treeBody = shadowRoot.querySelector('#tree'); |
| - assert(treeBody != null); |
| - virtualTree = new VirtualTree(32, treeBody); |
| - if (profile == null) { |
| - return; |
| - } |
| - var tree = profile.loadCodeTree(exclusive ? 'exclusive' : 'inclusive'); |
| - if (tree == null) { |
| - return; |
| - } |
| - if (filter != null) { |
| - tree = tree.filtered(filter); |
| - } |
| - for (var child in tree.root.children) { |
| - virtualTree.rows.add( |
| - new CodeCallTreeNodeRow(virtualTree, 0, profile, child)); |
| - } |
| - if (virtualTree.rows.length == 1) { |
| - virtualTree.rows[0].expanded = true; |
| - } |
| - } |
| -} |
| - |
| -@CustomTag('cpu-profile-tree') |
| -class CpuProfileTreeElement extends ObservatoryElement { |
| - ProfileTreeDirection direction = ProfileTreeDirection.Exclusive; |
| - ProfileTreeMode mode = ProfileTreeMode.Function; |
| - CpuProfile profile; |
| - TableTree codeTree; |
| - TableTree functionTree; |
| - CallTreeNodeFilter functionFilter; |
| - @observable bool show = true; |
| - |
| - CpuProfileTreeElement.created() : super.created(); |
| - |
| - void render() { |
| - _updateView(); |
| - } |
| - |
| - showChanged(oldValue) { |
| - var treeTable = shadowRoot.querySelector('#treeTable'); |
| - assert(treeTable != null); |
| - treeTable.style.display = show ? 'table' : 'none'; |
| - } |
| - |
| - void _updateView() { |
| - if (functionTree != null) { |
| - functionTree.clear(); |
| - functionTree = null; |
| - } |
| - if (codeTree != null) { |
| - codeTree.clear(); |
| - codeTree = null; |
| - } |
| - bool exclusive = direction == ProfileTreeDirection.Exclusive; |
| - if (mode == ProfileTreeMode.Code) { |
| - _buildCodeTree(exclusive); |
| - } else { |
| - assert(mode == ProfileTreeMode.Function); |
| - _buildFunctionTree(exclusive); |
| - } |
| - } |
| - |
| - void _buildFunctionTree(bool exclusive) { |
| - if (functionTree == null) { |
| - var tableBody = shadowRoot.querySelector('#treeBody'); |
| - assert(tableBody != null); |
| - functionTree = new TableTree(tableBody, 2); |
| - } |
| - if (profile == null) { |
| - return; |
| - } |
| - var tree = profile.loadFunctionTree(exclusive ? 'exclusive' : 'inclusive'); |
| - if (tree == null) { |
| - return; |
| - } |
| - if (functionFilter != null) { |
| - tree = tree.filtered(functionFilter); |
| - } |
| - var rootRow = |
| - new FunctionProfileTreeRow(functionTree, null, profile, tree.root); |
| - functionTree.initialize(rootRow); |
| - } |
| - |
| - void _buildCodeTree(bool exclusive) { |
| - if (codeTree == null) { |
| - var tableBody = shadowRoot.querySelector('#treeBody'); |
| - assert(tableBody != null); |
| - codeTree = new TableTree(tableBody, 2); |
| - } |
| - if (profile == null) { |
| - return; |
| - } |
| - var tree = profile.loadCodeTree(exclusive ? 'exclusive' : 'inclusive'); |
| - if (tree == null) { |
| - return; |
| - } |
| - var rootRow = new CodeProfileTreeRow(codeTree, null, profile, tree.root); |
| - codeTree.initialize(rootRow); |
| - } |
| -} |