|
| 1 | +#!/usr/bin/env node |
| 2 | +/** |
| 3 | + * @license |
| 4 | + * Copyright Google Inc. All Rights Reserved. |
| 5 | + * |
| 6 | + * Use of this source code is governed by an MIT-style license that can be |
| 7 | + * found in the LICENSE file at https://angular.io/license |
| 8 | + */ |
| 9 | + |
| 10 | +import { logging, tags } from '@angular-devkit/core'; |
| 11 | +import { createConsoleLogger } from '@angular-devkit/core/node'; |
| 12 | +import { appendFileSync, writeFileSync } from 'fs'; |
| 13 | +import * as minimist from 'minimist'; |
| 14 | +import { filter, map } from 'rxjs/operators'; |
| 15 | +import { Command } from '../src/command'; |
| 16 | +import { defaultReporter } from '../src/default-reporter'; |
| 17 | +import { defaultStatsCapture } from '../src/default-stats-capture'; |
| 18 | +import { runBenchmark } from '../src/run-benchmark'; |
| 19 | + |
| 20 | +// Show usage of the CLI tool, and exit the process. |
| 21 | +function usage(exitCode = 0): never { |
| 22 | + logger.info(tags.stripIndent` |
| 23 | + benchmark [options] -- [command to benchmark] |
| 24 | +
|
| 25 | + Collects process stats from running the command. |
| 26 | +
|
| 27 | + Options: |
| 28 | + --help Show this message. |
| 29 | + --verbose Show more information. |
| 30 | + --exit-code Expected exit code. Default is 0. |
| 31 | + --iterations Number of iterations to run the benchmark over. Default is 5. |
| 32 | + --retries Number of times to retry when process fails. Default is 5. |
| 33 | + --cwd Current working directory to run the process in. |
| 34 | + --output-file File to output benchmark log. |
| 35 | + --overwrite-output-file If the output file should be overwritten rather than appended to. |
| 36 | + --prefix Logging prefix. |
| 37 | +
|
| 38 | + Example: |
| 39 | + benchmark --iterations=3 -- node my-script.js |
| 40 | + `); |
| 41 | + |
| 42 | + process.exit(exitCode); |
| 43 | + // The node typing sometimes don't have a never type for process.exit(). |
| 44 | + throw 0; |
| 45 | +} |
| 46 | + |
| 47 | +// Parse the command line. |
| 48 | +const argv = minimist(process.argv.slice(2), { |
| 49 | + boolean: ['help', 'verbose', 'overwrite-output-file'], |
| 50 | + default: { |
| 51 | + 'exit-code': 0, |
| 52 | + 'iterations': 5, |
| 53 | + 'retries': 5, |
| 54 | + // TODO: add output file reporter |
| 55 | + 'output-file': null, |
| 56 | + 'cwd': process.cwd(), |
| 57 | + 'prefix': '[benchmark] ', |
| 58 | + }, |
| 59 | + '--': true, |
| 60 | +}); |
| 61 | + |
| 62 | +// Create the DevKit Logger used through the CLI. |
| 63 | +const consoleLogger = createConsoleLogger(argv['verbose']); |
| 64 | +if (argv['output-file'] !== null) { |
| 65 | + if (argv['overwrite-output-file']) { |
| 66 | + writeFileSync(argv['output-file'], ''); |
| 67 | + } |
| 68 | + consoleLogger.pipe(filter(entry => (entry.level != 'debug' || argv['verbose']))) |
| 69 | + .subscribe(entry => appendFileSync(argv['output-file'], `${entry.message}\n`)); |
| 70 | +} |
| 71 | +const logger = new logging.TransformLogger( |
| 72 | + 'benchmark-prefix-logger', |
| 73 | + stream => stream.pipe(map(entry => |
| 74 | + (entry.message = argv['prefix'] + entry.message, entry)), |
| 75 | + ), |
| 76 | + consoleLogger, |
| 77 | +); |
| 78 | + |
| 79 | +if (argv['help']) { |
| 80 | + usage(); |
| 81 | +} |
| 82 | + |
| 83 | +if (!Array.isArray(argv['--']) || (argv['--'] as Array<string>).length < 1) { |
| 84 | + logger.fatal(`Missing command, see benchmark --help for help.`); |
| 85 | + process.exit(1); |
| 86 | + throw 0; |
| 87 | +} |
| 88 | + |
| 89 | +// Run benchmark on given command, capturing stats and reporting them. |
| 90 | +const exitCode = argv['exit-code']; |
| 91 | +const cmd = (argv['--'] as Array<string>)[0]; |
| 92 | +const args = (argv['--'] as Array<string>).slice(1); |
| 93 | +const command = new Command(cmd, args, argv['cwd'], exitCode); |
| 94 | +const captures = [defaultStatsCapture]; |
| 95 | +const reporters = [defaultReporter(logger)]; |
| 96 | +const iterations = argv['iterations']; |
| 97 | +const retries = argv['retries']; |
| 98 | + |
| 99 | +logger.info(`Benchmarking process over ${iterations} iterations, with up to ${retries} retries.`); |
| 100 | +logger.info(` ${command.toString()}`); |
| 101 | + |
| 102 | +runBenchmark({ command, captures, reporters, iterations, retries, logger }).subscribe(); |
0 commit comments