prove の並列実行の話
perl でテストスクリプトを実行する prove コマンドには -j という並列実行するオプションがあります。たとえば prove -j2 とすると、2プロセス作って並列実行されます。
ただ、ウチのところのテストコードは基本的にストアドプロシージャのテストなので、DB をあれこれしている間は、他のテストを並列で流すことができません。
その辺の事情はだいぶ前にも書いてますが、まあこんな感じです。
DB を使う Web アプリって、同時にテスト流すとおかしくなるよね?
で、DB が1個しかないから、テストデータを流すときに主キーがかぶってエラーになったり、ゴミデータが残って、それが外部キー制約とかあったりして消せなくて、次のテストデータのロードでエラーになってこけたり。とにかく同時にテストを流すとめちゃくちゃになるんですよ。
で、いろいろ考えたんだけど、幸いにして、ウチのプロジェクトではテスト用の専用モジュールを作っているから、テスト用モジュールの中で排他制御しちゃうのが一番いいのかな、とか思ったり。
とはいえ、テストコードの実行に 10 分以上かかっている現状を、手をこまねいてみてるのもなんだかなー、と top の出力とかテストコードの実行を眺めてたら、ふと思いつきました。
「ん?スクリプトのコンパイルも意外と馬鹿にならないオーバーヘッドあるよな?並列化したらこの分だけでも少しは早くなるんじゃね?」
で、ためしに -j2 つけて実行してみました。
通常(並列なし)
$ time prove *.t ... All tests successful. Files=696, Tests=36885, 774 wallclock secs (10.36 usr 2.17 sys + 573.82 cusr 42.36 csys = 628.71 CPU) Result: PASS real 12m54.111s user 9m44.332s sys 0m44.549s
並列(-j2)
$ time prove -j2 *.t ... Files=696, Tests=36885, 565 wallclock secs (13.94 usr 2.70 sys + 585.98 cusr 43.60 csys = 646.22 CPU) Result: PASS real 9m24.724s user 10m0.077s sys 0m46.327s
まあ相変わらず時間はかかっていますが、ずいぶん早くなりました。(30%くらい早くなった)。っていうか -j2 つける以外なにもチューニングしてないわけで、もっと早くからやっておけばよかった orz*1
「DB 使うからウチのテストは並列で流せないよ」とあきらめないで、試してみるといいんじゃないかなー、と思います。*2テストコードのファイル数が少なかったりテストが短いと、ロックを取ったりする分のオーバーヘッドのほうが大きいかもしれませんが、ある程度の規模なら効果が出るんじゃないかな。
参考
Jenkins はじめました + ほか3つ(mixi Engineers' Blog)
データベースのテストってみんなどうやってるんだろ?