fastparallel
Advanced tools
Comparing version 1.7.2 to 2.0.0
{ | ||
"name": "fastparallel", | ||
"version": "1.7.2", | ||
"version": "2.0.0", | ||
"description": "Zero-overhead asynchronous parallel/each/map function call", | ||
@@ -5,0 +5,0 @@ "main": "parallel.js", |
@@ -15,2 +15,5 @@ 'use strict' | ||
var queue = reusify(options.results ? ResultsHolder : NoResultsHolder) | ||
var queueSingleCaller = reusify(SingleCaller) | ||
var goArray = options.results ? goResultsArray : goNoResultsArray | ||
var goFunc = options.results ? goResultsFunc : goNoResultsFunc | ||
@@ -20,3 +23,2 @@ return parallel | ||
function parallel (that, toCall, arg, done) { | ||
var i | ||
var holder = queue.get() | ||
@@ -31,12 +33,7 @@ done = done || nop | ||
holder._release = release | ||
if (typeof toCall === 'function') { | ||
holder._count = arg.length | ||
for (i = 0; i < arg.length; i++) { | ||
toCall.call(that, arg[i], holder.release) | ||
} | ||
goFunc(that, toCall, arg, holder) | ||
} else { | ||
holder._count = toCall.length | ||
for (i = 0; i < toCall.length; i++) { | ||
toCall[i].call(that, arg, holder.release) | ||
} | ||
goArray(that, toCall, arg, holder) | ||
} | ||
@@ -54,2 +51,46 @@ | ||
} | ||
function singleCallerRelease (holder) { | ||
queueSingleCaller.release(holder) | ||
} | ||
function goResultsFunc (that, toCall, arg, holder) { | ||
var singleCaller = null | ||
holder._count = arg.length | ||
holder._results = new Array(holder._count) | ||
for (var i = 0; i < arg.length; i++) { | ||
singleCaller = queueSingleCaller.get() | ||
singleCaller._release = singleCallerRelease | ||
singleCaller.parent = holder | ||
singleCaller.pos = i | ||
toCall.call(that, arg[i], singleCaller.release) | ||
} | ||
} | ||
function goResultsArray (that, toCall, arg, holder) { | ||
var singleCaller = null | ||
holder._count = toCall.length | ||
holder._results = new Array(holder._count) | ||
for (var i = 0; i < toCall.length; i++) { | ||
singleCaller = queueSingleCaller.get() | ||
singleCaller._release = singleCallerRelease | ||
singleCaller.parent = holder | ||
singleCaller.pos = i | ||
toCall[i].call(that, arg, singleCaller.release) | ||
} | ||
} | ||
function goNoResultsFunc (that, toCall, arg, holder) { | ||
holder._count = arg.length | ||
for (var i = 0; i < arg.length; i++) { | ||
toCall.call(that, arg[i], holder.release) | ||
} | ||
} | ||
function goNoResultsArray (that, toCall, arg, holder) { | ||
holder._count = toCall.length | ||
for (var i = 0; i < toCall.length; i++) { | ||
toCall[i].call(that, arg, holder.release) | ||
} | ||
} | ||
} | ||
@@ -77,9 +118,24 @@ | ||
function ResultsHolder (_release) { | ||
function SingleCaller () { | ||
this.pos = -1 | ||
this._release = nop | ||
this.parent = null | ||
this.next = null | ||
var that = this | ||
this.release = function (err, result) { | ||
that.parent.release(err, that.pos, result) | ||
that.pos = -1 | ||
that.parent = null | ||
that._release(that) | ||
} | ||
} | ||
function ResultsHolder () { | ||
this._count = -1 | ||
this._callback = nop | ||
this._results = [] | ||
this._results = null | ||
this._err = null | ||
this._callThat = null | ||
this._release = null | ||
this._release = nop | ||
this.next = null | ||
@@ -89,9 +145,10 @@ | ||
var i = 0 | ||
this.release = function (err, result) { | ||
this.release = function (err, pos, result) { | ||
that._err = that._err || err | ||
that._results[i] = result | ||
that._results[pos] = result | ||
if (++i === that._count || that._count === 0) { | ||
that._callback.call(that._callThat, that._err, that._results) | ||
that._callback = nop | ||
that._results = [] | ||
that._results = null | ||
that._err = null | ||
@@ -98,0 +155,0 @@ that._callThat = null |
@@ -8,13 +8,13 @@ # fastparallel [![Build Status](https://travis-ci.org/mcollina/fastparallel.svg?branch=master)](https://travis-ci.org/mcollina/fastparallel) | ||
* non-reusable `setImmediate`: 2172ms | ||
* `async.parallel`: 5739ms | ||
* `async.each`: 3015ms | ||
* `async.map`: 4981ms | ||
* `parallelize`: 3125ms | ||
* `fastparallel` with results: 2391ms | ||
* `fastparallel` without results: 2350ms | ||
* `fastparallel` map: 2351ms | ||
* `fastparallel` each: 2359ms | ||
* non-reusable `setImmediate`: 2453ms | ||
* `async.parallel`: 4269ms | ||
* `async.each`: 3286ms | ||
* `async.map`: 3822ms | ||
* `parallelize`: 3057ms | ||
* `fastparallel` with results: 2883ms | ||
* `fastparallel` without results: 2620ms | ||
* `fastparallel` map: 2839ms | ||
* `fastparallel` each: 2604ms | ||
These benchmarks where taken via `bench.js` on iojs 2.2.1, on a MacBook | ||
These benchmarks where taken via `bench.js` on node v4.0.0, on a MacBook | ||
Pro Retina 2014. | ||
@@ -29,2 +29,5 @@ | ||
__The major difference between version 1.x.x and 2.x.x is the order of | ||
results__, this is now ready to replace async in every case. | ||
## Example for parallel call | ||
@@ -98,4 +101,3 @@ | ||
The `results` array will be non-ordered, and the `done` function will | ||
be called only once, even if more than one error happen. | ||
The `done` function will be called only once, even if more than one error happen. | ||
@@ -102,0 +104,0 @@ This library works by caching the latest used function, so that running a new parallel |
29
test.js
@@ -321,1 +321,30 @@ var test = require('tape') | ||
}) | ||
test('accumulates results in order', function (t) { | ||
t.plan(8) | ||
var instance = parallel({ | ||
released: released | ||
}) | ||
var count = 2 | ||
var obj = {} | ||
instance(obj, [something, something], 42, function done (err, results) { | ||
t.notOk(err, 'no error') | ||
t.equal(count, 0, 'all functions must have completed') | ||
t.deepEqual(results, [2, 1]) | ||
}) | ||
function something (arg, cb) { | ||
t.equal(obj, this) | ||
t.equal(arg, 42) | ||
var value = count-- | ||
setTimeout(function () { | ||
cb(null, value) | ||
}, 10 * value) | ||
} | ||
function released () { | ||
t.pass() | ||
} | ||
}) |
18610
516
117