OLD | NEW |
(Empty) | |
| 1 <!DOCTYPE html> |
| 2 <html> |
| 3 <head> |
| 4 <title>Telemetry Performance Test Results</title> |
| 5 <style type="text/css"> |
| 6 |
| 7 section { |
| 8 background: white; |
| 9 padding: 10px; |
| 10 position: relative; |
| 11 } |
| 12 |
| 13 .time-plots { |
| 14 padding-left: 25px; |
| 15 } |
| 16 |
| 17 .time-plots > div { |
| 18 display: inline-block; |
| 19 width: 90px; |
| 20 height: 40px; |
| 21 margin-right: 10px; |
| 22 } |
| 23 |
| 24 section h1 { |
| 25 text-align: center; |
| 26 font-size: 1em; |
| 27 } |
| 28 |
| 29 section .tooltip { |
| 30 position: absolute; |
| 31 text-align: center; |
| 32 background: #ffcc66; |
| 33 border-radius: 5px; |
| 34 padding: 0px 5px; |
| 35 } |
| 36 |
| 37 body { |
| 38 padding: 0px; |
| 39 margin: 0px; |
| 40 font-family: sans-serif; |
| 41 } |
| 42 |
| 43 table { |
| 44 background: white; |
| 45 width: 100%; |
| 46 } |
| 47 |
| 48 table, td, th { |
| 49 border-collapse: collapse; |
| 50 padding: 5px; |
| 51 white-space: nowrap; |
| 52 } |
| 53 |
| 54 tr.even { |
| 55 background: #f6f6f6; |
| 56 } |
| 57 |
| 58 table td { |
| 59 position: relative; |
| 60 font-family: monospace; |
| 61 } |
| 62 |
| 63 th, td { |
| 64 cursor: pointer; |
| 65 cursor: hand; |
| 66 } |
| 67 |
| 68 th { |
| 69 background: #e6eeee; |
| 70 background: -webkit-gradient(linear, left top, left bottom, from(rgb(244, 24
4, 244)), to(rgb(217, 217, 217))); |
| 71 border: 1px solid #ccc; |
| 72 } |
| 73 |
| 74 th:after { |
| 75 content: ' \25B8'; |
| 76 } |
| 77 |
| 78 th.headerSortUp:after { |
| 79 content: ' \25BE'; |
| 80 } |
| 81 |
| 82 th.headerSortDown:after { |
| 83 content: ' \25B4'; |
| 84 } |
| 85 |
| 86 td.comparison, td.result { |
| 87 text-align: right; |
| 88 } |
| 89 |
| 90 td.better { |
| 91 color: #6c6; |
| 92 } |
| 93 |
| 94 td.worse { |
| 95 color: #c66; |
| 96 } |
| 97 |
| 98 td.missing { |
| 99 text-align: center; |
| 100 } |
| 101 |
| 102 .checkbox { |
| 103 display: inline-block; |
| 104 background: #eee; |
| 105 background: -webkit-gradient(linear, left bottom, left top, from(rgb(220, 22
0, 220)), to(rgb(200, 200, 200))); |
| 106 border: inset 1px #ddd; |
| 107 border-radius: 5px; |
| 108 margin: 10px; |
| 109 font-size: small; |
| 110 cursor: pointer; |
| 111 cursor: hand; |
| 112 -webkit-user-select: none; |
| 113 font-weight: bold; |
| 114 } |
| 115 |
| 116 .checkbox span { |
| 117 display: inline-block; |
| 118 line-height: 100%; |
| 119 padding: 5px 8px; |
| 120 border: outset 1px transparent; |
| 121 } |
| 122 |
| 123 .checkbox .checked { |
| 124 background: #e6eeee; |
| 125 background: -webkit-gradient(linear, left top, left bottom, from(rgb(255, 25
5, 255)), to(rgb(235, 235, 235))); |
| 126 border: outset 1px #eee; |
| 127 border-radius: 5px; |
| 128 } |
| 129 |
| 130 </style> |
| 131 </head> |
| 132 <body onload="init()"> |
| 133 <div style="padding: 0 10px; white-space: nowrap;"> |
| 134 Result <span id="time-memory" class="checkbox"><span class="checked">Time</span>
<span>Memory</span></span> |
| 135 Reference <span id="reference" class="checkbox"></span> |
| 136 Run Telemetry with --reset-html-results to clear all runs |
| 137 </div> |
| 138 <table id="container"></table> |
| 139 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"><
/script> |
| 140 <script> |
| 141 %plugins% |
| 142 </script> |
| 143 <script> |
| 144 function TestResult(metric, values, associatedRun) { |
| 145 if (values[0] instanceof Array) { |
| 146 var flattenedValues = []; |
| 147 for (var i = 0; i < values.length; i++) |
| 148 flattenedValues = flattenedValues.concat(values[i]); |
| 149 values = flattenedValues; |
| 150 } |
| 151 |
| 152 this.test = function () { return metric; } |
| 153 this.values = function () { return values.map(function (value) { return metr
ic.scalingFactor() * value; }); } |
| 154 this.unscaledMean = function () { return Statistics.sum(values) / values.len
gth; } |
| 155 this.mean = function () { return metric.scalingFactor() * this.unscaledMean(
); } |
| 156 this.min = function () { return metric.scalingFactor() * Statistics.min(valu
es); } |
| 157 this.max = function () { return metric.scalingFactor() * Statistics.max(valu
es); } |
| 158 this.confidenceIntervalDelta = function () { |
| 159 return metric.scalingFactor() * Statistics.confidenceIntervalDelta(0.95,
values.length, |
| 160 Statistics.sum(values), Statistics.squareSum(values)); |
| 161 } |
| 162 this.confidenceIntervalDeltaRatio = function () { return this.confidenceInte
rvalDelta() / this.mean(); } |
| 163 this.percentDifference = function(other) { return (other.unscaledMean() - th
is.unscaledMean()) / this.unscaledMean(); } |
| 164 this.isStatisticallySignificant = function (other) { |
| 165 var diff = Math.abs(other.mean() - this.mean()); |
| 166 return diff > this.confidenceIntervalDelta() && diff > other.confidenceI
ntervalDelta(); |
| 167 } |
| 168 this.run = function () { return associatedRun; } |
| 169 } |
| 170 |
| 171 function TestRun(entry) { |
| 172 this.description = function () { return entry['description']; } |
| 173 this.revision = function () { return entry['revision']; } |
| 174 this.label = function () { |
| 175 var label = 'r' + this.revision(); |
| 176 if (this.description()) |
| 177 label += ' ‐ ' + this.description(); |
| 178 return label; |
| 179 } |
| 180 } |
| 181 |
| 182 function PerfTestMetric(name, metric, unit, isImportant) { |
| 183 var testResults = []; |
| 184 var cachedUnit = null; |
| 185 var cachedScalingFactor = null; |
| 186 |
| 187 // We can't do this in TestResult because all results for each test need to
share the same unit and the same scaling factor. |
| 188 function computeScalingFactorIfNeeded() { |
| 189 // FIXME: We shouldn't be adjusting units on every test result. |
| 190 // We can only do this on the first test. |
| 191 if (!testResults.length || cachedUnit) |
| 192 return; |
| 193 |
| 194 var mean = testResults[0].unscaledMean(); // FIXME: We should look at al
l values. |
| 195 var kilo = unit == 'bytes' ? 1024 : 1000; |
| 196 if (mean > 10 * kilo * kilo && unit != 'ms') { |
| 197 cachedScalingFactor = 1 / kilo / kilo; |
| 198 cachedUnit = 'M ' + unit; |
| 199 } else if (mean > 10 * kilo) { |
| 200 cachedScalingFactor = 1 / kilo; |
| 201 cachedUnit = unit == 'ms' ? 's' : ('K ' + unit); |
| 202 } else { |
| 203 cachedScalingFactor = 1; |
| 204 cachedUnit = unit; |
| 205 } |
| 206 } |
| 207 |
| 208 this.name = function () { return name + ':' + metric; } |
| 209 this.isImportant = isImportant; |
| 210 this.isMemoryTest = function () { |
| 211 return (unit == 'kb' || |
| 212 unit == 'KB' || |
| 213 unit == 'MB' || |
| 214 unit == 'bytes'); |
| 215 } |
| 216 this.addResult = function (newResult) { |
| 217 testResults.push(newResult); |
| 218 cachedUnit = null; |
| 219 cachedScalingFactor = null; |
| 220 } |
| 221 this.results = function () { return testResults; } |
| 222 this.scalingFactor = function() { |
| 223 computeScalingFactorIfNeeded(); |
| 224 return cachedScalingFactor; |
| 225 } |
| 226 this.unit = function () { |
| 227 computeScalingFactorIfNeeded(); |
| 228 return cachedUnit; |
| 229 } |
| 230 this.biggerIsBetter = function () { |
| 231 if (window.unitToBiggerIsBetter == undefined) { |
| 232 window.unitToBiggerIsBetter = {}; |
| 233 var units = JSON.parse(document.getElementById('units-json').textCon
tent); |
| 234 for (var unit in units) { |
| 235 if (units[unit].improvement_direction == 'up') { |
| 236 window.unitToBiggerIsBetter[unit] = true; |
| 237 } |
| 238 } |
| 239 } |
| 240 return window.unitToBiggerIsBetter[unit]; |
| 241 } |
| 242 } |
| 243 |
| 244 var plotColor = 'rgb(230,50,50)'; |
| 245 var subpointsPlotOptions = { |
| 246 lines: {show:true, lineWidth: 0}, |
| 247 color: plotColor, |
| 248 points: {show: true, radius: 1}, |
| 249 bars: {show: false}}; |
| 250 |
| 251 var mainPlotOptions = { |
| 252 xaxis: { |
| 253 min: -0.5, |
| 254 tickSize: 1, |
| 255 }, |
| 256 crosshair: { mode: 'y' }, |
| 257 series: { shadowSize: 0 }, |
| 258 bars: {show: true, align: 'center', barWidth: 0.5}, |
| 259 lines: { show: false }, |
| 260 points: { show: true }, |
| 261 grid: { |
| 262 borderWidth: 1, |
| 263 borderColor: '#ccc', |
| 264 backgroundColor: '#fff', |
| 265 hoverable: true, |
| 266 autoHighlight: false, |
| 267 } |
| 268 }; |
| 269 |
| 270 var timePlotOptions = { |
| 271 yaxis: { show: false }, |
| 272 xaxis: { show: false }, |
| 273 lines: { show: true }, |
| 274 grid: { borderWidth: 1, borderColor: '#ccc' }, |
| 275 colors: [ plotColor ] |
| 276 }; |
| 277 |
| 278 function createPlot(container, test) { |
| 279 var section = $('<section><div class="plot"></div><div class="time-plots"></
div>' |
| 280 + '<span class="tooltip"></span></section>'); |
| 281 section.children('.plot').css({'width': (100 * test.results().length + 25) +
'px', 'height': '300px'}); |
| 282 $(container).append(section); |
| 283 |
| 284 var plotContainer = section.children('.plot'); |
| 285 var minIsZero = true; |
| 286 attachPlot(test, plotContainer, minIsZero); |
| 287 |
| 288 attachTimePlots(test, section.children('.time-plots')); |
| 289 |
| 290 var tooltip = section.children('.tooltip'); |
| 291 plotContainer.bind('plothover', function (event, position, item) { |
| 292 if (item) { |
| 293 var postfix = item.series.id ? ' (' + item.series.id + ')' : ''; |
| 294 tooltip.html(item.datapoint[1].toPrecision(4) + postfix); |
| 295 var sectionOffset = $(section).offset(); |
| 296 tooltip.css({left: item.pageX - sectionOffset.left - tooltip.outerWi
dth() / 2, top: item.pageY - sectionOffset.top + 10}); |
| 297 tooltip.fadeIn(200); |
| 298 } else |
| 299 tooltip.hide(); |
| 300 }); |
| 301 plotContainer.mouseout(function () { |
| 302 tooltip.hide(); |
| 303 }); |
| 304 plotContainer.click(function (event) { |
| 305 event.preventDefault(); |
| 306 minIsZero = !minIsZero; |
| 307 attachPlot(test, plotContainer, minIsZero); |
| 308 }); |
| 309 |
| 310 return section; |
| 311 } |
| 312 |
| 313 function attachTimePlots(test, container) { |
| 314 var results = test.results(); |
| 315 var attachedPlot = false; |
| 316 for (var i = 0; i < results.length; i++) { |
| 317 container.append('<div></div>'); |
| 318 var values = results[i].values(); |
| 319 if (!values) |
| 320 continue; |
| 321 attachedPlot = true; |
| 322 |
| 323 $.plot(container.children().last(), [values.map(function (value, index)
{ return [index, value]; })], |
| 324 $.extend(true, {}, timePlotOptions, {yaxis: {min: Math.min.apply(Mat
h, values) * 0.9, max: Math.max.apply(Math, values) * 1.1}, |
| 325 xaxis: {min: -0.5, max: values.length - 0.5}})); |
| 326 } |
| 327 if (!attachedPlot) |
| 328 container.children().remove(); |
| 329 } |
| 330 |
| 331 function attachPlot(test, plotContainer, minIsZero) { |
| 332 var results = test.results(); |
| 333 |
| 334 var values = results.reduce(function (values, result, index) { |
| 335 var newValues = result.values(); |
| 336 return newValues ? values.concat(newValues.map(function (value) { return
[index, value]; })) : values; |
| 337 }, []); |
| 338 |
| 339 var plotData = [$.extend(true, {}, subpointsPlotOptions, {data: values})]; |
| 340 plotData.push({id: 'μ', data: results.map(function (result, index) { retu
rn [index, result.mean()]; }), color: plotColor}); |
| 341 |
| 342 var overallMax = Statistics.max(results.map(function (result, index) { retur
n result.max(); })); |
| 343 var overallMin = Statistics.min(results.map(function (result, index) { retur
n result.min(); })); |
| 344 var margin = (overallMax - overallMin) * 0.1; |
| 345 var currentPlotOptions = $.extend(true, {}, mainPlotOptions, {yaxis: { |
| 346 min: minIsZero ? 0 : overallMin - margin, |
| 347 max: minIsZero ? overallMax * 1.1 : overallMax + margin}}); |
| 348 |
| 349 currentPlotOptions.xaxis.max = results.length - 0.5; |
| 350 currentPlotOptions.xaxis.ticks = results.map(function (result, index) { retu
rn [index, result.run().label()]; }); |
| 351 |
| 352 $.plot(plotContainer, plotData, currentPlotOptions); |
| 353 } |
| 354 |
| 355 function toFixedWidthPrecision(value) { |
| 356 var decimal = value.toFixed(2); |
| 357 return decimal; |
| 358 } |
| 359 |
| 360 function formatPercentage(fraction) { |
| 361 var percentage = fraction * 100; |
| 362 return (fraction * 100).toFixed(2) + '%'; |
| 363 } |
| 364 |
| 365 function createTable(tests, runs, shouldIgnoreMemory, referenceIndex) { |
| 366 $('#container').html('<thead><tr><th>Test</th><th>Unit</th>' + runs.map(func
tion (run, index) { |
| 367 return '<th colspan="' + (index == referenceIndex ? 2 : 3) + '" class="{
sorter: \'comparison\'}">' + run.label() + '</th>'; |
| 368 }).reduce(function (markup, cell) { return markup + cell; }, '') + '</tr></h
ead><tbody></tbody>'); |
| 369 |
| 370 var testNames = []; |
| 371 for (testName in tests) |
| 372 testNames.push(testName); |
| 373 |
| 374 testNames.sort().map(function (testName) { |
| 375 var test = tests[testName]; |
| 376 if (test.isMemoryTest() != shouldIgnoreMemory) |
| 377 createTableRow(runs, test, referenceIndex); |
| 378 }); |
| 379 |
| 380 $('#container').tablesorter({widgets: ['zebra']}); |
| 381 } |
| 382 |
| 383 function linearRegression(points) { |
| 384 // Implement http://www.easycalculation.com/statistics/learn-correlation.php
. |
| 385 // x = magnitude |
| 386 // y = iterations |
| 387 var sumX = 0; |
| 388 var sumY = 0; |
| 389 var sumXSquared = 0; |
| 390 var sumYSquared = 0; |
| 391 var sumXTimesY = 0; |
| 392 |
| 393 for (var i = 0; i < points.length; i++) { |
| 394 var x = i; |
| 395 var y = points[i]; |
| 396 sumX += x; |
| 397 sumY += y; |
| 398 sumXSquared += x * x; |
| 399 sumYSquared += y * y; |
| 400 sumXTimesY += x * y; |
| 401 } |
| 402 |
| 403 var r = (points.length * sumXTimesY - sumX * sumY) / |
| 404 Math.sqrt((points.length * sumXSquared - sumX * sumX) * |
| 405 (points.length * sumYSquared - sumY * sumY)); |
| 406 |
| 407 if (isNaN(r) || r == Math.Infinity) |
| 408 r = 0; |
| 409 |
| 410 var slope = (points.length * sumXTimesY - sumX * sumY) / (points.length * su
mXSquared - sumX * sumX); |
| 411 var intercept = sumY / points.length - slope * sumX / points.length; |
| 412 return {slope: slope, intercept: intercept, rSquared: r * r}; |
| 413 } |
| 414 |
| 415 var warningSign = '<svg viewBox="0 0 100 100" style="width: 18px; height: 18px;
vertical-align: bottom;" version="1.1">' |
| 416 + '<polygon fill="red" points="50,10 90,80 10,80 50,10" stroke="red" stroke-
width="10" stroke-linejoin="round" />' |
| 417 + '<polygon fill="white" points="47,30 48,29, 50, 28.7, 52,29 53,30 50,60" s
troke="white" stroke-width="10" stroke-linejoin="round" />' |
| 418 + '<circle cx="50" cy="73" r="6" fill="white" />' |
| 419 + '</svg>'; |
| 420 |
| 421 function createTableRow(runs, test, referenceIndex) { |
| 422 var tableRow = $('<tr><td class="test"' + (test.isImportant ? ' style="font-
weight:bold"' : '') + '>' + test.name() + '</td><td class="unit">' + test.unit()
+ '</td></tr>'); |
| 423 |
| 424 function markupForRun(result, referenceResult) { |
| 425 var comparisonCell = ''; |
| 426 var hiddenValue = ''; |
| 427 var shouldCompare = result !== referenceResult; |
| 428 if (shouldCompare && referenceResult) { |
| 429 var percentDifference = referenceResult.percentDifference(result); |
| 430 var better = test.biggerIsBetter() ? percentDifference > 0 : percent
Difference < 0; |
| 431 var comparison = ''; |
| 432 var className = 'comparison'; |
| 433 if (referenceResult.isStatisticallySignificant(result)) { |
| 434 comparison = formatPercentage(Math.abs(percentDifference)) + (be
tter ? ' Better' : ' Worse '); |
| 435 className += better ? ' better' : ' worse'; |
| 436 } |
| 437 hiddenValue = '<span style="display: none">|' + comparison + '</span
>'; |
| 438 comparisonCell = '<td class="' + className + '">' + comparison + '</
td>'; |
| 439 } else if (shouldCompare) |
| 440 comparisonCell = '<td class="comparison"></td>'; |
| 441 |
| 442 var values = result.values(); |
| 443 var warning = ''; |
| 444 var regressionAnalysis = ''; |
| 445 if (values && values.length > 3) { |
| 446 regressionResult = linearRegression(values); |
| 447 regressionAnalysis = 'slope=' + toFixedWidthPrecision(regressionResu
lt.slope) |
| 448 + ', R^2=' + toFixedWidthPrecision(regressionResult.rSquared); |
| 449 if (regressionResult.rSquared > 0.6 && Math.abs(regressionResult.slo
pe) > 0.01) { |
| 450 warning = ' <span class="regression-warning" title="Detected a t
ime dependency with ' + regressionAnalysis + '">' + warningSign + ' </span>'; |
| 451 } |
| 452 } |
| 453 |
| 454 var statistics = 'σ=' + toFixedWidthPrecision(result.confidenceInt
ervalDelta()) + ', min=' + toFixedWidthPrecision(result.min()) |
| 455 + ', max=' + toFixedWidthPrecision(result.max()) + '\n' + regression
Analysis; |
| 456 |
| 457 // Tablesorter doesn't know about the second cell so put the comparison
in the invisible element. |
| 458 return '<td class="result" title="' + statistics + '">' + toFixedWidthPr
ecision(result.mean()) + hiddenValue |
| 459 + '</td><td class="confidenceIntervalDelta" title="' + statistics +
'">± ' |
| 460 + formatPercentage(result.confidenceIntervalDeltaRatio()) + warning
+ '</td>' + comparisonCell; |
| 461 } |
| 462 |
| 463 function markupForMissingRun(isReference) { |
| 464 return '<td colspan="' + (isReference ? 2 : 3) + '" class="missing">Miss
ing</td>'; |
| 465 } |
| 466 |
| 467 var runIndex = 0; |
| 468 var results = test.results(); |
| 469 var referenceResult = undefined; |
| 470 var resultIndexMap = {}; |
| 471 for (var i = 0; i < results.length; i++) { |
| 472 while (runs[runIndex] !== results[i].run()) |
| 473 runIndex++; |
| 474 if (runIndex == referenceIndex) |
| 475 referenceResult = results[i]; |
| 476 resultIndexMap[runIndex] = i; |
| 477 } |
| 478 for (var i = 0; i < runs.length; i++) { |
| 479 var resultIndex = resultIndexMap[i]; |
| 480 if (resultIndex == undefined) |
| 481 tableRow.append(markupForMissingRun(i == referenceIndex)); |
| 482 else |
| 483 tableRow.append(markupForRun(results[resultIndex], referenceResult))
; |
| 484 } |
| 485 |
| 486 $('#container').children('tbody').last().append(tableRow); |
| 487 |
| 488 function toggle() { |
| 489 var firstCell = tableRow.children('td').first(); |
| 490 if (firstCell.children('section').length) { |
| 491 firstCell.children('section').remove(); |
| 492 tableRow.children('td').css({'padding-bottom': ''}); |
| 493 } else { |
| 494 var plot = createPlot(firstCell, test); |
| 495 plot.css({'position': 'absolute', 'z-index': 2}); |
| 496 var offset = tableRow.offset(); |
| 497 offset.left += 1; |
| 498 offset.top += tableRow.outerHeight(); |
| 499 plot.offset(offset); |
| 500 tableRow.children('td').css({'padding-bottom': plot.outerHeight() +
5}); |
| 501 } |
| 502 |
| 503 return false; |
| 504 }; |
| 505 |
| 506 tableRow.click(function(event) { |
| 507 if (event.target != tableRow[0] && event.target.parentNode != tableRow[0
]) |
| 508 return; |
| 509 |
| 510 event.preventDefault(); |
| 511 |
| 512 toggle(); |
| 513 }); |
| 514 |
| 515 if (test.isImportant) { |
| 516 toggle(); |
| 517 } |
| 518 } |
| 519 |
| 520 function init() { |
| 521 $.tablesorter.addParser({ |
| 522 id: 'comparison', |
| 523 is: function(s) { |
| 524 return s.indexOf('|') >= 0; |
| 525 }, |
| 526 format: function(s) { |
| 527 var parsed = parseFloat(s.substring(s.indexOf('|') + 1)); |
| 528 return isNaN(parsed) ? 0 : parsed; |
| 529 }, |
| 530 type: 'numeric', |
| 531 }); |
| 532 |
| 533 var runs = []; |
| 534 var metrics = {}; |
| 535 $.each(JSON.parse(document.getElementById('results-json').textContent), func
tion (index, entry) { |
| 536 var run = new TestRun(entry); |
| 537 runs.push(run); |
| 538 |
| 539 function addTests(tests, parentFullName) { |
| 540 for (var testName in tests) { |
| 541 var fullTestName = parentFullName + '/' + testName; |
| 542 var rawMetrics = tests[testName].metrics; |
| 543 |
| 544 for (var metricName in rawMetrics) { |
| 545 var fullMetricName = fullTestName + ':' + metricName; |
| 546 var metric = metrics[fullMetricName]; |
| 547 if (!metric) { |
| 548 metric = new PerfTestMetric(fullTestName, metricName, ra
wMetrics[metricName].units, rawMetrics[metricName].important); |
| 549 metrics[fullMetricName] = metric; |
| 550 } |
| 551 metric.addResult(new TestResult(metric, rawMetrics[metricNam
e].current, run)); |
| 552 } |
| 553 |
| 554 if (tests[testName].tests) |
| 555 addTests(tests[testName].tests, fullTestName); |
| 556 } |
| 557 } |
| 558 |
| 559 addTests(entry.tests, ''); |
| 560 }); |
| 561 |
| 562 var shouldIgnoreMemory= true; |
| 563 var referenceIndex = 0; |
| 564 |
| 565 createTable(metrics, runs, shouldIgnoreMemory, referenceIndex); |
| 566 |
| 567 $('#time-memory').bind('change', function (event, checkedElement) { |
| 568 shouldIgnoreMemory = checkedElement.textContent == 'Time'; |
| 569 createTable(metrics, runs, shouldIgnoreMemory, referenceIndex); |
| 570 }); |
| 571 |
| 572 runs.map(function (run, index) { |
| 573 $('#reference').append('<span value="' + index + '"' + (index == referen
ceIndex ? ' class="checked"' : '') + '>' + run.label() + '</span>'); |
| 574 }) |
| 575 |
| 576 $('#reference').bind('change', function (event, checkedElement) { |
| 577 referenceIndex = parseInt(checkedElement.getAttribute('value')); |
| 578 createTable(metrics, runs, shouldIgnoreMemory, referenceIndex); |
| 579 }); |
| 580 |
| 581 $('.checkbox').each(function (index, checkbox) { |
| 582 $(checkbox).children('span').click(function (event) { |
| 583 if ($(this).hasClass('checked')) |
| 584 return; |
| 585 $(checkbox).children('span').removeClass('checked'); |
| 586 $(this).addClass('checked'); |
| 587 $(checkbox).trigger('change', $(this)); |
| 588 }); |
| 589 }); |
| 590 } |
| 591 |
| 592 </script> |
| 593 <script id="results-json" type="application/json">%json_results%</script> |
| 594 <script id="units-json" type="application/json">%json_units%</script> |
| 595 </body> |
| 596 </html> |
OLD | NEW |