はじめに
Async.js v2がリリースされたので紹介します。
1分でわかるまとめ
New features
- modularization対応
- ex)
const each = require('async/each')
- ex)
- ES2015対応
- npm i async-es
- ex)
import {each} from 'async-es'
- New functions
-
race
,mapValues
,timeout
,reflect
,refelectAll
,autoInject
,retryable
-
- 機能拡張
-
constant
,setImmediate
,nextTick
,auto
,queue
-
Breaking Changes
-
auto
- callbackを最後の引数に取るように引数の順序の変更
-
waterfall
- double callback時にエラーを返すように変更
-
map
- 常にArrayを返すように変更
-
filter
,reject
,some
,every
- 第一引数にエラー、第二引数に結果を返すように変更
-
queue
,priorityQueue
,cargo
-
q.tasks
=>q._tasks
-
q.saturated()
のタイミングの変更
-
Others
- Series, Limit系でStack Overflowが起こるようになった
- 全体的に遅くなった
New Functions
いくつか新しいFunctionが追加されました。
かっこいいドキュメントができましたので、詳細はこちらを参考にしてください。
http://caolan.github.io/async/
Breaking Changes
追記します。
Stack Overflow
https://github.com/caolan/async/issues/883#issuecomment-131959140
パフォーマンスの向上のためSetImmediate
を取り除いたためです。大きな同期処理が続く場合は気をつけてください、基本的には大丈夫だと思います。またAsync v1, Neo-Asyncでは同期的呼び出し時に非同期処理する処理がされているため、Stack Overflowは回避されています。
const _ = require('lodash');
const collection = _.times(3000);
const iterator = (value, next) => {
next();
};
const callback = _.noop;
current.eachSeries(collection, iterator, callback);
/*
* const iterator = (value, next) => {
* ^
*
* RangeError: Maximum call stack size exceeded
*/
File Sizes
version | async.js | async.min.js |
---|---|---|
v2.0.0 | 176kb | 20kb |
v1.5.2 | 38kb | 12kb |
async.jsはドキュメントも含まれるのであまり参考になりませんが、少しファイルサイズが大きくなっているのは内部的にlodashを使っているためだと思われます。
Performance
Asyncのパフォーマンスツールを使用して計測しました。
環境は以下のとおりです。
- Node v6.3.0
- Async v2.0.0 vs v1.5.2
$ git clone https://github.com/caolan/async
$ npm i
$ ./perf/benchmark.js v1.5.2
結果
Series系の一部ではSetImmediate
の呼び出しを取り除いたため早くなっていますが全体的に遅くなっています。遅くなった原因としては、lodashの使用と共通化に伴う変更が原因と思われます。
queue
ではDLL
という実装方法で爆速になりました。
全結果を載せておきます。
Comparing v1.5.2 with current on Node v6.3.0
--------------------------------------
each(10) v1.5.2 x 49,029 ops/sec ±32.11% (19 runs sampled), 0.0204ms per run
each(10) current x 49,381 ops/sec ±1.37% (28 runs sampled), 0.0203ms per run
current is faster
--------------------------------------
each(300) v1.5.2 x 9,472 ops/sec ±3.48% (29 runs sampled), 0.106ms per run
each(300) current x 4,813 ops/sec ±4.79% (27 runs sampled), 0.208ms per run
v1.5.2 is faster
--------------------------------------
each(10000) v1.5.2 x 329 ops/sec ±3.05% (29 runs sampled), 3.04ms per run
each(10000) current x 107 ops/sec ±8.39% (26 runs sampled), 9.36ms per run
v1.5.2 is faster
--------------------------------------
eachSeries(10) v1.5.2 x 32,026 ops/sec ±7.86% (26 runs sampled), 0.0312ms per run
eachSeries(10) current x 17,009 ops/sec ±42.55% (18 runs sampled), 0.0588ms per run
v1.5.2 is faster
--------------------------------------
eachSeries(300) v1.5.2 x 1,491 ops/sec ±17.82% (24 runs sampled), 0.670ms per run
eachSeries(300) current x 1,382 ops/sec ±4.72% (28 runs sampled), 0.724ms per run
current is faster
--------------------------------------
eachSeries(10000) v1.5.2 x 53.16 ops/sec ±2.87% (30 runs sampled), 18.8ms per run
eachSeries(10000) current x 43.90 ops/sec ±3.31% (26 runs sampled), 22.8ms per run
v1.5.2 is faster
--------------------------------------
eachLimit(10) v1.5.2 x 48,308 ops/sec ±5.09% (25 runs sampled), 0.0207ms per run
eachLimit(10) current x 37,282 ops/sec ±5.38% (26 runs sampled), 0.0268ms per run
v1.5.2 is faster
--------------------------------------
eachLimit(300) v1.5.2 x 3,928 ops/sec ±3.86% (27 runs sampled), 0.255ms per run
eachLimit(300) current x 2,992 ops/sec ±3.95% (27 runs sampled), 0.334ms per run
v1.5.2 is faster
--------------------------------------
eachLimit(10000) v1.5.2 x 118 ops/sec ±6.30% (25 runs sampled), 8.50ms per run
eachLimit(10000) current x 61.79 ops/sec ±46.85% (19 runs sampled), 16.2ms per run
v1.5.2 is faster
--------------------------------------
map(10) v1.5.2 x 50,711 ops/sec ±26.43% (22 runs sampled), 0.0197ms per run
map(10) current x 30,258 ops/sec ±26.17% (20 runs sampled), 0.0330ms per run
v1.5.2 is faster
--------------------------------------
map(300) v1.5.2 x 7,404 ops/sec ±11.10% (23 runs sampled), 0.135ms per run
map(300) current x 4,519 ops/sec ±4.02% (26 runs sampled), 0.221ms per run
v1.5.2 is faster
--------------------------------------
map(10000) v1.5.2 x 166 ops/sec ±46.03% (21 runs sampled), 6.04ms per run
map(10000) current x 109 ops/sec ±5.72% (27 runs sampled), 9.21ms per run
v1.5.2 is faster
--------------------------------------
mapSeries(10) v1.5.2 x 29,031 ops/sec ±17.98% (27 runs sampled), 0.0344ms per run
mapSeries(10) current x 14,085 ops/sec ±29.79% (16 runs sampled), 0.0710ms per run
v1.5.2 is faster
--------------------------------------
mapSeries(300) v1.5.2 x 1,537 ops/sec ±7.65% (29 runs sampled), 0.651ms per run
mapSeries(300) current x 1,349 ops/sec ±5.99% (25 runs sampled), 0.742ms per run
v1.5.2 is faster
--------------------------------------
mapSeries(10000) v1.5.2 x 48.81 ops/sec ±5.34% (28 runs sampled), 20.5ms per run
mapSeries(10000) current x 42.37 ops/sec ±3.58% (24 runs sampled), 23.6ms per run
v1.5.2 is faster
--------------------------------------
mapLimit(10) v1.5.2 x 45,862 ops/sec ±6.83% (26 runs sampled), 0.0218ms per run
mapLimit(10) current x 37,708 ops/sec ±3.91% (26 runs sampled), 0.0265ms per run
v1.5.2 is faster
--------------------------------------
mapLimit(300) v1.5.2 x 3,610 ops/sec ±4.73% (27 runs sampled), 0.277ms per run
mapLimit(300) current x 2,777 ops/sec ±5.14% (29 runs sampled), 0.360ms per run
v1.5.2 is faster
--------------------------------------
mapLimit(10000) v1.5.2 x 119 ops/sec ±3.83% (29 runs sampled), 8.40ms per run
mapLimit(10000) current x 82.18 ops/sec ±4.68% (28 runs sampled), 12.2ms per run
v1.5.2 is faster
--------------------------------------
eachOf(10) v1.5.2 x 61,832 ops/sec ±4.98% (27 runs sampled), 0.0162ms per run
eachOf(10) current x 38,973 ops/sec ±41.01% (23 runs sampled), 0.0257ms per run
v1.5.2 is faster
--------------------------------------
eachOf(300) v1.5.2 x 6,835 ops/sec ±32.66% (21 runs sampled), 0.146ms per run
eachOf(300) current x 5,119 ops/sec ±3.02% (29 runs sampled), 0.195ms per run
v1.5.2 is faster
--------------------------------------
eachOf(10000) v1.5.2 x 298 ops/sec ±3.93% (28 runs sampled), 3.35ms per run
eachOf(10000) current x 105 ops/sec ±11.86% (23 runs sampled), 9.50ms per run
v1.5.2 is faster
--------------------------------------
eachOfSeries(10) v1.5.2 x 32,839 ops/sec ±3.43% (28 runs sampled), 0.0305ms per run
eachOfSeries(10) current x 26,088 ops/sec ±5.12% (25 runs sampled), 0.0383ms per run
v1.5.2 is faster
--------------------------------------
eachOfSeries(300) v1.5.2 x 1,733 ops/sec ±3.21% (28 runs sampled), 0.577ms per run
eachOfSeries(300) current x 1,463 ops/sec ±3.47% (27 runs sampled), 0.684ms per run
v1.5.2 is faster
--------------------------------------
eachOfSeries(10000) v1.5.2 x 49.75 ops/sec ±4.28% (28 runs sampled), 20.1ms per run
eachOfSeries(10000) current x 42.45 ops/sec ±4.64% (24 runs sampled), 23.6ms per run
v1.5.2 is faster
--------------------------------------
eachOfLimit(10) v1.5.2 x 42,325 ops/sec ±6.78% (25 runs sampled), 0.0236ms per run
eachOfLimit(10) current x 26,073 ops/sec ±64.36% (19 runs sampled), 0.0384ms per run
v1.5.2 is faster
--------------------------------------
eachOfLimit(300) v1.5.2 x 3,112 ops/sec ±30.78% (20 runs sampled), 0.321ms per run
eachOfLimit(300) current x 2,723 ops/sec ±11.62% (25 runs sampled), 0.367ms per run
current is faster
--------------------------------------
eachOfLimit(10000) v1.5.2 x 120 ops/sec ±3.92% (29 runs sampled), 8.36ms per run
eachOfLimit(10000) current x 91.09 ops/sec ±3.70% (25 runs sampled), 11.0ms per run
v1.5.2 is faster
--------------------------------------
parallel(10) v1.5.2 x 52,151 ops/sec ±5.13% (25 runs sampled), 0.0192ms per run
parallel(10) current x 41,603 ops/sec ±6.28% (27 runs sampled), 0.0240ms per run
v1.5.2 is faster
--------------------------------------
parallel(100) v1.5.2 x 12,092 ops/sec ±5.12% (25 runs sampled), 0.0827ms per run
parallel(100) current x 11,884 ops/sec ±5.30% (25 runs sampled), 0.0841ms per run
Tie
--------------------------------------
parallel(1000) v1.5.2 x 1,578 ops/sec ±5.27% (27 runs sampled), 0.634ms per run
parallel(1000) current x 1,333 ops/sec ±6.03% (25 runs sampled), 0.750ms per run
v1.5.2 is faster
--------------------------------------
series(10) v1.5.2 x 28,878 ops/sec ±4.72% (27 runs sampled), 0.0346ms per run
series(10) current x 25,547 ops/sec ±4.50% (26 runs sampled), 0.0391ms per run
v1.5.2 is faster
--------------------------------------
series(100) v1.5.2 x 4,053 ops/sec ±5.02% (27 runs sampled), 0.247ms per run
series(100) current x 3,930 ops/sec ±6.58% (25 runs sampled), 0.254ms per run
Tie
--------------------------------------
series(1000) v1.5.2 x 337 ops/sec ±27.99% (22 runs sampled), 2.97ms per run
series(1000) current x 381 ops/sec ±12.79% (24 runs sampled), 2.63ms per run
Tie
--------------------------------------
waterfall(10) v1.5.2 x 12,545 ops/sec ±4.69% (28 runs sampled), 0.0797ms per run
waterfall(10) current x 22,550 ops/sec ±3.36% (27 runs sampled), 0.0443ms per run
current is faster
--------------------------------------
waterfall(100) v1.5.2 x 1,588 ops/sec ±5.08% (24 runs sampled), 0.630ms per run
waterfall(100) current x 2,966 ops/sec ±4.67% (27 runs sampled), 0.337ms per run
current is faster
--------------------------------------
waterfall(1000) v1.5.2 x 80.64 ops/sec ±52.33% (15 runs sampled), 12.4ms per run
waterfall(1000) current x 101 ops/sec ±60.69% (13 runs sampled), 9.86ms per run
Tie
--------------------------------------
queue(1000) v1.5.2 x 207 ops/sec ±42.54% (22 runs sampled), 4.82ms per run
queue(1000) current x 235 ops/sec ±13.33% (22 runs sampled), 4.26ms per run
Tie
--------------------------------------
queue(30000) v1.5.2 x 9.21 ops/sec ±6.84% (18 runs sampled), 109ms per run
queue(30000) current x 6.33 ops/sec ±8.19% (12 runs sampled), 158ms per run
v1.5.2 is faster
--------------------------------------
queue(100000) v1.5.2 x 0.08 ops/sec ±0.00% (1 run sampled), 1.20e+4ms per run
queue(100000) current x 2.17 ops/sec ±6.49% (5 runs sampled), 462ms per run
current is faster
--------------------------------------
queue(200000) v1.5.2 x 0.02 ops/sec ±0.00% (1 run sampled), 4.24e+4ms per run
queue(200000) current x 0.88 ops/sec ±307.06% (2 runs sampled), 1.14e+3ms per run
current is faster
--------------------------------------
some - no short circuit- false(500) v1.5.2 x 4,159 ops/sec ±6.45% (25 runs sampled), 0.240ms per run
some - no short circuit- false(500) current x 2,075 ops/sec ±7.24% (25 runs sampled), 0.482ms per run
v1.5.2 is faster
--------------------------------------
some - short circuit - true(500) v1.5.2 x 4,209 ops/sec ±5.47% (24 runs sampled), 0.238ms per run
some - short circuit - true(500) current x 2,517 ops/sec ±2.73% (29 runs sampled), 0.397ms per run
v1.5.2 is faster
--------------------------------------
every - no short circuit- true(500) v1.5.2 x 4,545 ops/sec ±6.82% (29 runs sampled), 0.220ms per run
every - no short circuit- true(500) current x 2,324 ops/sec ±4.81% (28 runs sampled), 0.430ms per run
v1.5.2 is faster
--------------------------------------
every - short circuit - false(500) v1.5.2 x 3,983 ops/sec ±6.26% (24 runs sampled), 0.251ms per run
every - short circuit - false(500) current x 2,241 ops/sec ±5.60% (28 runs sampled), 0.446ms per run
v1.5.2 is faster
--------------------------------------
(node:86129) DeprecationWarning: 'root' is deprecated, use 'global'
defer nextTick() v1.5.2 x 154,592 ops/sec ±3.57% (25 runs sampled), 0.00647ms per run
defer nextTick() current x 149,698 ops/sec ±4.84% (26 runs sampled), 0.00668ms per run
Tie
--------------------------------------
defer setImmediate() v1.5.2 x 94,268 ops/sec ±6.25% (27 runs sampled), 0.0106ms per run
defer setImmediate() current x 96,639 ops/sec ±4.65% (28 runs sampled), 0.0103ms per run
Tie
--------------------------------------
defer async.nextTick() v1.5.2 x 152,795 ops/sec ±5.08% (27 runs sampled), 0.00654ms per run
defer async.nextTick() current x 129,662 ops/sec ±5.02% (25 runs sampled), 0.00771ms per run
v1.5.2 is faster
--------------------------------------
defer async.setImmediate() v1.5.2 x 91,861 ops/sec ±7.86% (26 runs sampled), 0.0109ms per run
defer async.setImmediate() current x 86,145 ops/sec ±6.19% (25 runs sampled), 0.0116ms per run
v1.5.2 is faster
--------------------------------------
defer setTimeout() v1.5.2 x 680 ops/sec ±2.06% (29 runs sampled), 1.47ms per run
defer setTimeout() current x 676 ops/sec ±1.60% (4 runs sampled), 1.48ms per run
Tie
--------------------------------------
ensureAsync sync() v1.5.2 x 83,276 ops/sec ±1.83% (29 runs sampled), 0.0120ms per run
ensureAsync sync() current x 75,419 ops/sec ±4.37% (23 runs sampled), 0.0133ms per run
v1.5.2 is faster
--------------------------------------
ensureAsync async() v1.5.2 x 73,835 ops/sec ±7.30% (26 runs sampled), 0.0135ms per run
ensureAsync async() current x 69,525 ops/sec ±5.76% (24 runs sampled), 0.0144ms per run
v1.5.2 is faster
--------------------------------------
ensureAsync async noWrap() v1.5.2 x 89,438 ops/sec ±7.30% (25 runs sampled), 0.0112ms per run
ensureAsync async noWrap() current x 85,166 ops/sec ±6.13% (24 runs sampled), 0.0117ms per run
Tie
--------------------------------------
current faster overall (1920ms total vs. 54700ms total)
v1.5.2 won more benchmarks (36 vs. 7)
まとめ
Async v2ではモジュール化やES2015対応、新しいFunctionの実装がされました、ぜひ使ってみてください。またlodashの開発者なども携わっておりとても勉強になります。
すでにPromiseが主流になっていますが、今後ももうしばらくAsyncの更新は続くと思います。