diff --git a/codespeed/static/js/comparison.js b/codespeed/static/js/comparison.js index 48415b3e..19ada2bc 100644 --- a/codespeed/static/js/comparison.js +++ b/codespeed/static/js/comparison.js @@ -16,6 +16,10 @@ var COLORS = [ ]; function getColor(i) { return COLORS[i % COLORS.length]; } +function getExeLabel(key) { + return $("label[for='exe_" + key.replace(/:/g, '\\:') + "']").text().trim(); +} + function getConfiguration() { return { exe: readCheckbox("input[name='executables']:checked"), @@ -27,6 +31,86 @@ function getConfiguration() { }; } +function updateGraphTitle(exes, enviros, bens, baseline, chart, chartTitles) { + var $title = $("#graph-title"); + + if (enviros.length === 1 && exes.length === 2 && baseline !== "none" && + chart !== "stacked bars" && compdata) { + + var baselineExe = baseline, baselineEnv = null; + if (baseline.indexOf('@') !== -1) { + var bparts = baseline.split('@'); + baselineExe = bparts[0]; + baselineEnv = bparts[1]; + } + + var otherExes = exes.filter(function(e) { return e !== baselineExe; }); + if (otherExes.length === 1) { + var otherExe = otherExes[0]; + var envId = enviros[0]; + var envForBase = baselineEnv !== null ? baselineEnv : envId; + + var product = 1, count = 0; + for (var b = 0; b < bens.length; b++) { + var val = compdata[otherExe] && compdata[otherExe][envId] + ? compdata[otherExe][envId][bens[b]] + : null; + var baseval = compdata[baselineExe] && compdata[baselineExe][envForBase] + ? compdata[baselineExe][envForBase][bens[b]] + : null; + if (val !== null && baseval !== null && baseval !== 0 && val > 0) { + product *= val / baseval; + count++; + } + } + + if (count > 0) { + var geomean = Math.pow(product, 1 / count); + + var lessCount = 0, moreCount = 0; + var benSet = {}; + for (var b = 0; b < bens.length; b++) { benSet[bens[b]] = true; } + for (var u in bench_units) { + var unitBens = bench_units[u][0]; + var unitLess = bench_units[u][1].indexOf("less") !== -1; + for (var ub = 0; ub < unitBens.length; ub++) { + if (benSet[unitBens[ub]]) { + if (unitLess) { lessCount++; } else { moreCount++; } + } + } + } + + var otherLabel = getExeLabel(otherExe); + var baselineLabel = getExeLabel(baselineExe); + if (baselineEnv !== null) { + baselineLabel += ' @ ' + $("label[for='env_" + baselineEnv + "']").text().trim(); + } + + var suffix; + if (moreCount === 0 && lessCount > 0) { + suffix = geomean < 1 + ? ' or ' + (1 / geomean).toFixed(1) + '× faster' + : ' or ' + geomean.toFixed(1) + '× slower'; + } else if (lessCount === 0 && moreCount > 0) { + suffix = geomean > 1 + ? ' or ' + geomean.toFixed(1) + '× faster' + : ' or ' + (1 / geomean).toFixed(1) + '× slower'; + } else { + suffix = ' relative to baseline'; + } + + $title.html('The geometric average of ' + count + ' benchmarks for ' + + otherLabel + ' is ' + geomean.toFixed(2) + '' + + suffix + ' than the baseline ' + baselineLabel + ''); + return; + } + } + } + + // Fall back to the chart title(s) + $title.text(chartTitles.join(' / ')); +} + function refreshContent() { var conf = getConfiguration(), exes = conf.exe.split(","), @@ -34,6 +118,7 @@ function refreshContent() { enviros = conf.env.split(","), msg = ""; + $("#graph-title").html(""); var h = $("#plotwrapper").height();//get height for error message if (exes[0] === "") { $("#plotwrapper").html('

No executables selected

'); @@ -73,6 +158,7 @@ function refreshContent() { $("#plotwrapper").fadeOut("fast", function() { $(this).html(msg).show(); var plotcounter = 1; + var chartTitles = []; for (var unit in bench_units) { var benchmarks = []; for (var ben in bens) { @@ -85,8 +171,9 @@ function refreshContent() { var plotid = "plot" + plotcounter; $("#plotwrapper").append('
'); plotcounter++; - renderComparisonPlot(plotid, unit, benchmarks, exes, enviros, conf.bas, conf.chart, conf.hor); + chartTitles.push(renderComparisonPlot(plotid, unit, benchmarks, exes, enviros, conf.bas, conf.chart, conf.hor)); } + updateGraphTitle(exes, enviros, bens, conf.bas, conf.chart, chartTitles); }); } @@ -114,7 +201,7 @@ function updateBaselineDropdown() { if (multiEnv) { enviros.forEach(function(envId) { var envName = $("label[for='env_" + envId + "']").text().trim(); - $baseline.append($('