|
| 1 | +import * as fs from 'fs'; |
| 2 | + |
| 3 | +import { BenchmarkOptions } from './benchmark-options'; |
| 4 | +import { |
| 5 | + benchmarkLog, |
| 6 | + isNumber, |
| 7 | + average, |
| 8 | + combine, |
| 9 | + makeArray, |
| 10 | + makeMatchFn, |
| 11 | + matchSpawn, |
| 12 | + serialMultiPromise |
| 13 | +} from './utils'; |
| 14 | + |
| 15 | +export const benchmark = (benchmarkOptions: BenchmarkOptions) => { |
| 16 | + const log = benchmarkLog.bind(null, benchmarkOptions); |
| 17 | + const logIfDefined = (str: string, prop: any) => { |
| 18 | + if (Array.isArray(prop) && prop.length === 0) { |
| 19 | + prop = null; |
| 20 | + } |
| 21 | + return prop ? log(str + prop) : null; |
| 22 | + }; |
| 23 | + |
| 24 | + const cwd = process.cwd(); |
| 25 | + |
| 26 | + // Build match function |
| 27 | + let matchFn: any = null; |
| 28 | + if (benchmarkOptions.match) { |
| 29 | + matchFn = makeMatchFn( |
| 30 | + benchmarkOptions.debug, |
| 31 | + benchmarkOptions.match, |
| 32 | + benchmarkOptions.matchCount, |
| 33 | + benchmarkOptions.matchEditFile, |
| 34 | + benchmarkOptions.matchEditString, |
| 35 | + ); |
| 36 | + } |
| 37 | + |
| 38 | + let editedFileContents: string; |
| 39 | + if (benchmarkOptions.matchEditFile) { |
| 40 | + // backup contents of file that is being edited for rebuilds |
| 41 | + editedFileContents = fs.readFileSync(benchmarkOptions.matchEditFile, 'utf8'); |
| 42 | + } |
| 43 | + // combine flags commands |
| 44 | + let flagCombinations = combine(benchmarkOptions.extraArgs); |
| 45 | + flagCombinations.unshift([]); |
| 46 | + |
| 47 | + const startTime = Date.now(); |
| 48 | + log(`Base command: ${benchmarkOptions.command}`); |
| 49 | + log(`Iterations: ${benchmarkOptions.iterations}`); |
| 50 | + logIfDefined('Comment: ', benchmarkOptions.comment); |
| 51 | + logIfDefined('Extra args: ', benchmarkOptions.extraArgs); |
| 52 | + logIfDefined('Logging to: ', benchmarkOptions.logFile); |
| 53 | + if (benchmarkOptions.match) { |
| 54 | + log(`Match output: ${benchmarkOptions.match}`); |
| 55 | + logIfDefined('Match count: ', benchmarkOptions.matchCount); |
| 56 | + logIfDefined('Match edit file: ', benchmarkOptions.matchEditFile); |
| 57 | + logIfDefined('Match edit string: ', benchmarkOptions.matchEditString); |
| 58 | + } |
| 59 | + if (benchmarkOptions.debug) { |
| 60 | + log('### Debug mode, all output is logged ###'); |
| 61 | + } |
| 62 | + log(''); |
| 63 | + |
| 64 | + |
| 65 | + let promise = Promise.resolve(); |
| 66 | + let hasFailures = false; |
| 67 | + |
| 68 | + flagCombinations.forEach((flags) => |
| 69 | + promise = promise |
| 70 | + .then(() => serialMultiPromise( |
| 71 | + benchmarkOptions.iterations, |
| 72 | + matchSpawn, |
| 73 | + benchmarkOptions.debug, |
| 74 | + cwd, |
| 75 | + matchFn, |
| 76 | + benchmarkOptions.command, |
| 77 | + flags |
| 78 | + ).then((results: any[]) => { |
| 79 | + const failures = results.filter(result => result.err && result.err !== 0); |
| 80 | + log(`Full command: ${benchmarkOptions.command} ${flags.join(' ')}`); |
| 81 | + |
| 82 | + let times = results.filter(result => !result.err) |
| 83 | + .map((result) => result.time); |
| 84 | + log(`Time average: ${average(times)}`); |
| 85 | + log(`Times: ${times.join()}`); |
| 86 | + |
| 87 | + if (benchmarkOptions.match) { |
| 88 | + let matches = results.filter(result => !result.err) |
| 89 | + .map((result) => result.match); |
| 90 | + if (matches.every(match => isNumber(match))) { |
| 91 | + log(`Match average: ${average(matches)}`); |
| 92 | + } |
| 93 | + log(`Matches: ${matches.join()}`); |
| 94 | + } |
| 95 | + |
| 96 | + if (failures.length > 0) { |
| 97 | + hasFailures = true; |
| 98 | + log(`Failures: ${failures.length}`); |
| 99 | + log(failures); |
| 100 | + } |
| 101 | + log(''); |
| 102 | + })) |
| 103 | + ); |
| 104 | + |
| 105 | + return promise.then(() => { |
| 106 | + log(`Benchmark execution time: ${Date.now() - startTime}ms`); |
| 107 | + // restore contents of file that was being edited for rebuilds |
| 108 | + if (benchmarkOptions.matchEditFile) { |
| 109 | + fs.writeFileSync(benchmarkOptions.matchEditFile, editedFileContents, 'utf8'); |
| 110 | + } |
| 111 | + return hasFailures ? Promise.reject(new Error('Some benchmarks failed')) : Promise.resolve(); |
| 112 | + }); |
| 113 | +}; |
0 commit comments