README.md (7909B)
1 <!-- 2 3 @license Apache-2.0 4 5 Copyright (c) 2018 The Stdlib Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 19 --> 20 21 # Parallel 22 23 > Execute scripts in parallel. 24 25 <section class="usage"> 26 27 ## Usage 28 29 ```javascript 30 var parallel = require( '@stdlib/utils/parallel' ); 31 ``` 32 33 #### parallel( files, \[options,] clbk ) 34 35 Executes scripts in parallel. 36 37 <!-- run-disable --> 38 39 ```javascript 40 var files = [ 41 './a.js', 42 './b.js' 43 ]; 44 45 function done( error ) { 46 if ( error ) { 47 console.error( 'Exit code: '+error.code ); 48 console.error( 'Signal: '+error.signal ); 49 throw error; 50 } 51 console.log( 'Done!' ); 52 } 53 54 parallel( files, done ); 55 ``` 56 57 The function accepts the following `options`: 58 59 - **cmd**: executable file/command. Default: `'node'`. 60 - **workers**: number of workers. Default: number of CPUs minus `1`. 61 - **concurrency**: number of scripts to execute concurrently. Default: `options.workers`. 62 - **ordered**: `boolean` indicating whether to preserve the order of script output. Default: `false`. 63 - **maxBuffer**: maximum child process `stdio` buffer size. This option is **only** applied when `options.ordered = true`. Default: `200*1024*1024` bytes. 64 - **uid**: child process user identity. 65 - **gid**: child process group identity. 66 67 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. 68 69 <!-- run-disable --> 70 71 ```javascript 72 var files = [ 73 './a.js', 74 './b.js' 75 ]; 76 77 function done( error ) { 78 if ( error ) { 79 console.error( 'Exit code: '+error.code ); 80 console.error( 'Signal: '+error.signal ); 81 throw error; 82 } 83 console.log( 'Done!' ); 84 } 85 86 var opts = { 87 'workers': 8 88 }; 89 90 parallel( files, opts, done ); 91 ``` 92 93 By default, the number of scripts running concurrently is equal to the number of workers. To adjust the concurrency, set the `concurrency` option. 94 95 <!-- run-disable --> 96 97 ```javascript 98 var files = [ 99 './a.js', 100 './b.js' 101 ]; 102 103 function done( error ) { 104 if ( error ) { 105 console.error( 'Exit code: '+error.code ); 106 console.error( 'Signal: '+error.signal ); 107 throw error; 108 } 109 console.log( 'Done!' ); 110 } 111 112 var opts = { 113 'concurrency': 6 114 }; 115 116 parallel( files, opts, done ); 117 ``` 118 119 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. 120 121 By default, each script is executed as a [Node.js][node-js] script. 122 123 ```text 124 $ node <script_path> 125 ``` 126 127 To run scripts via an alternative executable or none at all, set the `cmd` option. 128 129 <!-- run-disable --> 130 131 ```javascript 132 var files = [ 133 './a.js', 134 './b.js' 135 ]; 136 137 function done( error ) { 138 if ( error ) { 139 console.error( 'Exit code: '+error.code ); 140 console.error( 'Signal: '+error.signal ); 141 throw error; 142 } 143 console.log( 'Done!' ); 144 } 145 146 var opts = { 147 'cmd': '' // e.g., if scripts contain a shebang 148 }; 149 150 parallel( files, opts, done ); 151 ``` 152 153 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`. 154 155 <!-- run-disable --> 156 157 ```javascript 158 var files = [ 159 './a.js', 160 './b.js' 161 ]; 162 163 function done( error ) { 164 if ( error ) { 165 console.error( 'Exit code: '+error.code ); 166 console.error( 'Signal: '+error.signal ); 167 throw error; 168 } 169 console.log( 'Done!' ); 170 } 171 172 var opts = { 173 'ordered': true 174 }; 175 176 parallel( files, opts, done ); 177 ``` 178 179 </section> 180 181 <!-- /.usage --> 182 183 <section class="notes"> 184 185 ## Notes 186 187 - Relative file paths are resolved relative to the current working directory. 188 - Ordered script output does **not** imply that scripts are executed in order. To preserve script order, execute the scripts sequentially via some other means. 189 - Script concurrency cannot exceed the number of scripts. 190 - If the script concurrency is less than the number of workers, the number of workers is reduced to match the specified concurrency. 191 192 </section> 193 194 <!-- /.notes --> 195 196 <section class="examples"> 197 198 ## Examples 199 200 <!-- run-disable --> 201 202 <!-- FIXME: re-enable running of code block once able to set `maxBuffer` configuration --> 203 204 <!-- eslint no-undef: "error" --> 205 206 ```javascript 207 var fs = require( 'fs' ); 208 var path = require( 'path' ); 209 var writeFileSync = require( '@stdlib/fs/write-file' ).sync; 210 var unlinkSync = require( '@stdlib/fs/unlink' ).sync; 211 var parallel = require( '@stdlib/utils/parallel' ); 212 213 var nFiles = 100; 214 var files; 215 var opts; 216 var dir; 217 218 function template( id ) { 219 var file = ''; 220 221 file += '\'use strict\';'; 222 223 file += 'var id;'; 224 file += 'var N;'; 225 file += 'var i;'; 226 227 file += 'id = '+id+';'; 228 file += 'N = 1e5;'; 229 file += 'console.log( \'File: %s. id: %s. N: %d.\', __filename, id, N );'; 230 231 file += 'for ( i = 0; i < N; i++ ) {'; 232 file += 'console.log( \'id: %s. v: %d.\', id, i );'; 233 file += '}'; 234 235 return file; 236 } 237 238 function createDir() { 239 var dir = path.join( __dirname, 'examples', 'tmp' ); 240 fs.mkdirSync( dir ); 241 return dir; 242 } 243 244 function createScripts( dir, nFiles ) { 245 var content; 246 var fpath; 247 var files; 248 var i; 249 250 files = new Array( nFiles ); 251 for ( i = 0; i < nFiles; i++ ) { 252 content = template( i.toString() ); 253 fpath = path.join( dir, i+'.js' ); 254 writeFileSync( fpath, content, { 255 'encoding': 'utf8' 256 }); 257 files[ i ] = fpath; 258 } 259 return files; 260 } 261 262 function cleanup() { 263 var i; 264 265 // Delete the temporary files... 266 for ( i = 0; i < files.length; i++ ) { 267 unlinkSync( files[ i ] ); 268 } 269 // Remove temporary directory: 270 fs.rmdirSync( dir ); 271 } 272 273 function done( error ) { 274 if ( error ) { 275 throw error; 276 } 277 cleanup(); 278 console.log( 'Done!' ); 279 } 280 281 // Make a temporary directory to store files... 282 dir = createDir(); 283 284 // Create temporary files... 285 files = createScripts( dir, nFiles ); 286 287 // Set the runner options: 288 opts = { 289 'concurrency': 3, 290 'workers': 3, 291 'ordered': false 292 }; 293 294 // Run all temporary scripts: 295 parallel( files, opts, done ); 296 ``` 297 298 </section> 299 300 <!-- /.examples --> 301 302 * * * 303 304 <section class="cli"> 305 306 ## CLI 307 308 <section class="usage"> 309 310 ### Usage 311 312 ```text 313 Usage: parallel [options] <script1> <script2> ... 314 315 Options: 316 317 -h, --help Print this message. 318 -V, --version Print the package version. 319 --cmd cmd Executable file/command. 320 --workers num Number of workers. 321 --concurrency num Number of scripts to run concurrently. 322 --ordered Preserve order of script output. 323 --uid uid Process user identity. 324 --gid gid Process group identity. 325 --maxbuffer size Max buffer size for stdout and stderr. 326 ``` 327 328 </section> 329 330 <!-- /.usage --> 331 332 <section class="examples"> 333 334 ### Examples 335 336 ```bash 337 $ 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 338 ``` 339 340 </section> 341 342 <!-- /.examples --> 343 344 </section> 345 346 <!-- /.cli --> 347 348 <section class="links"> 349 350 [node-js]: http://nodejs.org/ 351 352 </section> 353 354 <!-- /.links -->