time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

main.js (3812B)


      1 /**
      2 * @license Apache-2.0
      3 *
      4 * Copyright (c) 2018 The Stdlib Authors.
      5 *
      6 * Licensed under the Apache License, Version 2.0 (the "License");
      7 * you may not use this file except in compliance with the License.
      8 * You may obtain a copy of the License at
      9 *
     10 *    http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing, software
     13 * distributed under the License is distributed on an "AS IS" BASIS,
     14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15 * See the License for the specific language governing permissions and
     16 * limitations under the License.
     17 */
     18 
     19 'use strict';
     20 
     21 // MODULES //
     22 
     23 var path = require( 'path' );
     24 var isStringArray = require( '@stdlib/assert/is-string-array' ).primitives;
     25 var isFunction = require( '@stdlib/assert/is-function' );
     26 var cwd = require( '@stdlib/process/cwd' );
     27 var copy = require( './../../copy' );
     28 var defaults = require( './defaults.js' );
     29 var validate = require( './validate.js' );
     30 var exec = require( './node' );
     31 
     32 
     33 // MAIN //
     34 
     35 /**
     36 * Executes scripts in parallel.
     37 *
     38 * @param {StringArray} files - script file paths
     39 * @param {Options} [options] - function options
     40 * @param {string} [options.cmd='node'] - executable file/command
     41 * @param {PositiveInteger} [options.concurrency] - number of scripts to execute concurrently
     42 * @param {PositiveInteger} [options.workers] - number of workers
     43 * @param {boolean} [options.ordered=false] - boolean indicating whether to preserve the order of script output
     44 * @param {NonNegativeInteger} [options.uid] - process user identity
     45 * @param {NonNegativeInteger} [options.gid] - process group identity
     46 * @param {NonNegativeInteger} [options.maxBuffer=200*1024*1024] - max child process `stdio` buffer size
     47 * @param {Callback} clbk - callback to invoke after executing all scripts
     48 * @throws {TypeError} first argument must be a string array
     49 * @throws {TypeError} options argument must be an object
     50 * @throws {TypeError} must provide valid options
     51 * @throws {TypeError} callback argument must be a function
     52 *
     53 * @example
     54 * var files = [ './a.js', './b.js ' ];
     55 *
     56 * var opts = {
     57 *     'workers': 3,
     58 *     'concurrency': 3
     59 * };
     60 *
     61 * function done( error ) {
     62 *     if ( error ) {
     63 *         throw error;
     64 *     }
     65 * }
     66 *
     67 * parallel( files, opts, done );
     68 */
     69 function parallel() {
     70 	var options;
     71 	var files;
     72 	var opts;
     73 	var clbk;
     74 	var err;
     75 	var dir;
     76 	var i;
     77 
     78 	files = arguments[ 0 ];
     79 	if ( !isStringArray( files ) ) {
     80 		throw new TypeError( 'invalid argument. First argument must be an array of string primitives. Value: `' + files + '`.' );
     81 	}
     82 	files = files.slice();
     83 	opts = copy( defaults );
     84 	if ( arguments.length > 2 ) {
     85 		options = arguments[ 1 ];
     86 		clbk = arguments[ 2 ];
     87 		err = validate( opts, options );
     88 		if ( err ) {
     89 			throw err;
     90 		}
     91 	} else {
     92 		clbk = arguments[ 1 ];
     93 	}
     94 	if ( !isFunction( clbk ) ) {
     95 		throw new TypeError( 'invalid argument. Callback argument must be a function. Value: `' + clbk + '`.' );
     96 	}
     97 	// Prevent the number of concurrent scripts exceeding the number of actual scripts to run.
     98 	if ( opts.concurrency > files.length ) {
     99 		opts.concurrency = files.length;
    100 	}
    101 	// Prevent the number of workers exceeding the number of concurrent scripts (excess capacity), as some workers would never be allocated scripts to run and always be idle.
    102 	if ( opts.workers > opts.concurrency ) {
    103 		opts.workers = opts.concurrency;
    104 	}
    105 	// Resolve any relative paths to absolute paths...
    106 	dir = cwd();
    107 	for ( i = 0; i < files.length; i++ ) {
    108 		files[ i ] = path.resolve( dir, files[ i ] );
    109 	}
    110 	exec( files, opts, done );
    111 
    112 	/**
    113 	* Callback invoked after executing all scripts.
    114 	*
    115 	* @private
    116 	* @param {Error} error - error object
    117 	* @returns {void}
    118 	*/
    119 	function done( error ) {
    120 		if ( error ) {
    121 			return clbk( error );
    122 		}
    123 		clbk();
    124 	}
    125 }
    126 
    127 
    128 // EXPORTS //
    129 
    130 module.exports = parallel;