さらに spec の実行を速くする

MySQL のデータを RAM Disk 上に置いて 3 倍の速度を達成したわけだが、さらなる高速化を考えた。

遅いところ

経験上、fixture を何度も読込んでいると遅いことがわかっている。fixture を before(:each) ではなく、before(:all) で読み込むようにすれば、回数が減るので速くなる。

ちなみに fixture は指定されたディレクトリ配下のファイル郡が
MySQL 上の一つの DB の各テーブルに対応させた状態にして管理している。
読込の単位は、このディレクトリ毎としている。

fixture の読込を減らす

同じ fixture を何度も読み込んでいることが問題なわけで、最初に一回読み込んだら、その snapshot を取って、再読み込みの際は snapshot まで戻せばよい。

MySQL に snapshot 機能は存在しない。
よって、 fixture を登録しているところで次のような処理を行うことで、これを実現した。

  1. 過去に fixture が読込済みで無い場合
    1. 通常の fixture の登録処理を行う
    2. mysqldump で DB 全体をバックアップする
  2. fixture が読込済みの場合
    1. mysql コマンドでバックアップからリストアする

速度

さらに 1.5 倍の速度が達成された。


Ram DISK : 366 sec
fixture を dump & restore : 232 sec
ちなみに mysql & mysqldump を TCP/IP 経由ではなく、UNIX DOMAIN Socket で接続すると 10 秒程度の向上がみられた(上記はこれを反映している)。

さらにさらに速くする

以下は未検証。

MySQL には snapshot 機能は無いわけだが、 Transaction は条件を限定すればそれっぽく使えるはず。


普通だったら処理の完了後は commit され、再度テストに使える状態ではなくなる。でも commit せずに rollback すれば、テストデータ投入時と同じ状態になるため、再度テストに使うことができるようになるはずである。


今作っているシステムは Transaction の「入り」、「出(commit)」を独自の Class によって管理しているので、「出(commit)」の部分では何も行わないようにして、fixture の再読込みで行うようにすれば、これは実現可能であると思う。


また、多分 MySQL の commit は「commit 後に実際に DB のデータを書き換える」構成のようなので、この方法によってかなりの速度向上が見込めるかと思う。