1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 tvcm.require('tracing.analysis.util');
8 tvcm.require('tracing.selection');
9 tvcm.require('tracing.timeline_view_side_panel');
10 tvcm.require('tvcm.iteration_helpers');
11 tvcm.require('tvcm.statistics');
12 tvcm.require('tvcm.ui.dom_helpers');
13 tvcm.require('tvcm.ui.pie_chart');
14 tvcm.require('tvcm.ui.sunburst_chart');
16 tvcm.requireTemplate('tracing.sampling_summary_side_panel');
18 tvcm.exportTo('tracing', function() {
19 var RequestSelectionChangeEvent = tracing.RequestSelectionChangeEvent;
24 var CallTreeNode = function(name, category) {
25 this.parent = undefined;
27 this.category = category;
35 var Thread = function(thread) {
37 this.rootNode = new CallTreeNode('root', 'root');
38 this.rootCategories = {};
40 this.sfToNode[0] = self.rootNode;
44 getCallTreeNode: function(stackFrame) {
45 if (stackFrame.id in this.sfToNode)
46 return this.sfToNode[stackFrame.id];
48 // Create & save the node.
49 var newNode = new CallTreeNode(stackFrame.title, stackFrame.category);
50 this.sfToNode[stackFrame.id] = newNode;
52 // Add node to parent tree node.
53 if (stackFrame.parentFrame) {
54 var parentNode = this.getCallTreeNode(stackFrame.parentFrame);
55 parentNode.children.push(newNode);
57 // Creating a root category node for each category helps group samples
58 // that may be missing call stacks.
59 var rootCategory = this.rootCategories[stackFrame.category];
62 new CallTreeNode(stackFrame.category, stackFrame.category);
63 this.rootNode.children.push(rootCategory);
64 this.rootCategories[stackFrame.category] = rootCategory;
66 rootCategory.children.push(newNode);
71 addSample: function(sample) {
72 var node = this.getCallTreeNode(sample.leafStackFrame);
73 node.selfTime += sample.weight;
77 function genCallTree(node, isRoot) {
79 category: node.category,
83 if (isRoot || node.children.length > 0) {
85 for (var c = 0; c < node.children.length; c++)
86 ret.children.push(genCallTree(node.children[c], false));
87 if (node.selfTime > 0.0)
90 category: ret.category,
95 ret.size = node.selfTime;
102 // Create sunburst data from model data.
103 function createSunburstData(model, rangeOfInterest) {
104 // TODO(vmiura): Add selection.
106 function getOrCreateThread(thread) {
108 if (thread.tid in threads) {
109 ret = threads[thread.tid];
111 ret = new Thread(thread);
112 threads[thread.tid] = ret;
118 var samples = model.samples;
119 var rangeMin = rangeOfInterest.min;
120 var rangeMax = rangeOfInterest.max;
121 for (var i = 0; i < samples.length; i++) {
122 var sample = samples[i];
123 if (sample.start >= rangeMin && sample.start <= rangeMax)
124 getOrCreateThread(sample.thread).addSample(sample);
127 // Generate sunburst data.
129 name: '<All Threads>',
133 for (var t in threads) {
134 if (!threads.hasOwnProperty(t)) continue;
135 var thread = threads[t];
137 name: '<' + thread.thread.name + '>',
139 children: genCallTree(thread.rootNode, true)
141 sunburstData.children.push(threadData);
146 // Create sunburst chart from model data.
147 function createSunburstChart(model, rangeOfInterest) {
148 // TODO(vmiura): Add selection.
149 var sunburstData = createSunburstData(model, rangeOfInterest);
150 var chart = new tvcm.ui.SunburstChart();
153 chart.chartTitle = 'Sampling Summary';
154 chart.data = sunburstData;
161 var SamplingSummarySidePanel =
162 tvcm.ui.define('x-sample-summary-side-panel',
163 tracing.TimelineViewSidePanel);
164 SamplingSummarySidePanel.textLabel = 'Sampling Summary';
165 SamplingSummarySidePanel.supportsModel = function(m) {
166 if (m == undefined) {
169 reason: 'Unknown tracing model'
173 if (m.samples.length == 0) {
176 reason: 'No sampling data in trace'
185 SamplingSummarySidePanel.prototype = {
186 __proto__: tracing.TimelineViewSidePanel.prototype,
188 decorate: function() {
189 tracing.TimelineViewSidePanel.prototype.decorate.call(this);
190 this.classList.add('x-sample-summary-side-panel');
191 this.appendChild(tvcm.instantiateTemplate(
192 '#x-sample-summary-side-panel-template'));
194 this.rangeOfInterest_ = new tvcm.Range();
195 this.chart_ = undefined;
204 this.updateContents_();
207 get rangeOfInterest() {
208 return this.rangeOfInterest_;
211 set rangeOfInterest(rangeOfInterest) {
212 this.rangeOfInterest_ = rangeOfInterest;
213 this.updateContents_();
216 updateContents_: function() {
217 var resultArea = this.querySelector('result-area');
218 this.chart_ = undefined;
219 resultArea.textContent = '';
221 if (this.model_ === undefined)
225 if (this.rangeOfInterest_.isEmpty)
226 rangeOfInterest = this.model_.bounds;
228 rangeOfInterest = this.rangeOfInterest_;
230 this.chart_ = createSunburstChart(this.model_, rangeOfInterest);
231 resultArea.appendChild(this.chart_);
232 this.chart_.setSize(this.chart_.getMinSize());
236 tracing.TimelineViewSidePanel.registerPanelSubtype(SamplingSummarySidePanel);
239 SamplingSummarySidePanel: SamplingSummarySidePanel,
240 createSunburstData: createSunburstData