cli (4221B)
1 #!/usr/bin/env node 2 3 /** 4 * @license Apache-2.0 5 * 6 * Copyright (c) 2018 The Stdlib Authors. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 'use strict'; 22 23 // MODULES // 24 25 var resolve = require( 'path' ).resolve; 26 var stdin = require( '@stdlib/process/read-stdin' ); 27 var readFileSync = require( '@stdlib/fs/read-file' ).sync; 28 var CLI = require( '@stdlib/cli/ctor' ); 29 var stdinStream = require( '@stdlib/streams/node/stdin' ); 30 var nextTick = require( '@stdlib/utils/next-tick' ); 31 var timeit = require( './../lib' ); 32 33 34 // FUNCTIONS // 35 36 /** 37 * Prints results as JSON. 38 * 39 * @private 40 * @param {Object} results - results 41 */ 42 function printJSON( results ) { 43 console.log( JSON.stringify( results ) ); // eslint-disable-line no-console 44 } 45 46 /** 47 * Prints results as CSV. 48 * 49 * @private 50 * @param {Object} results - results 51 */ 52 function printCSV( results ) { 53 var times = results.times; 54 var i; 55 56 console.log( '%s,%s', 'seconds', 'nanoseconds' ); // eslint-disable-line no-console 57 for ( i = 0; i < times.length; i++ ) { 58 console.log( '%d,%d', times[i][0], times[i][1] ); // eslint-disable-line no-console 59 } 60 } 61 62 /** 63 * Pretty prints results. 64 * 65 * @private 66 * @param {Object} results - results 67 */ 68 function prettyPrint( results ) { 69 var unit; 70 var r; 71 72 r = results.elapsed*1e6 / results.iterations; 73 if ( r < 1000 ) { 74 unit = 'usec'; 75 } else { 76 r /= 1000; 77 if ( r < 1000 ) { 78 unit = 'msec'; 79 } else { 80 r /= 1000; 81 unit = 'sec'; 82 } 83 } 84 /* eslint-disable no-console */ 85 86 console.log( '' ); 87 console.log( 'iterations: %d', results.iterations ); 88 console.log( 'repeats: %d', results.repeats ); 89 console.log( 'iterations/s: %d', results.rate ); 90 console.log( 'elapsed time: %d sec', results.elapsed ); 91 console.log( 'lower bound: %d %s/iteration', r, unit ); 92 console.log( '' ); 93 94 /* eslint-enable no-console */ 95 } 96 97 98 // MAIN // 99 100 /** 101 * Main execution sequence. 102 * 103 * @private 104 * @returns {void} 105 */ 106 function main() { 107 var flags; 108 var args; 109 var code; 110 var opts; 111 var cli; 112 113 // Create a command-line interface: 114 cli = new CLI({ 115 'pkg': require( './../package.json' ), 116 'options': require( './../etc/cli_opts.json' ), 117 'help': readFileSync( resolve( __dirname, '..', 'docs', 'usage.txt' ), { 118 'encoding': 'utf8' 119 }) 120 }); 121 122 // Get any provided command-line options: 123 flags = cli.flags(); 124 if ( flags.help || flags.version ) { 125 return; 126 } 127 128 // Get any provided command-line arguments: 129 args = cli.args(); 130 131 opts = {}; 132 if ( flags.iterations ) { 133 opts.iterations = parseInt( flags.iterations, 10 ); 134 } else { 135 opts.iterations = null; 136 } 137 if ( flags.repeats ) { 138 opts.repeats = parseInt( flags.repeats, 10 ); 139 } 140 if ( flags.before ) { 141 opts.before = flags.before; 142 } 143 if ( flags.after ) { 144 opts.after = flags.after; 145 } 146 if ( flags.async ) { 147 opts.asynchronous = flags.async; 148 } 149 150 // Check if we are receiving data from `stdin`... 151 if ( !stdinStream.isTTY ) { 152 return stdin( onRead ); 153 } 154 code = args[ 0 ]; 155 nextTick( next ); 156 157 /** 158 * Callback invoked upon reading from `stdin`. 159 * 160 * @private 161 * @param {(Error|null)} error - error object 162 * @param {Buffer} data - data 163 * @returns {void} 164 */ 165 function onRead( error, data ) { 166 if ( error ) { 167 return done( error ); 168 } 169 code = data.toString(); 170 next(); 171 } 172 173 /** 174 * Times a snippet. 175 * 176 * @private 177 */ 178 function next() { 179 timeit( code, opts, done ); 180 } 181 182 /** 183 * Callback invoked upon completion. 184 * 185 * @private 186 * @param {(Error|null)} error - error object 187 * @param {Object} results - results 188 * @returns {void} 189 */ 190 function done( error, results ) { 191 if ( error ) { 192 return cli.error( error ); 193 } 194 if ( flags.format === 'json' ) { 195 printJSON( results ); 196 } else if ( flags.format === 'csv' ) { 197 printCSV( results ); 198 } else { 199 prettyPrint( results ); 200 } 201 } 202 } 203 204 main();