| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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. | |
| 4 | |
| 5 'use strict'; | |
| 6 | |
| 7 /** | |
| 8 * @fileoverview TimelineView visualizes TRACE_EVENT events using the | |
| 9 * tracing.Timeline component and adds in selection summary and control buttons. | |
| 10 */ | |
| 11 cr.define('tracing', function() { | |
| 12 function tsRound(ts) { | |
| 13 return Math.round(ts * 1000.0) / 1000.0; | |
| 14 } | |
| 15 | |
| 16 /** | |
| 17 * Creates and appends a DOM node of type |tagName| to |parent|. Optionally, | |
| 18 * sets the new node's text to |opt_text|. Returns the newly created node. | |
| 19 */ | |
| 20 function appendElement(parent, tagName, opt_text) { | |
| 21 var n = parent.ownerDocument.createElement(tagName); | |
| 22 parent.appendChild(n); | |
| 23 if (opt_text != undefined) | |
| 24 n.textContent = opt_text; | |
| 25 return n; | |
| 26 } | |
| 27 | |
| 28 /** | |
| 29 * Adds |tagName| to |parent| with className |classname|. Returns | |
| 30 * the newly created node. | |
| 31 */ | |
| 32 function appendElementWithClass(parent, tagName, classname) { | |
| 33 var n = appendElement(parent, tagName); | |
| 34 n.className = classname; | |
| 35 return n; | |
| 36 } | |
| 37 | |
| 38 /** | |
| 39 * Adds |text| to |parent|. | |
| 40 */ | |
| 41 function appendText(parent, text) { | |
| 42 var textNode = parent.ownerDocument.createTextNode(text); | |
| 43 parent.appendChild(textNode); | |
| 44 return textNode; | |
| 45 } | |
| 46 | |
| 47 /** | |
| 48 * Adds a table header to |row| with |text| and className | |
| 49 * |table|.className-header. Returns the newly created node. | |
| 50 */ | |
| 51 function appendTableHeader(table, row, text) { | |
| 52 var th = appendElement(row, 'th', text); | |
| 53 th.className = table.className + '-header'; | |
| 54 return th; | |
| 55 } | |
| 56 | |
| 57 /** | |
| 58 * Adds table cell number |cellnum| to |row| with |text| and | |
| 59 * className |table|.className-col-|cellnum|. Returns the newly | |
| 60 * created node. | |
| 61 */ | |
| 62 function appendTableCell(table, row, cellnum, text) { | |
| 63 var td = appendElement(row, 'td', text); | |
| 64 td.className = table.className + '-col-' + cellnum; | |
| 65 return td; | |
| 66 } | |
| 67 | |
| 68 /** | |
| 69 * Creates and appends a row to |table| with a left-aligned |label] | |
| 70 * header that spans all columns. Returns the newly created nodes. | |
| 71 */ | |
| 72 function appendSummaryHeader(table, label) { | |
| 73 var row = appendElement(table, 'tr'); | |
| 74 var th = appendTableHeader(table, row, label); | |
| 75 return row; | |
| 76 } | |
| 77 | |
| 78 /** | |
| 79 * Creates and appends a row to |table| with a left-aligned |label] | |
| 80 * in the first column and an optional |opt_text| value in the second | |
| 81 * column. Returns the newly created nodes. | |
| 82 */ | |
| 83 function appendSummaryRow(table, label, opt_text) { | |
| 84 var row = appendElement(table, 'tr'); | |
| 85 var td = appendTableCell(table, row, 0, label); | |
| 86 if (opt_text) { | |
| 87 var td = appendTableCell(table, row, 1, opt_text); | |
| 88 } | |
| 89 return row; | |
| 90 } | |
| 91 | |
| 92 /** | |
| 93 * Creates and appends a row to |table| with a left-aligned |label] | |
| 94 * in the first column and a millisecvond |time| value in the second | |
| 95 * column. Returns the newly created nodes. | |
| 96 */ | |
| 97 function appendSummaryRowTime(table, label, time) { | |
| 98 return appendSummaryRow(table, label, tsRound(time) + ' ms'); | |
| 99 } | |
| 100 | |
| 101 /** | |
| 102 * Creates and appends a row to |table| that summarizes one or more slices. | |
| 103 * The row has a left-aligned |label] in the first column, the |duration| | |
| 104 * of the data in the second, the number of |occurrences| in the third. | |
| 105 * Returns the newly created nodes. | |
| 106 */ | |
| 107 function appendSliceRow(table, label, duration, occurences) { | |
| 108 var row = appendElement(table, 'tr'); | |
| 109 var td = appendTableCell(table, row, 0, label); | |
| 110 var td = appendTableCell(table, row, 1, tsRound(duration) + ' ms'); | |
| 111 var td = appendTableCell(table, row, 2, | |
| 112 String(occurences) + ' occurences'); | |
| 113 return row; | |
| 114 } | |
| 115 | |
| 116 /** | |
| 117 * Converts the selection to a tabular summary display and appends | |
| 118 * the newly created elements to |parent|. Returns the new elements. | |
| 119 */ | |
| 120 function createSummaryElementForSelection(parent, selection) { | |
| 121 var sliceHits = selection.getSliceHits(); | |
| 122 var counterSampleHits = selection.getCounterSampleHits(); | |
| 123 | |
| 124 if (sliceHits.length == 1) { | |
| 125 var slice = sliceHits[0].slice; | |
| 126 | |
| 127 var table = appendElementWithClass(parent, 'table', 'timeline-slice'); | |
| 128 | |
| 129 appendSummaryHeader(table, 'Selected item:'); | |
| 130 | |
| 131 appendSummaryRow(table, 'Title', slice.title); | |
| 132 appendSummaryRowTime(table, 'Start', slice.start); | |
| 133 appendSummaryRowTime(table, 'Duration', slice.duration); | |
| 134 if (slice.durationInUserTime) | |
| 135 appendSummaryRowTime(table, 'Duration (U)', slice.durationInUserTime); | |
| 136 | |
| 137 var n = 0; | |
| 138 for (var argName in slice.args) { | |
| 139 n += 1; | |
| 140 } | |
| 141 if (n > 0) { | |
| 142 appendSummaryRow(table, 'Args'); | |
| 143 for (var argName in slice.args) { | |
| 144 var argVal = slice.args[argName]; | |
| 145 // TODO(sleffler) use span instead? | |
| 146 appendSummaryRow(table, ' ' + argName, argVal); | |
| 147 } | |
| 148 } | |
| 149 } else if (sliceHits.length > 1) { | |
| 150 var tsLo = sliceHits.range.min; | |
| 151 var tsHi = sliceHits.range.max; | |
| 152 | |
| 153 // compute total sliceHits duration | |
| 154 var titles = sliceHits.map(function(i) { return i.slice.title; }); | |
| 155 | |
| 156 var slicesByTitle = {}; | |
| 157 for (var i = 0; i < sliceHits.length; i++) { | |
| 158 var slice = sliceHits[i].slice; | |
| 159 if (!slicesByTitle[slice.title]) | |
| 160 slicesByTitle[slice.title] = { | |
| 161 slices: [] | |
| 162 }; | |
| 163 slicesByTitle[slice.title].slices.push(slice); | |
| 164 } | |
| 165 | |
| 166 var table = appendElementWithClass(parent, 'table', 'timeline-slices'); | |
| 167 | |
| 168 appendSummaryHeader(table, 'Slices:'); | |
| 169 | |
| 170 var totalDuration = 0; | |
| 171 for (var sliceGroupTitle in slicesByTitle) { | |
| 172 var sliceGroup = slicesByTitle[sliceGroupTitle]; | |
| 173 var duration = 0; | |
| 174 for (i = 0; i < sliceGroup.slices.length; i++) | |
| 175 duration += sliceGroup.slices[i].duration; | |
| 176 totalDuration += duration; | |
| 177 | |
| 178 appendSliceRow(table, sliceGroupTitle, duration, | |
| 179 sliceGroup.slices.length); | |
| 180 } | |
| 181 | |
| 182 appendSliceRow(table, '*Totals', totalDuration, sliceHits.length); | |
| 183 | |
| 184 appendElement(table, 'p'); // TODO(sleffler) proper vertical space? | |
| 185 appendSummaryRowTime(table, 'Selection start', tsLo); | |
| 186 appendSummaryRowTime(table, 'Selection extent', tsHi - tsLo); | |
| 187 } | |
| 188 | |
| 189 if (counterSampleHits.length == 1) { | |
| 190 var hit = counterSampleHits[0]; | |
| 191 var ctr = hit.counter; | |
| 192 var sampleIndex = hit.sampleIndex; | |
| 193 var values = []; | |
| 194 for (var i = 0; i < ctr.numSeries; ++i) | |
| 195 values.push(ctr.samples[ctr.numSeries * sampleIndex + i]); | |
| 196 | |
| 197 var table = appendElementWithClass(parent, 'table', 'timeline-counter'); | |
| 198 | |
| 199 appendSummaryHeader(table, 'Selected counter:'); | |
| 200 | |
| 201 appendSummaryRow(table, 'Title', ctr.name); | |
| 202 appendSummaryRowTime(table, 'Timestamp', ctr.timestamps[sampleIndex]); | |
| 203 if (ctr.numSeries > 1) | |
| 204 appendSummaryRow(table, 'Values', values.join('\n')); | |
| 205 else | |
| 206 appendSummaryRow(table, 'Value', values.join('\n')); | |
| 207 } else if (counterSampleHits.length > 1 && sliceHits.length == 0) { | |
| 208 appendText(parent, 'Analysis of multiple counters is not yet' + | |
| 209 'implemented. Pick a single counter.'); | |
| 210 } | |
| 211 } | |
| 212 | |
| 213 var TimelineAnalysisView = cr.ui.define('div'); | |
| 214 | |
| 215 TimelineAnalysisView.prototype = { | |
| 216 __proto__: HTMLDivElement.prototype, | |
| 217 | |
| 218 decorate: function() { | |
| 219 this.className = 'timeline-analysis'; | |
| 220 }, | |
| 221 | |
| 222 set selection(selection) { | |
| 223 this.textContent = ''; | |
| 224 createSummaryElementForSelection(this, selection); | |
| 225 } | |
| 226 }; | |
| 227 | |
| 228 return { | |
| 229 TimelineAnalysisView: TimelineAnalysisView, | |
| 230 }; | |
| 231 }); | |
| OLD | NEW |