|
10 | 10 | 'use strict';
|
11 | 11 |
|
12 | 12 | const { Suite } = require('benchmark');
|
13 |
| -const beautifyBenchmark = require('beautify-benchmark'); |
14 | 13 | const { execSync } = require('child_process');
|
15 | 14 | const os = require('os');
|
16 | 15 | const fs = require('fs');
|
@@ -83,25 +82,89 @@ function runBenchmark(benchmark, environments) {
|
83 | 82 | const modules = environments.map(({ distPath }) =>
|
84 | 83 | require(path.join(distPath, benchmark))
|
85 | 84 | );
|
| 85 | + const benchResults = [] |
| 86 | + |
86 | 87 | const suite = new Suite(modules[0].name, {
|
87 | 88 | onStart(event) {
|
88 | 89 | console.log('⏱️ ' + event.currentTarget.name);
|
89 |
| - beautifyBenchmark.reset(); |
90 | 90 | },
|
91 |
| - onCycle(event) { |
92 |
| - beautifyBenchmark.add(event.target); |
| 91 | + onCycle({ target }) { |
| 92 | + benchResults.push(target); |
| 93 | + process.stdout.write( |
| 94 | + ' ' + cyan(benchResults.length) + ' tests completed.\u000D', |
| 95 | + ); |
93 | 96 | },
|
94 | 97 | onError(event) {
|
95 | 98 | console.error(event.target.error);
|
96 | 99 | },
|
97 | 100 | onComplete() {
|
98 |
| - beautifyBenchmark.log(); |
| 101 | + console.log('\n'); |
| 102 | + beautifyBenchmark(benchResults); |
99 | 103 | },
|
100 | 104 | });
|
101 | 105 | for (let i = 0; i < environments.length; i++) {
|
102 | 106 | suite.add(environments[i].revision, modules[i].measure);
|
103 | 107 | }
|
104 | 108 | suite.run({ async: false });
|
| 109 | + console.log(''); |
| 110 | +} |
| 111 | + |
| 112 | +function beautifyBenchmark(results) { |
| 113 | + const benches = results.map(result => ({ |
| 114 | + name: result.name, |
| 115 | + error: result.error, |
| 116 | + ops: result.hz, |
| 117 | + deviation: result.stats.rme, |
| 118 | + numRuns: result.stats.sample.length, |
| 119 | + })); |
| 120 | + |
| 121 | + const nameMaxLen = maxBy(benches, ({ name }) => name.length); |
| 122 | + const opsTop = maxBy(benches, ({ ops }) => ops); |
| 123 | + const opsMaxLen = maxBy(benches, ({ ops }) => beautifyNumber(ops).length); |
| 124 | + |
| 125 | + for (const bench of benches) { |
| 126 | + if (bench.error) { |
| 127 | + console.log(' ' + bench.name + ': ' + red(String(bench.error))); |
| 128 | + continue; |
| 129 | + } |
| 130 | + |
| 131 | + const { name, ops, deviation, numRuns } = bench; |
| 132 | + console.log( |
| 133 | + ' ' + nameStr() + grey(' x ') + opsStr() + ' ops/sec ' + |
| 134 | + grey('\xb1') + deviationStr() + cyan('%') + |
| 135 | + grey(' (' + numRuns + ' runs sampled)') |
| 136 | + ); |
| 137 | + |
| 138 | + function nameStr() { |
| 139 | + const nameFmt = name.padEnd(nameMaxLen); |
| 140 | + return (ops === opsTop) ? green(nameFmt) : nameFmt; |
| 141 | + } |
| 142 | + |
| 143 | + function opsStr() { |
| 144 | + const percent = ops / opsTop; |
| 145 | + const colorFn = percent > 0.95 ? green : (percent > 0.80 ? yellow : red); |
| 146 | + return colorFn(beautifyNumber(ops).padStart(opsMaxLen)); |
| 147 | + } |
| 148 | + |
| 149 | + function deviationStr() { |
| 150 | + const colorFn = deviation > 5 ? red : (deviation > 2 ? yellow : green); |
| 151 | + return colorFn(deviation.toFixed(2)); |
| 152 | + } |
| 153 | + } |
| 154 | +} |
| 155 | + |
| 156 | +function red(str) { return '\u001b[31m' + str + '\u001b[0m' } |
| 157 | +function green(str) { return '\u001b[32m' + str + '\u001b[0m' } |
| 158 | +function yellow(str) { return '\u001b[33m' + str + '\u001b[0m' } |
| 159 | +function cyan(str) { return '\u001b[36m' + str + '\u001b[0m' } |
| 160 | +function grey(str) { return '\u001b[90m' + str + '\u001b[0m' } |
| 161 | + |
| 162 | +function beautifyNumber(num) { |
| 163 | + return Number(num.toFixed(num > 100 ? 0 : 2)).toLocaleString(); |
| 164 | +} |
| 165 | + |
| 166 | +function maxBy(array, fn) { |
| 167 | + return Math.max(...array.map(fn)); |
105 | 168 | }
|
106 | 169 |
|
107 | 170 | // Prepare all revisions and run benchmarks matching a pattern against them.
|
|
0 commit comments