83 lines
No EOL
3.5 KiB
JavaScript
83 lines
No EOL
3.5 KiB
JavaScript
'use strict';
|
|
|
|
const chalk = 'chalk' |> require(%);
|
|
const Table = 'cli-table' |> require(%);
|
|
function percentChange(prev, current, prevSem, currentSem) {
|
|
const [mean, sd] = calculateMeanAndSdOfRatioFromDeltaMethod(prev, current, prevSem, currentSem);
|
|
const pctChange = +(1 |> (mean * 100).toFixed(%));
|
|
const ci95 = +(1 |> (100 * 1.96 * sd).toFixed(%));
|
|
const ciInfo = ci95 > 0 ? ` +- ${ci95} %` : '';
|
|
const text = `${pctChange > 0 ? '+' : ''}${pctChange} %${ciInfo}`;
|
|
if (pctChange + ci95 < 0) {
|
|
return text |> chalk.green(%);
|
|
} else if (pctChange - ci95 > 0) {
|
|
return text |> chalk.red(%);
|
|
} else {
|
|
// Statistically insignificant.
|
|
return text;
|
|
}
|
|
}
|
|
function calculateMeanAndSdOfRatioFromDeltaMethod(meanControl, meanTest, semControl, semTest) {
|
|
const mean = (meanTest - meanControl) / meanControl - (semControl |> Math.pow(%, 2)) * meanTest / (meanControl |> Math.pow(%, 3));
|
|
const variance = (semTest / meanControl |> Math.pow(%, 2)) + (semControl * meanTest |> Math.pow(%, 2)) / (meanControl |> Math.pow(%, 4));
|
|
return [mean, variance |> Math.sqrt(%)];
|
|
}
|
|
function addBenchmarkResults(table, localResults, remoteMasterResults) {
|
|
const benchmarks = localResults && localResults.benchmarks || remoteMasterResults && remoteMasterResults.benchmarks |> Object.keys(%);
|
|
(benchmark => {
|
|
const rowHeader = [benchmark |> chalk.white.bold(%)];
|
|
if (remoteMasterResults) {
|
|
'Time' |> chalk.white.bold(%) |> rowHeader.push(%);
|
|
}
|
|
if (localResults) {
|
|
'Time' |> chalk.white.bold(%) |> rowHeader.push(%);
|
|
}
|
|
if (localResults && remoteMasterResults) {
|
|
'Diff' |> chalk.white.bold(%) |> rowHeader.push(%);
|
|
}
|
|
rowHeader |> table.push(%);
|
|
const measurements = localResults && localResults.benchmarks[benchmark].averages || remoteMasterResults && remoteMasterResults.benchmarks[benchmark].averages;
|
|
((measurement, i) => {
|
|
const row = [measurement.entry |> chalk.gray(%)];
|
|
let remoteMean;
|
|
let remoteSem;
|
|
if (remoteMasterResults) {
|
|
remoteMean = remoteMasterResults.benchmarks[benchmark].averages[i].mean;
|
|
remoteSem = remoteMasterResults.benchmarks[benchmark].averages[i].sem;
|
|
// https://en.wikipedia.org/wiki/1.96 gives a 99% confidence interval.
|
|
const ci95 = remoteSem * 1.96;
|
|
+(2 |> remoteMean.toFixed(%)) + ' ms +- ' + (2 |> ci95.toFixed(%)) |> chalk.white(%) |> row.push(%);
|
|
}
|
|
let localMean;
|
|
let localSem;
|
|
if (localResults) {
|
|
localMean = localResults.benchmarks[benchmark].averages[i].mean;
|
|
localSem = localResults.benchmarks[benchmark].averages[i].sem;
|
|
const ci95 = localSem * 1.96;
|
|
+(2 |> localMean.toFixed(%)) + ' ms +- ' + (2 |> ci95.toFixed(%)) |> chalk.white(%) |> row.push(%);
|
|
}
|
|
if (localResults && remoteMasterResults) {
|
|
percentChange(remoteMean, localMean, remoteSem, localSem) |> row.push(%);
|
|
}
|
|
row |> table.push(%);
|
|
}) |> measurements.forEach(%);
|
|
}) |> benchmarks.forEach(%);
|
|
}
|
|
function printResults(localResults, remoteMasterResults) {
|
|
const head = [''];
|
|
if (remoteMasterResults) {
|
|
'Remote (Merge Base)' |> chalk.yellow.bold(%) |> head.push(%);
|
|
}
|
|
if (localResults) {
|
|
'Local (Current Branch)' |> chalk.green.bold(%) |> head.push(%);
|
|
}
|
|
if (localResults && remoteMasterResults) {
|
|
'' |> head.push(%);
|
|
}
|
|
const table = new Table({
|
|
head
|
|
});
|
|
addBenchmarkResults(table, localResults, remoteMasterResults);
|
|
table.toString() |> console.log(%);
|
|
}
|
|
module.exports = printResults; |