3 Copyright (c) 2013 The Chromium Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style license that can be
5 found in the LICENSE file.
8 <link rel="import" href="/tracing/analysis/analysis_results.html">
9 <link rel="import" href="/tracing/analysis/analysis_sub_view.html">
10 <link rel="import" href="/tracing/analysis/util.html">
11 <link rel="import" href="/base.html">
12 <link rel="import" href="/base/ui.html">
13 <link rel="import" href="/base/ui/sortable_table.html">
15 <polymer-element name="single-slice-analysis-sub-view"
16 extends="tracing-analysis-sub-view"
17 constructor="SingleSliceAnalysisSubView">
21 tv.onPolymerReady(function() {
22 tracing.registerAnalysisSubViewType(
24 function supported(selection) {
25 if (selection.length != 1)
27 return selection[0] instanceof tracing.trace_model.Slice ||
28 selection[0] instanceof tracing.trace_model.FlowEvent ||
29 selection[0] instanceof tracing.trace_model.InstantEvent;
31 function constructView(selection) {
32 var event = selection[0];
33 var typeName = event.analysisTypeName;
34 var customViewInfo = tracing.analysis.SliceView.getViewInfo(typeName);
36 return new customViewInfo.constructor();
37 return new SingleSliceAnalysisSubView();
40 passSelectionToConstructor: true
42 tracing.registerAnalysisSubViewType(
45 if (selection.length <= 1)
47 return selection[0] instanceof tracing.trace_model.Slice ||
48 selection[0] instanceof tracing.trace_model.FlowEvent ||
49 selection[0] instanceof tracing.trace_model.InstantEvent;
51 MultipleSlicesAnalysisSubView);
55 var TYPE_TO_NAME_LIST = [
57 type: tracing.trace_model.Slice,
61 type: tracing.trace_model.FlowEvent,
65 type: tracing.trace_model.InstantEvent,
72 this.currentSelection_ = undefined;
75 set selection(selection) {
76 this.currentSelection_ = selection;
77 this.textContent = '';
79 if (selection.length === 0)
83 for (var i = 0; i < TYPE_TO_NAME_LIST.length; i++) {
84 var item = TYPE_TO_NAME_LIST[i];
85 if (selection[0] instanceof item.type) {
91 var results = new tracing.analysis.AnalysisResults();
92 this.appendChild(results);
94 this.analyzeSingleSlice_(results, selection[0], typeName);
98 return this.currentSelection_;
101 analyzeSingleSlice_: function(results, slice, type) {
102 results.appendHeader('Selected ' + type + ':');
103 var table = results.appendTable('analysis-slice-table', 2);
106 results.appendInfoRow(table, 'Error', slice.error);
109 results.appendInfoRow(table, 'Title', slice.title);
112 results.appendInfoRow(table, 'Category', slice.category);
114 results.appendInfoRowTime(table, 'Start', slice.start);
115 results.appendInfoRowTime(table, 'Wall Duration', slice.duration);
117 if (slice.cpuDuration)
118 results.appendInfoRowTime(table, 'CPU Duration', slice.cpuDuration);
121 results.appendInfoRowTime(table, 'Self Time', slice.selfTime);
123 if (slice.cpuSelfTime) {
125 if (slice.cpuSelfTime > slice.selfTime) {
127 'Note that CPU Self Time is larger than Self Time. ' +
128 'This is a known limitation of this system, which occurs ' +
129 'due to several subslices, rounding issues, and inprecise ' +
130 'time at which we get cpu- and real-time.';
132 results.appendInfoRowTime(table, 'CPU Self Time', slice.cpuSelfTime,
136 if (slice.durationInUserTime) {
137 results.appendInfoRowTime(table, 'Duration (U)',
138 slice.durationInUserTime);
142 for (var argName in slice.args) {
146 results.appendInfoRow(table, 'Args');
147 for (var argName in slice.args) {
148 var argVal = slice.args[argName];
149 // TODO(sleffler) use span instead?
150 results.appendInfoRow(table, ' ' + argName, argVal);
159 <polymer-element name="multiple-slices-analysis-sub-view"
160 extends="tracing-analysis-sub-view"
161 constructor="MultipleSlicesAnalysisSubView">
165 var TYPE_TO_NAME_LIST = [
167 type: tracing.trace_model.Slice,
171 type: tracing.trace_model.FlowEvent,
175 type: tracing.trace_model.InstantEvent,
176 name: 'Instant Events'
181 created: function() {
182 this.currentSelection_ = undefined;
185 set selection(selection) {
186 this.currentSelection_ = selection;
187 this.textContent = '';
189 if (selection.length === 0)
193 for (var i = 0; i < TYPE_TO_NAME_LIST.length; i++) {
194 var item = TYPE_TO_NAME_LIST[i];
195 if (selection[0] instanceof item.type) {
196 typeName = item.name;
201 var results = new tracing.analysis.AnalysisResults();
202 this.appendChild(results);
204 this.analyzeMultipleSlices_(results, selection, typeName);
208 return this.currentSelection_;
211 analyzeSingleTypeSlices_: function(results, sliceGroup, hasCpuDuration) {
212 results.appendInfo('Title: ', sliceGroup[0].title);
213 results.appendInfo('Category: ', sliceGroup[0].category);
215 var table = results.appendTable('analysis-slice-table',
217 var row = results.appendHeadRow(table);
218 results.appendTableCell(table, row, 'Start');
219 results.appendTableCell(table, row, 'Wall Duration (ms)');
221 results.appendTableCell(table, row, 'CPU Duration (ms)');
222 results.appendTableCell(table, row, 'Self Time (ms)');
223 results.appendTableCell(table, row, 'Args');
226 tv.iterItems(sliceGroup, function(title, slice) {
228 results.appendDetailsRow(table, slice.start, slice.duration,
229 slice.selfTime ? slice.selfTime : slice.duration, slice.args,
231 return new tracing.Selection([slice]);
232 }, slice.cpuDuration);
235 tv.ui.SortableTable.decorate(table);
238 analyzeMultipleSlices_: function(results, slices, type) {
239 var tsLo = slices.bounds.min;
240 var tsHi = slices.bounds.max;
243 var sliceGroups = {};
244 var hasCpuDuration = false;
246 for (var i = 0; i < slices.length; i++) {
247 var slice = slices[i];
248 if (sliceGroups[slice.title] === undefined) {
249 sliceGroups[slice.title] = [];
253 if (slice.cpuDuration)
254 hasCpuDuration = true;
256 var sliceGroup = sliceGroups[slice.title];
257 sliceGroup.push(slices[i]);
260 results.appendHeader(type + ':');
261 var table = results.appendTable('analysis-slice-table',
263 var row = results.appendHeadRow(table);
264 results.appendTableCell(table, row, 'Name');
265 results.appendTableCell(table, row, 'Wall Duration (ms)');
267 results.appendTableCell(table, row, 'CPU Duration (ms)');
268 results.appendTableCell(table, row, 'Self Time (ms)');
270 results.appendTableCell(table, row, 'CPU Self Time (ms)');
271 results.appendTableCell(table, row, 'Occurrences');
273 var thisComponent = this;
274 var totalDuration = 0;
275 var totalCpuDuration = 0;
276 var totalSelfTime = 0;
277 var totalCpuSelfTime = 0;
278 tv.iterItems(sliceGroups, function(sliceGroupTitle, sliceGroup) {
284 var startOfFirstOccurrence = Number.MAX_VALUE;
285 var startOfLastOccurrence = -Number.MAX_VALUE;
286 var min = Number.MAX_VALUE;
287 var max = -Number.MAX_VALUE;
288 for (var i = 0; i < sliceGroup.length; i++) {
289 var slice = sliceGroup[i];
290 duration += slice.duration;
291 if (slice.cpuDuration) {
292 cpuDuration += slice.cpuDuration;
293 cpuSelfTime += slice.cpuSelfTime ? slice.cpuSelfTime :
296 selfTime += slice.selfTime ? slice.selfTime : slice.duration;
297 startOfFirstOccurrence = Math.min(slice.start, startOfFirstOccurrence);
298 startOfLastOccurrence = Math.max(slice.start, startOfLastOccurrence);
299 min = Math.min(slice.duration, min);
300 max = Math.max(slice.duration, max);
303 totalDuration += duration;
304 totalCpuDuration += cpuDuration;
305 totalSelfTime += selfTime;
306 totalCpuSelfTime += cpuSelfTime;
308 if (sliceGroup.length == 0)
310 avg = duration / sliceGroup.length;
316 avg_stddev: undefined,
317 frequency: undefined,
318 frequency_stddev: undefined
321 // Compute the stddev of the slice durations.
322 var sumOfSquaredDistancesToMean = 0;
323 for (var i = 0; i < sliceGroup.length; i++) {
324 var signedDistance = statistics.avg - sliceGroup[i].duration;
325 sumOfSquaredDistancesToMean += signedDistance * signedDistance;
328 statistics.avg_stddev =
329 Math.sqrt(sumOfSquaredDistancesToMean / (sliceGroup.length - 1));
331 // We require at least 3 samples to compute the stddev.
332 var elapsed = startOfLastOccurrence - startOfFirstOccurrence;
333 if (sliceGroup.length > 2 && elapsed > 0) {
334 var numDistances = sliceGroup.length - 1;
335 statistics.frequency = (1000 * numDistances) / elapsed;
337 // Compute the stddev.
338 sumOfSquaredDistancesToMean = 0;
339 for (var i = 1; i < sliceGroup.length; i++) {
340 var currentFrequency =
341 1000 / (sliceGroup[i].start - sliceGroup[i - 1].start);
342 var signedDistance = statistics.frequency - currentFrequency;
343 sumOfSquaredDistancesToMean += signedDistance * signedDistance;
346 statistics.frequency_stddev =
347 Math.sqrt(sumOfSquaredDistancesToMean / (numDistances - 1));
349 results.appendDataRow(table, sliceGroupTitle, duration,
350 hasCpuDuration ? (cpuDuration > 0 ?
351 cpuDuration : '') : null,
353 hasCpuDuration ? (cpuSelfTime > 0 ?
354 cpuSelfTime : '') : null,
355 sliceGroup.length, null, statistics, function() {
356 return new tracing.Selection(sliceGroup);
359 // The whole selection is a single type so list out the information
360 // for each sub slice.
362 thisComponent.analyzeSingleTypeSlices_(results, sliceGroup,
366 // Only one row so we already know the totals.
367 if (numTitles !== 1) {
368 results.appendDataRow(table, 'Totals', totalDuration,
369 hasCpuDuration ? totalCpuDuration : null,
371 hasCpuDuration ? totalCpuSelfTime : null,
373 null, null, null, true);
374 results.appendSpacingRow(table, true);
375 tv.ui.SortableTable.decorate(table);
378 results.appendInfoRowTime(table, 'Selection start', tsLo, true);
379 results.appendInfoRowTime(table, 'Selection extent', tsHi - tsLo, true);