MongoDB Driverとcoの相性がとてもよろしい件🌞
Node.js v4 + coで非同期処理のパフォーマンスを測定したところ、学びがあったのでメモ。
きっかけ
某勉強会で非同期処理について調べてみたところ、coを使った書き方がかなりイケてるなと思いました。
が、パフォーマンス的に心配。
そこで定番のAsync.jsと比較してみることにしました。
計測までの流れ
せっかくだからDBにつなごうと思い、モンゴさんと繋ぎました。
準備
npm i co async mongodb
ソースコード
'use strict'; const async = require('async'); const co = require('co'); const MongoClient = require('mongodb').MongoClient; const TRY_TIMES = 1000; const url = 'mongodb://localhost:27017/test'; function testCo() { return new Promise((resolve, reject) => { co(function* () { const db = yield MongoClient.connect(url); const start = Date.now(); for (let i = 0; i < TRY_TIMES; i++) { const results = yield db.collection('test').find().limit(10).toArray(); // console.log(results.length); } db.close(); resolve(Date.now() - start); }).catch((err) => { console.error(err.stack); reject(err); }); }); } function testAsync() { return new Promise((resolve, reject) => { MongoClient.connect(url, (err, db) => { const start = Date.now(); async.times(TRY_TIMES, (n, next) => { db.collection('test').find().limit(10).toArray((err, results) => { // console.log(results.length); next(err); }); }, (err) => { if (err) { return reject(err); } db.close(); resolve(Date.now() - start); }); }); }); } co(function* () { const asyncElapsed = yield testAsync(); const coElapsed = yield testCo(); console.log(`async=${asyncElapsed}ms, co=${coElapsed}ms`); })
実行
> node co.js async=761ms, co=821ms
考察
- 予想通りcoの方が遅い
- でも1000回ループさせて60ms差ならそんな悪くない気が
- MongoDB Driverのv2系はコールバックを渡さないとPromiseを返す仕様になっていてcoと相性がよろしい
まとめ
coをAsync/Awaitまでのつなぎとして使えそうな手応えがつかめました。
もうちょい調査は続けてみますが、エラー処理とかで問題なければ使いそうな気がします。
(もし、既に使っているよとか、書き方が変とか、こんな懸念があるよとか、ご指摘あれば、コメントいただければ幸いです)
おまけ
↓のサイトはCallback Hell 〜 Async/Awaitの書き方が比較されていて、とても参考になりました。
The long road to Async/Await in JavaScript - Thomas Hunter II
せっかくなのでリンクを貼っておきます🌞