scalikejdbc asyncを試してみた

scalikejdbc-asyncでノンブロッキングなMySQLへのアクセスができると聞いて試してみた。 https://github.com/seratch/scalikejdbc-async

seratch さんが Activate にインスパイアされて作ったそうだ。

業務でPlay2を使うことがあるので今回の検証には

  • Playframework 2.1.3
  • MySQL 5.6.13(homebrewでいれたやつ)

を使ってみた。githubにはplayで使う場合のsampleもあって親切。

コネクションプールまわりは初期値とMaxを100にして新しい生成コストが発生しないようにした。

db.default.poolInitialSize=100
db.default.maxPoolSize=100
db.default.maxIdleMillis=1000
db.default.maxQueueSize=99
db.default.connectionTimeoutMillis=3000

PostgreSQLだとplay-sampleがうまく動くんだけどMySQLのときはinsertがうまく動かない。 作者のseratchさんに相談してみると、auto の代わりに localTxを使ったほうがいいとのことだったので 試してみたらそれでいけた。

こんなかんじに書いていたのを

def create(createdAt: DateTime = DateTime.now)(
implicit session: AsyncDBSession = AsyncDB.sharedSession, cxt: EC = ECGlobal): Future[Log] = {
  for {
    id <- withSQL {
      insert.into(Log).namedValues(column.createdAt -> createdAt)
    }.updateAndReturnGeneratedKey.future()
  } yield Log(id = id, createdAt = createdAt)
}

こういうふうに変更した。

def create(createdAt: DateTime = DateTime.now) = AsyncDB.localTx { implicit s =>
  for {
    id <- withSQL {
      insert.into(Log).namedValues(column.createdAt -> createdAt)
    }.updateAndReturnGeneratedKey.future()
  } yield Log(id = id, createdAt = createdAt)
}

試してみたコードはここにアップしといた。

https://github.com/wshino/scalikejdbc-async-mysql

同じ条件でscalikejdbcを使ったplay2を動かしてみて、abをかけてどの程度さばける多さが違うのか試してみた。 abの結果を10回取得してみて平均値を算出してみた。以下のようなかんじ。

/usr/local/apache/bin/ab -n 1000 -c 50 http://172.19.8.122:9000/

一度のリクエストでinsertを1回、selectを1回している。

結果としてscalikejdbcの場合は

  • Requests per second: 554.473

scalikejdbc-asyncの場合は

  • Requests per second: 919.9

おおむね1.6倍ほど高速になったので満足。 プロダクトに使うかどうかは未定だけどわりといいパフォーマンスは出てるんではなかろうか。 そのうちtypesafeが作ってるslickもasyncになるんじゃないかって期待してる。

Published: October 02 2013

  • category:
  • tags:
blog comments powered by Disqus