なっく日報

技術やら生活やらのメモ

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

せっかくなのでリンクを貼っておきます🌞