# Parallel
> Execute scripts in parallel.
## Usage
```javascript
var parallel = require( '@stdlib/utils/parallel' );
```
#### parallel( files, \[options,] clbk )
Executes scripts in parallel.
```javascript
var files = [
'./a.js',
'./b.js'
];
function done( error ) {
if ( error ) {
console.error( 'Exit code: '+error.code );
console.error( 'Signal: '+error.signal );
throw error;
}
console.log( 'Done!' );
}
parallel( files, done );
```
The function accepts the following `options`:
- **cmd**: executable file/command. Default: `'node'`.
- **workers**: number of workers. Default: number of CPUs minus `1`.
- **concurrency**: number of scripts to execute concurrently. Default: `options.workers`.
- **ordered**: `boolean` indicating whether to preserve the order of script output. Default: `false`.
- **maxBuffer**: maximum child process `stdio` buffer size. This option is **only** applied when `options.ordered = true`. Default: `200*1024*1024` bytes.
- **uid**: child process user identity.
- **gid**: child process group identity.
By default, the number of workers running scripts is equal to the number of CPUs minus `1` (master process). To adjust the number of workers, set the `workers` option.
```javascript
var files = [
'./a.js',
'./b.js'
];
function done( error ) {
if ( error ) {
console.error( 'Exit code: '+error.code );
console.error( 'Signal: '+error.signal );
throw error;
}
console.log( 'Done!' );
}
var opts = {
'workers': 8
};
parallel( files, opts, done );
```
By default, the number of scripts running concurrently is equal to the number of workers. To adjust the concurrency, set the `concurrency` option.
```javascript
var files = [
'./a.js',
'./b.js'
];
function done( error ) {
if ( error ) {
console.error( 'Exit code: '+error.code );
console.error( 'Signal: '+error.signal );
throw error;
}
console.log( 'Done!' );
}
var opts = {
'concurrency': 6
};
parallel( files, opts, done );
```
By specifying a concurrency greater than the number of workers, a worker may be executing more than `1` script at any one time. While not likely to be advantageous for synchronous scripts, setting a higher concurrency may be advantageous for scripts performing asynchronous tasks.
By default, each script is executed as a [Node.js][node-js] script.
```text
$ node
```
To run scripts via an alternative executable or none at all, set the `cmd` option.
```javascript
var files = [
'./a.js',
'./b.js'
];
function done( error ) {
if ( error ) {
console.error( 'Exit code: '+error.code );
console.error( 'Signal: '+error.signal );
throw error;
}
console.log( 'Done!' );
}
var opts = {
'cmd': '' // e.g., if scripts contain a shebang
};
parallel( files, opts, done );
```
By default, the `stdio` output for each script is interleaved; i.e., the `stdio` output from one script **may** be interleaved with the `stdio` output from one or more other scripts. To preserve the `stdio` output order for each script, set the `ordered` option to `true`.
```javascript
var files = [
'./a.js',
'./b.js'
];
function done( error ) {
if ( error ) {
console.error( 'Exit code: '+error.code );
console.error( 'Signal: '+error.signal );
throw error;
}
console.log( 'Done!' );
}
var opts = {
'ordered': true
};
parallel( files, opts, done );
```
## Notes
- Relative file paths are resolved relative to the current working directory.
- Ordered script output does **not** imply that scripts are executed in order. To preserve script order, execute the scripts sequentially via some other means.
- Script concurrency cannot exceed the number of scripts.
- If the script concurrency is less than the number of workers, the number of workers is reduced to match the specified concurrency.
## Examples
```javascript
var fs = require( 'fs' );
var path = require( 'path' );
var writeFileSync = require( '@stdlib/fs/write-file' ).sync;
var unlinkSync = require( '@stdlib/fs/unlink' ).sync;
var parallel = require( '@stdlib/utils/parallel' );
var nFiles = 100;
var files;
var opts;
var dir;
function template( id ) {
var file = '';
file += '\'use strict\';';
file += 'var id;';
file += 'var N;';
file += 'var i;';
file += 'id = '+id+';';
file += 'N = 1e5;';
file += 'console.log( \'File: %s. id: %s. N: %d.\', __filename, id, N );';
file += 'for ( i = 0; i < N; i++ ) {';
file += 'console.log( \'id: %s. v: %d.\', id, i );';
file += '}';
return file;
}
function createDir() {
var dir = path.join( __dirname, 'examples', 'tmp' );
fs.mkdirSync( dir );
return dir;
}
function createScripts( dir, nFiles ) {
var content;
var fpath;
var files;
var i;
files = new Array( nFiles );
for ( i = 0; i < nFiles; i++ ) {
content = template( i.toString() );
fpath = path.join( dir, i+'.js' );
writeFileSync( fpath, content, {
'encoding': 'utf8'
});
files[ i ] = fpath;
}
return files;
}
function cleanup() {
var i;
// Delete the temporary files...
for ( i = 0; i < files.length; i++ ) {
unlinkSync( files[ i ] );
}
// Remove temporary directory:
fs.rmdirSync( dir );
}
function done( error ) {
if ( error ) {
throw error;
}
cleanup();
console.log( 'Done!' );
}
// Make a temporary directory to store files...
dir = createDir();
// Create temporary files...
files = createScripts( dir, nFiles );
// Set the runner options:
opts = {
'concurrency': 3,
'workers': 3,
'ordered': false
};
// Run all temporary scripts:
parallel( files, opts, done );
```
* * *
## CLI
### Usage
```text
Usage: parallel [options] ...
Options:
-h, --help Print this message.
-V, --version Print the package version.
--cmd cmd Executable file/command.
--workers num Number of workers.
--concurrency num Number of scripts to run concurrently.
--ordered Preserve order of script output.
--uid uid Process user identity.
--gid gid Process group identity.
--maxbuffer size Max buffer size for stdout and stderr.
```
### Examples
```bash
$ parallel --cmd 'node' --workers 4 --concurrency 8 ./1.js ./2.js ./3.js ./4.js ./5.js ./6.js ./7.js ./8.js ./9.js ./10.js
```
[node-js]: http://nodejs.org/