// Copyright (c) 2011 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. /** * @fileoverview TimelineView visualizes GPU_TRACE events using the * gpu.Timeline component. */ cr.define('gpu', 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; } /** * TimelineView * @constructor * @extends {HTMLDivElement} */ TimelineView = cr.ui.define('div'); TimelineView.prototype = { __proto__: HTMLDivElement.prototype, decorate: function() { this.className = 'timeline-view'; this.timelineContainer_ = document.createElement('div'); this.timelineContainer_.className = 'timeline-container'; var summaryContainer_ = document.createElement('div'); summaryContainer_.className = 'summary-container'; this.summary_ = document.createElement('pre'); this.summary_.className = 'summary'; summaryContainer_.appendChild(this.summary_); this.appendChild(this.timelineContainer_); this.appendChild(summaryContainer_); this.onSelectionChangedBoundToThis_ = this.onSelectionChanged_.bind(this); }, set traceEvents(traceEvents) { console.log('TimelineView.refresh'); this.timelineModel_ = new gpu.TimelineModel(traceEvents); // remove old timeline this.timelineContainer_.textContent = ''; // create new timeline if needed if (traceEvents.length) { this.timeline_ = new gpu.Timeline(); this.timeline_.model = this.timelineModel_; this.timelineContainer_.appendChild(this.timeline_); this.timeline_.onResize(); this.timeline_.addEventListener('selectionChange', this.onSelectionChangedBoundToThis_); this.onSelectionChanged_(); } else { this.timeline_ = null; } }, onSelectionChanged_: function(e) { console.log('selection changed'); var timeline = this.timeline_; var selection = timeline.selection; var outputDiv = this.summary_; if (!selection.length) { outputDiv.textContent = timeline.keyHelp; return; } var text = ''; if (selection.length == 1) { var c0Width = 10; var slice = selection[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'; 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 { var c0Width = 55; var c1Width = 12; var c2Width = 5; text = 'Selection summary:\n'; var tsLo = Math.min.apply(Math, selection.map( function(s) {return s.slice.start;})); var tsHi = Math.max.apply(Math, selection.map( function(s) {return s.slice.end;})); // compute total selection duration var titles = selection.map(function(i) { return i.slice.title; }); var slicesByTitle = {}; for (var i = 0; i < selection.length; i++) { var slice = selection[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(selection.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'; } // done outputDiv.textContent = text; } }; return { TimelineView: TimelineView }; });