もっと速いユニットテストを頼む

今やってるプロジェクトのテストケースとテストデータが結構な量あり、私のマシンで実行すると15分以上かかってしまいます。テスト環境は、 VMwareでCentOSをゲストOSにして、Windows7をホストOSにしてます。ノートPCは8Gメモリ、5400rpmのHDD。一番の原因は、5400rpmのHDDかつVMwareのゲストOSのディスクI/Oが遅いということです。そのためテストデータ(Fixture)をテストケースごとにリストアしてという動作に時間がかかります。

まずは、HDDをIntel SSDに変えてこれを10分以下に短縮できました。SSD快適すぎる。IntelSSDは移行ツールも無料で付いてるので便利です。

SSDで快適にはなりましたが、もっと速くがロマンというもの。また、SSDにディスクI/O発行しまくるのはSSDの寿命を縮めるので精神的に良くないです。(SSDはデータブロックの書き換え回数に上限があるので)

ということで、OS起動時に、MySQLのデータフォルダをメモリに全部載せてしまって、シャットダウンするときにディスクに戻すというアイディアを実行しました。

結論から言うと、テストは5分ぐらいに収まりました!

[追記] phpのxdebugはテスト実行中はOFFにしたほうが良いです。 3分ぐらい短縮できました。

メモリに載せるとは、Linuxのtmpfsというメモリファイルシステムの機能を使って(WindowsのRAM diskみたいなやつ)、そこにMySQLデータをmvコマンドで移動させるだけです。CentOSのようなRedhatクローンのLinuxだと、標準で/dev/shmというディレクトリがtmpfsとしてマウントされているので、今回はそれを利用します。CentOSに2Gのメモリを割り当てたら、/dev/shmは500Mほどマウントされました。


ちなみに、テストデータは一度バックアップを取っておいて、いつでも吹っ飛んで良いようにします。(OSがクラッシュすると全部消えるので)

/etc/rc.d/init.d/mysql stop
cp -rp /var/lib/mysql /var/lib/mysql-bkup


今回2つのスクリプトを作りました。

  • onMemoryDeploy.sh:
    • DBファイルを/dev/shmに移動させて、/var/lib/mysqlにリンクを貼るスクリプト(その逆の動作も)
  • onMemoryMySQL:
    • CentOSのinit script。 /etc/rc.d/init.d/以下においてOS起動、停止時にonMemoryDeploy.shを実行する

Ubuntuの人とかMacの人はinit scriptを自作して、onMemoryDeploy.shのパラメータを変えればいけると思います。


ではまず、onMemoryDeploy.shから。
やっている事は、mysql停止して、tmpfsにデータをmvして、/var/lib/mysqlにシンボリックリンクを貼ってるだけです。最初の5行のパラメータを自分の環境用に変更すればうごくと思います。


次に、CentOS用のinit script.


今回は、2つのスクリプトを下記のディレクトリに設置。

/root/onMemoryDeploy.sh
/etc/rc.d/init.d/onMemoryMySQL

そして、起動時に実行されるようにする

/sbin/chkconfig --add onMemoryMySQL
/sbin/chkconfig onMemoryMySQL on

これだけです。Enjoy!


余談
CentOS用のinit scriptで、/var/lock/subsys/onMemoryMySQLにファイルを作っているのは、このファイルが存在しないと停止時に実行してくれなくなるので。実験中は何度かデータ消しました。。。