1 // Copyright (c) 2013 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.requireStylesheet('tracing.analysis.analysis_results');
9 tvcm.require('tracing.analysis.util');
10 tvcm.require('tracing.analysis.analysis_link');
11 tvcm.require('tracing.analysis.generic_object_view');
12 tvcm.require('tvcm.ui');
14 tvcm.exportTo('tracing.analysis', function() {
15 var AnalysisResults = tvcm.ui.define('div');
17 AnalysisResults.prototype = {
18 __proto__: HTMLDivElement.prototype,
20 decorate: function() {
21 this.className = 'analysis-results';
24 get requiresTallView() {
29 this.textContent = '';
32 createSelectionChangingLink: function(text, selectionGenerator,
34 var el = this.ownerDocument.createElement('a');
35 tracing.analysis.AnalysisLink.decorate(el);
36 el.textContent = text;
37 el.selectionGenerator = selectionGenerator;
39 el.title = opt_tooltip;
43 appendElement_: function(parent, tagName, opt_text) {
44 var n = parent.ownerDocument.createElement(tagName);
45 parent.appendChild(n);
46 if (opt_text != undefined)
47 n.textContent = opt_text;
51 appendText_: function(parent, text) {
52 var textElement = parent.ownerDocument.createTextNode(text);
53 parent.appendChild(textNode);
57 appendTableCell_: function(table, row, cellnum, text, opt_warning) {
58 var td = this.appendElement_(row, 'td', text);
59 td.className = table.className + '-col-' + cellnum;
61 var span = document.createElement('span');
62 span.textContent = ' ' + String.fromCharCode(9888);
63 span.title = opt_warning;
70 * Creates and append a table cell at the end of the given row.
72 appendTableCell: function(table, row, text) {
73 return this.appendTableCell_(table, row, row.children.length, text);
76 appendTableCellWithTooltip_: function(table, row, cellnum, text, tooltip) {
78 var td = this.appendElement_(row, 'td');
79 td.className = table.className + '-col-' + cellnum;
80 var span = this.appendElement_(td, 'span', text);
81 span.className = 'tooltip';
85 this.appendTableCell_(table, row, cellnum, text);
90 * Creates and appends a section header element.
92 appendHeader: function(label) {
93 var header = this.appendElement_(this, 'span', label);
94 header.className = 'analysis-header';
99 * Creates and appends a info element of the format "<b>label</b>value".
101 appendInfo: function(label, value) {
102 var div = this.appendElement_(this, 'div');
103 div.label = this.appendElement_(div, 'b', label);
104 div.value = this.appendElement_(div, 'span', value);
109 * Adds a table with the given className.
111 * @return {HTMLTableElement} The newly created table.
113 appendTable: function(className, numColumns) {
114 var table = this.appendElement_(this, 'table');
115 table.className = className + ' analysis-table';
116 table.numColumns = numColumns;
121 * Creates and appends a |tr| in |thead|, if |thead| does not exist, create
124 appendHeadRow: function(table) {
126 throw new Error('Only one header row allowed.');
127 if (table.tbody || table.tfoot)
129 'Cannot add a header row after data rows have been added.');
130 table.headerRow = this.appendElement_(
131 this.appendElement_(table, 'thead'), 'tr');
132 table.headerRow.className = 'analysis-table-header';
133 return table.headerRow;
137 * Creates and appends a |tr| in |tbody|, if |tbody| does not exist, create
140 appendBodyRow: function(table) {
143 'Cannot add a tbody row after footer rows have been added.');
145 table.tbody = this.appendElement_(table, 'tbody');
146 var row = this.appendElement_(table.tbody, 'tr');
148 row.className = 'analysis-table-row';
150 row.className = 'analysis-table-row-inverted';
155 * Creates and appends a |tr| in |tfoot|, if |tfoot| does not exist, create
158 appendFootRow: function(table) {
160 table.tfoot = this.appendElement_(table, 'tfoot');
161 table.tfoot.rowsClassName = (
162 (table.headerRow ? 1 : 0) +
163 (table.tbody ? table.tbody.rows.length : 0)) % 2 ?
164 'analysis-table-row' : 'analysis-table-row-inverted';
167 var row = this.appendElement_(table.tfoot, 'tr');
168 row.className = table.tfoot.rowsClassName;
173 * Adds a spacing row to spread out results.
175 appendSpacingRow: function(table, opt_inFoot) {
176 if (table.tfoot || opt_inFoot)
177 var row = this.appendFootRow(table);
179 var row = this.appendBodyRow(table);
180 for (var i = 0; i < table.numColumns; i++)
181 this.appendTableCell_(table, row, i, ' ');
185 * Creates and appends a row to |table| with a left-aligned |label] in the
186 * first column and an optional |opt_value| in the second column.
188 appendInfoRow: function(table, label, opt_value, opt_inFoot) {
189 if (table.tfoot || opt_inFoot)
190 var row = this.appendFootRow(table);
192 var row = this.appendBodyRow(table);
193 this.appendTableCell_(table, row, 0, label);
194 if (opt_value !== undefined) {
195 var objectView = new tracing.analysis.GenericObjectView();
196 objectView.object = opt_value;
197 objectView.classList.add('analysis-table-col-1');
198 objectView.style.display = 'table-cell';
199 row.appendChild(objectView);
201 this.appendTableCell_(table, row, 1, '');
203 for (var i = 2; i < table.numColumns; i++)
204 this.appendTableCell_(table, row, i, '');
208 * Creates and appends a row to |table| with a left-aligned |label] in the
209 * first column and a millisecond |time| value in the second column.
211 appendInfoRowTime: function(table, label, time, opt_inFoot, opt_warning) {
212 if (table.tfoot || opt_inFoot)
213 var row = this.appendFootRow(table);
215 var row = this.appendBodyRow(table);
216 this.appendTableCell_(table, row, 0, label);
217 this.appendTableCell_(
218 table, row, 1, tracing.analysis.tsRound(time) + ' ms', opt_warning);
222 * Creates and appends a row to |table| that summarizes a single slice or a
223 * single counter. The row has a left-aligned |start| in the first column,
224 * the |duration| of the data in the second, the number of |occurrences| in
227 * @param {object=} opt_statistics May be undefined, or an object which
228 * contains calculated staistics containing min/max/avg for slices,
229 * or min/max/avg/start/end for counters.
231 appendDetailsRow: function(table, start, duration, selfTime, args,
232 opt_selectionGenerator, opt_cpuDuration) {
233 var row = this.appendBodyRow(table);
235 if (opt_selectionGenerator) {
236 var labelEl = this.appendTableCell(table, row,
237 tracing.analysis.tsRound(start));
238 labelEl.textContent = '';
239 labelEl.appendChild(this.createSelectionChangingLink(
240 tracing.analysis.tsRound(start),
241 opt_selectionGenerator, ''));
243 this.appendTableCell(table, row, tracing.analysis.tsRound(start));
246 if (duration !== null)
247 this.appendTableCell(table, row, tracing.analysis.tsRound(duration));
250 this.appendTableCell(table, row,
251 opt_cpuDuration != '' ?
252 tracing.analysis.tsRound(opt_cpuDuration) :
255 if (selfTime !== null)
256 this.appendTableCell(table, row, tracing.analysis.tsRound(selfTime));
258 var argsCell = this.appendTableCell(table, row, '');
260 for (var argName in args) {
265 for (var argName in args) {
266 var argVal = args[argName];
267 var objectView = new tracing.analysis.GenericObjectView();
268 objectView.object = argVal;
269 var argsRow = this.appendElement_(
270 this.appendElement_(argsCell, 'table'), 'tr');
271 this.appendElement_(argsRow, 'td', argName + ':');
272 this.appendElement_(argsRow, 'td').appendChild(objectView);
278 * Creates and appends a row to |table| that summarizes one or more slices,
279 * or one or more counters. The row has a left-aligned |label| in the first
280 * column, the |duration| of the data in the second, the number of
281 * |occurrences| in the third.
283 * @param {object=} opt_statistics May be undefined, or an object which
284 * contains calculated staistics containing min/max/avg for slices,
285 * or min/max/avg/start/end for counters.
287 appendDataRow: function(table, label, opt_duration, opt_cpuDuration,
288 opt_selfTime, opt_cpuSelfTime, opt_occurences,
289 opt_percentage, opt_statistics,
290 opt_selectionGenerator, opt_inFoot) {
292 var tooltip = undefined;
293 if (opt_statistics) {
294 tooltip = 'Min Duration:\u0009' +
295 tracing.analysis.tsRound(opt_statistics.min) +
296 ' ms \u000DMax Duration:\u0009' +
297 tracing.analysis.tsRound(opt_statistics.max) +
298 ' ms \u000DAvg Duration:\u0009' +
299 tracing.analysis.tsRound(opt_statistics.avg) +
301 tracing.analysis.tsRound(opt_statistics.avg_stddev) + ')';
303 if (opt_statistics.start) {
304 tooltip += '\u000DStart Time:\u0009' +
305 tracing.analysis.tsRound(opt_statistics.start) + ' ms';
307 if (opt_statistics.end) {
308 tooltip += '\u000DEnd Time:\u0009' +
309 tracing.analysis.tsRound(opt_statistics.end) + ' ms';
311 if (opt_statistics.frequency && opt_statistics.frequency_stddev) {
312 tooltip += '\u000DFrequency:\u0009' +
313 tracing.analysis.tsRound(opt_statistics.frequency) +
314 ' occurrences/s (\u03C3 = ' +
315 tracing.analysis.tsRound(opt_statistics.frequency_stddev) + ')';
319 if (table.tfoot || opt_inFoot)
320 var row = this.appendFootRow(table);
322 var row = this.appendBodyRow(table);
325 if (!opt_selectionGenerator) {
326 this.appendTableCellWithTooltip_(table, row, cellNum, label, tooltip);
328 var labelEl = this.appendTableCellWithTooltip_(
329 table, row, cellNum, label, tooltip);
331 labelEl.textContent = '';
333 this.createSelectionChangingLink(label, opt_selectionGenerator,
339 if (opt_duration !== null) {
341 if (opt_duration instanceof Array) {
342 this.appendTableCellWithTooltip_(table, row, cellNum,
343 '[' + opt_duration.join(', ') + ']', tooltip);
345 this.appendTableCellWithTooltip_(table, row, cellNum,
346 tracing.analysis.tsRound(opt_duration), tooltip);
349 this.appendTableCell_(table, row, cellNum, '');
354 if (opt_cpuDuration !== null) {
355 if (opt_cpuDuration != '') {
356 this.appendTableCellWithTooltip_(table, row, cellNum,
357 tracing.analysis.tsRound(opt_cpuDuration), tooltip);
359 this.appendTableCell_(table, row, cellNum, '');
364 if (opt_selfTime !== null) {
366 this.appendTableCellWithTooltip_(table, row, cellNum,
367 tracing.analysis.tsRound(opt_selfTime), tooltip);
369 this.appendTableCell_(table, row, cellNum, '');
374 if (opt_cpuSelfTime !== null) {
375 if (opt_cpuSelfTime) {
376 this.appendTableCellWithTooltip_(table, row, cellNum,
377 tracing.analysis.tsRound(opt_cpuSelfTime), tooltip);
379 this.appendTableCell_(table, row, cellNum, '');
384 if (opt_percentage !== null) {
385 if (opt_percentage) {
386 this.appendTableCellWithTooltip_(table, row, cellNum,
387 opt_percentage, tooltip);
389 this.appendTableCell_(table, row, cellNum, '');
394 if (opt_occurences) {
395 this.appendTableCellWithTooltip_(table, row, cellNum,
396 String(opt_occurences), tooltip);
398 this.appendTableCell_(table, row, cellNum, '');
404 AnalysisResults: AnalysisResults