| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| 'use strict'; |
| |
| /** |
| * @fileoverview TimelineView visualizes TRACE_EVENT events using the |
| * tracing.Timeline component and adds in selection summary and control buttons. |
| */ |
| cr.define('tracing', function() { |
| function tsRound(ts) { |
| return Math.round(ts * 1000.0) / 1000.0; |
| } |
| |
| function getPadding(text, width) { |
| width = width || 0; |
| |
| if (typeof text != 'string') |
| text = String(text); |
| |
| if (text.length >= width) |
| return ''; |
| |
| var pad = ''; |
| for (var i = 0; i < width - text.length; i++) |
| pad += ' '; |
| return pad; |
| } |
| |
| function leftAlign(text, width) { |
| return text + getPadding(text, width); |
| } |
| |
| function rightAlign(text, width) { |
| return getPadding(text, width) + text; |
| } |
| |
| |
| function getTextForSelection(selection) { |
| var text = ''; |
| var sliceHits = selection.getSliceHits(); |
| var counterSampleHits = selection.getCounterSampleHits(); |
| |
| if (sliceHits.length == 1) { |
| var c0Width = 14; |
| var slice = sliceHits[0].slice; |
| text = 'Selected item:\n'; |
| text += leftAlign('Title', c0Width) + ': ' + slice.title + '\n'; |
| text += leftAlign('Start', c0Width) + ': ' + |
| tsRound(slice.start) + ' ms\n'; |
| text += leftAlign('Duration', c0Width) + ': ' + |
| tsRound(slice.duration) + ' ms\n'; |
| if (slice.durationInUserTime) |
| text += leftAlign('Duration (U)', c0Width) + ': ' + |
| tsRound(slice.durationInUserTime) + ' ms\n'; |
| |
| var n = 0; |
| for (var argName in slice.args) { |
| n += 1; |
| } |
| if (n > 0) { |
| text += leftAlign('Args', c0Width) + ':\n'; |
| for (var argName in slice.args) { |
| var argVal = slice.args[argName]; |
| text += leftAlign(' ' + argName, c0Width) + ': ' + argVal + '\n'; |
| } |
| } |
| } else if (sliceHits.length > 1) { |
| var c0Width = 55; |
| var c1Width = 12; |
| var c2Width = 5; |
| text = 'Slices:\n'; |
| var tsLo = sliceHits.range.min; |
| var tsHi = sliceHits.range.max; |
| |
| // compute total sliceHits duration |
| var titles = sliceHits.map(function(i) { return i.slice.title; }); |
| |
| var slicesByTitle = {}; |
| for (var i = 0; i < sliceHits.length; i++) { |
| var slice = sliceHits[i].slice; |
| if (!slicesByTitle[slice.title]) |
| slicesByTitle[slice.title] = { |
| slices: [] |
| }; |
| slicesByTitle[slice.title].slices.push(slice); |
| } |
| var totalDuration = 0; |
| for (var sliceGroupTitle in slicesByTitle) { |
| var sliceGroup = slicesByTitle[sliceGroupTitle]; |
| var duration = 0; |
| for (i = 0; i < sliceGroup.slices.length; i++) |
| duration += sliceGroup.slices[i].duration; |
| totalDuration += duration; |
| |
| text += ' ' + |
| leftAlign(sliceGroupTitle, c0Width) + ': ' + |
| rightAlign(tsRound(duration) + 'ms', c1Width) + ' ' + |
| rightAlign(String(sliceGroup.slices.length), c2Width) + |
| ' occurrences' + '\n'; |
| } |
| |
| text += leftAlign('*Totals', c0Width) + ' : ' + |
| rightAlign(tsRound(totalDuration) + 'ms', c1Width) + ' ' + |
| rightAlign(String(sliceHits.length), c2Width) + ' occurrences' + |
| '\n'; |
| |
| text += '\n'; |
| |
| text += leftAlign('Selection start', c0Width) + ' : ' + |
| rightAlign(tsRound(tsLo) + 'ms', c1Width) + |
| '\n'; |
| text += leftAlign('Selection extent', c0Width) + ' : ' + |
| rightAlign(tsRound(tsHi - tsLo) + 'ms', c1Width) + |
| '\n'; |
| } |
| |
| if (counterSampleHits.length == 1) { |
| text = 'Selected counter:\n'; |
| var c0Width = 55; |
| var hit = counterSampleHits[0]; |
| var ctr = hit.counter; |
| var sampleIndex = hit.sampleIndex; |
| var values = []; |
| for (var i = 0; i < ctr.numSeries; ++i) |
| values.push(ctr.samples[ctr.numSeries * sampleIndex + i]); |
| text += leftAlign('Title', c0Width) + ': ' + ctr.name + '\n'; |
| text += leftAlign('Timestamp', c0Width) + ': ' + |
| tsRound(ctr.timestamps[sampleIndex]) + ' ms\n'; |
| if (ctr.numSeries > 1) |
| text += leftAlign('Values', c0Width) + ': ' + values.join('\n') + '\n'; |
| else |
| text += leftAlign('Value', c0Width) + ': ' + values.join('\n') + '\n'; |
| |
| } else if (counterSampleHits.length > 1 && sliceHits.length == 0) { |
| text += 'Analysis of multiple counters not yet implemented. ' + |
| 'Pick a single counter.'; |
| } |
| return text; |
| } |
| |
| var TimelineAnalysisView = cr.ui.define('div'); |
| |
| TimelineAnalysisView.prototype = { |
| __proto__: HTMLDivElement.prototype, |
| |
| decorate: function() { |
| this.className = 'timeline-analysis'; |
| }, |
| |
| set selection(selection) { |
| this.textContent = getTextForSelection(selection); |
| } |
| }; |
| |
| return { |
| TimelineAnalysisView: TimelineAnalysisView, |
| }; |
| }); |