OLD | NEW |
| (Empty) |
1 <html> | |
2 <head> | |
3 <style> | |
4 body { | |
5 font-family: sans-serif; | |
6 } | |
7 div#output { | |
8 cursor: pointer; | |
9 } | |
10 div#switcher { | |
11 cursor: pointer; | |
12 } | |
13 div#switcher a { | |
14 border-top: 1px solid black; | |
15 border-left: 1px solid black; | |
16 padding-left: 0.5em; | |
17 padding-right: 0.5em; | |
18 } | |
19 canvas.plot { | |
20 border: 1px solid black; | |
21 } | |
22 div.plot-coordinates { | |
23 font-family: monospace; | |
24 } | |
25 iframe { | |
26 display: none; | |
27 width: 100%; | |
28 height: 100%; | |
29 border: none; | |
30 } | |
31 div.selector { | |
32 border: solid 1px black; | |
33 cursor: pointer; | |
34 padding-left: 0.3em; | |
35 background-color: white; | |
36 } | |
37 div.selector:hover { | |
38 background-color: rgb(200,200,250); | |
39 } | |
40 div.selected { | |
41 border-left: none; | |
42 } | |
43 div#selectors { | |
44 width: 80px; | |
45 display: none; | |
46 } | |
47 .latest { | |
48 font-weight: bold; | |
49 color: rgb(60, 0, 240); | |
50 } | |
51 .reference { | |
52 font-weight: bold; | |
53 color: rgb(110, 50, 35); | |
54 } | |
55 </style> | |
56 <script src="js/common.js"></script> | |
57 <script src="js/coordinates.js"></script> | |
58 <script src="js/plotter.js"></script> | |
59 <script src="config.js"></script> | |
60 <script> | |
61 // TODO(pjohnson): Much of this code is common to all of the performance | |
62 // reports. It would be nice to refactor the shared code into a common place. | |
63 | |
64 document.title = Config.title; | |
65 | |
66 String.prototype.startsWith = function(s) { | |
67 return this.indexOf(s) == 0; | |
68 } | |
69 | |
70 function strcmp(a, b) { | |
71 return a < b ? -1 : (a > b ? 1 : 0); | |
72 } | |
73 | |
74 // Hard-coded default trace to show if none are specified. | |
75 var defaultTrace = 'c:V8.OsMemoryAllocated'; | |
76 | |
77 var params = ParseParams(); | |
78 if (!('history' in params)) { | |
79 params.history = 150; | |
80 } | |
81 if (!('trace' in params)) { | |
82 params.trace = defaultTrace; | |
83 } | |
84 | |
85 function goTo(trace) { | |
86 params.trace = trace; | |
87 if (params.trace == '' && params.trace != '0') { | |
88 params.trace = defaultTrace; | |
89 } | |
90 window.location.href = MakeURL(params); | |
91 } | |
92 | |
93 function goToFromEvent(e) { | |
94 var trace = e.target.value; | |
95 return goTo(trace); | |
96 } | |
97 | |
98 var didUpdatePositionDetails = false; | |
99 | |
100 function unitsForTrace() { | |
101 if ('trace' in params) { | |
102 if (params.trace.startsWith("t:")) { | |
103 return 'msec'; | |
104 } | |
105 } | |
106 return 'thing-a-ma-bobs'; | |
107 } | |
108 | |
109 function timing(dict) { | |
110 return parseFloat(dict['time']); | |
111 } | |
112 | |
113 function jsonToJs(data) { | |
114 return eval('(' + data + ')') | |
115 } | |
116 | |
117 function addSelectionTabs(rows) { | |
118 if (rows.length > 0 && rows[0].length > 0) { | |
119 data = jsonToJs(rows[0]); | |
120 tabs = []; | |
121 | |
122 for (var clNumber in data) { | |
123 for (var testName in data[clNumber]['latest']) { | |
124 tabs.push(testName); | |
125 } | |
126 } | |
127 | |
128 tabs.sort(sortTraces); | |
129 | |
130 initPlotSwitcher(tabs); | |
131 } | |
132 } | |
133 | |
134 function appendTestResult(dataRows, currentData, testType, testName) { | |
135 if (!dataRows[testType]) { | |
136 dataRows[testType] = []; | |
137 } | |
138 | |
139 mean = parseFloat(currentData[testName]['mean']); | |
140 stdd = parseFloat(currentData[testName]['stdd']); | |
141 dataRows[testType].push([mean, stdd]); | |
142 } | |
143 | |
144 function onSummaryReceived(data) { | |
145 var rows = data.split('\n'); | |
146 addSelectionTabs(rows); | |
147 var clNumbers = []; | |
148 var dataRows = {}; | |
149 | |
150 for (var i = 0; i < rows.length; i++) { | |
151 if (rows[i].length < 1) { | |
152 break; | |
153 } | |
154 if (i > params.history) { // limit by history | |
155 break; | |
156 } | |
157 | |
158 clData = jsonToJs(rows[i]); | |
159 | |
160 for (var clNumber in clData) { | |
161 clNumbers.push(clNumber); | |
162 | |
163 for (var testType in clData[clNumber]) { | |
164 var currentData = clData[clNumber][testType]; | |
165 // Specific selection that is defined in params.trace. | |
166 if (currentData[params.trace]) { | |
167 appendTestResult(dataRows, currentData, testType, params.trace); | |
168 } | |
169 } | |
170 } | |
171 } | |
172 | |
173 // Don't depend on any special for-in order. | |
174 var keys = []; | |
175 for (var key in dataRows) { | |
176 keys.push(key); | |
177 } | |
178 keys.sort(); | |
179 | |
180 var dataGrid = []; | |
181 for (var i = 0; i < keys.length; i++) { | |
182 var key = keys[i]; | |
183 dataGrid.push(dataRows[key].reverse()); | |
184 } | |
185 clNumbers.reverse(); | |
186 var plotter = new Plotter(clNumbers, dataGrid, Config.dataDescription, | |
187 unitsForTrace(), document.getElementById("output")); | |
188 plotter.onclick = handlePlotClicked; | |
189 plotter.plot(); | |
190 | |
191 return; | |
192 } | |
193 | |
194 function handlePlotClicked(cl, value, fuzz, e) { | |
195 document.getElementById('view-change'). | |
196 setAttribute('src', Config.changeLinkPrefix + cl); | |
197 | |
198 if (!didUpdatePositionDetails) { | |
199 updatePositionDetails(); | |
200 didUpdatePositionDetails = true; | |
201 } | |
202 } | |
203 | |
204 function updatePositionDetails() { | |
205 var output = document.getElementById("output"); | |
206 var win_height = window.innerHeight; | |
207 var details = document.getElementById("views"); | |
208 var views = document.getElementById("views"); | |
209 var selectors = document.getElementById("selectors"); | |
210 selectors.style.display = "block"; | |
211 | |
212 var views_width = output.offsetWidth - selectors.offsetWidth; | |
213 | |
214 views.style.border = "1px solid black"; | |
215 views.style.width = views_width + "px"; | |
216 views.style.height = (win_height - output.offsetHeight - | |
217 output.offsetTop - 30) + "px"; | |
218 | |
219 selectors.style.position = "absolute"; | |
220 selectors.style.left = (views.offsetLeft + views_width + 1) + "px"; | |
221 selectors.style.top = views.offsetTop + "px"; | |
222 | |
223 viewCl(); | |
224 } | |
225 | |
226 function viewCl(target) { | |
227 document.getElementById("view-change").style.display = "block"; | |
228 } | |
229 | |
230 function addOption(selectBox, text, value) { | |
231 var option = document.createElement("option"); | |
232 option.text = text; | |
233 option.value = value; | |
234 selectBox.add(option); | |
235 } | |
236 | |
237 function initPlotSwitcher(tabs) { | |
238 var selectBox = document.getElementById("switcher"); | |
239 | |
240 if (selectBox.attachEvent) { | |
241 selectBox.attachEvent("onchange", goToFromEvent); | |
242 } else { | |
243 selectBox.addEventListener("change", goToFromEvent, false); | |
244 } | |
245 | |
246 var selectedIndex = 0; | |
247 for (var i = 0; i < tabs.length; i++) { | |
248 if (tabs[i] == params.trace) { | |
249 selectedIndex = i; | |
250 } | |
251 addOption(selectBox, tabs[i], tabs[i]); | |
252 } | |
253 selectBox.selectedIndex = selectedIndex; | |
254 | |
255 if ('lookout' in params) { | |
256 switcher.style.display = "none"; | |
257 details.style.display = "none"; | |
258 header_text.style.display = "none"; | |
259 explain.style.display = "none"; | |
260 selection.style.display = "none"; | |
261 } else { | |
262 document.getElementById("header_lookout").style.display = "none"; | |
263 } | |
264 } | |
265 | |
266 function log(data) { | |
267 document.getElementById('log').appendChild( | |
268 document.createTextNode(data + '\n')); | |
269 } | |
270 | |
271 function init() { | |
272 Fetch("summary.dat", onSummaryReceived); | |
273 } | |
274 | |
275 // Used to sort by trace name, ignoring the "c:" and "t:" prefixes. | |
276 // This allows related traces (such as a timer and a counter for the same | |
277 // thing) to appear next to each other in the drop-down box. | |
278 function sortTraces(a, b) { | |
279 function getMeat(trace) { | |
280 if (trace.startsWith("c:") || trace.startsWith("t:")) { | |
281 trace = trace.substring(2); | |
282 } | |
283 return trace; | |
284 } | |
285 | |
286 var aMeat = getMeat(a); | |
287 var bMeat = getMeat(b); | |
288 var meatCmp = strcmp(aMeat, bMeat); | |
289 | |
290 if (meatCmp != 0) { | |
291 return meatCmp; | |
292 } | |
293 return strcmp(a, b); | |
294 } | |
295 | |
296 window.addEventListener("load", init, false); | |
297 </script> | |
298 </head> | |
299 <body> | |
300 <p> | |
301 <div id="header_lookout" align="center"> | |
302 <font style='color: #0066FF; font-family: Arial, serif;font-size: 20pt; font-w
eight: bold;'> | |
303 <script>document.write(Config.title);</script> | |
304 </font> | |
305 </div> | |
306 <div id="header_text"> | |
307 Builds generated by the | |
308 <script> | |
309 document.write('<a href="' + Config.builderLink + '">' + Config.builder + '</a>'
); | |
310 </script> | |
311 build slave are run through the | |
312 <script> | |
313 document.write('<b>' + Config.title + '</b>'); | |
314 </script> | |
315 and the results of that test are charted here. | |
316 </div> | |
317 </p> | |
318 <p style="font-size: 0.75em; font-style: italic; color: rgb(100,100,100)"> | |
319 <div id="explain"> | |
320 The vertical axis is the count or time and the horizontal axis is the | |
321 change-list for the build being tested.<br /><br /> | |
322 <span class="latest">This color</span> is for the latest build, and | |
323 <span class="reference">this color</span> is for the reference build. | |
324 </div> | |
325 </p> | |
326 <select id="switcher"> | |
327 | |
328 </select> | |
329 <div id="output"></div> | |
330 <div id="details"> | |
331 <div id="views"> | |
332 <iframe id="view-change"></iframe> | |
333 <iframe id="view-pages"></iframe> | |
334 </div> | |
335 <div id="selectors"> | |
336 <div class="selector" onclick="viewCl()">CL</div> | |
337 </div> | |
338 </div> | |
339 <pre id="log"></pre> | |
340 </body> | |
341 </html> | |
OLD | NEW |