ククログ

株式会社クリアコード > ククログ > test-unitで並列テスト実行

test-unitで並列テスト実行

test-unitをメンテナンスしている須藤です。最近@tikkssとtest-unitを改良しているので紹介します。テストを並列実行できるように改良しています。

きっかけ

@tikkssはRed Data Toolsに参加しているのですが、red-datasetsのテストが遅いのをどうにかするということに取り組んでいました。いくつかのケースはテスト内容を減らすことで高速化しましたが、その方法で高速化できるものは一通り対応しつくしました。これ以上の高速化はtest-unitでテストを並列実行できるようにするしかないのでは!?という気持ちになったので@tikkssと一緒に取り組み始めました。

週に1回、お昼の30分で一緒に取り組んでいます。最近は毎週水曜日の12:15-12:45に取り組んでいます。私は東京に住んでいて@tikkssは島根に住んでいるので、Jitsi Meetを使ってオンラインで取り組んでいます。取り組んでいる様子はYouTubeでライブ配信しています。アーカイブもしているので、あとから視聴することもできます。

予定

次の3種類の並列実行をサポートする予定です。

  • Threadベース
  • マルチプロセスベース
  • Ractorベース

現状

実はまだ完成していないのですが、一部動くものはできています。Threadを使った並列実行機能は動いていて、マルチプロセスやRactorを使った並列実行機能はまだ動いていません。この間リリースしたtest-unit 3.6.3Threadを使った並列実行機能は入っているので、興味がある人は--parallelオプションを使ってみてください。

なお、普通はThreadを使って並列実行してもテストは速くなりません!RubyでThreadを使って速くなるのはIO待ちが多いときです。RubyのThreadは同時にRubyのコードを実行できないからです。IO待ちになると他のThreadに処理が移るのでIOを待っている間も違う処理をできます。待ち時間を有効活用できるのでIO待ちがある場合は速くなるというわけです。

普通はテスト中にIO待ちになることはそんなに多くありません。そのためThreadを使った並列実行機能で速くなることはほぼないんですねぇ。むしろ、オーバーヘッドがある分、微妙に遅くなります。

そんなに速度向上を期待できないのにどうして実装したかというと、練習のためです。まずは一番簡単なThreadベースで汎用的な並列実行の仕組みを用意して、その上でマルチプロセスベース・Ractorベースの仕組みを実装していこうとしています。

今後

Threadベースの仕組みが動くようになったので、マルチプロセスベースの実装に着手し始めています。まだ、各プロセス間でどのように通信するかも決まっていません。今後、プロセス間の通信プロトコルや、実行するテストの情報をどうやって共有するか、テスト結果をどう収集するかなどを検討して実装していくことになります。

マルチプロセスベースの仕組みが仕上がったらRactorベースの仕組みに着手する予定です。

マルチプロセスベースの仕組みは速くなると思いますが、Ractorベースの仕組みは速くなるかどうかはやってみないとわからないなぁと思っています。

また、こまごました使い勝手の部分の作り込みもまだなのでそのあたりも整備していかないといけません。たとえば、各ワーカーにワーカーIDのような情報を渡してあげないといけません。並列実行する場合、各ワーカーが別々のリソース(たとえば、Railsアプリケーションならデータベースとか)を使った方が速度がでます。共有リソースをロックしたりする必要がなくなるからです。ワーカーIDのような情報があると各ワーカーごとに独立したリソースを確保しやすくなります。

まとめ

最近、@tikkssと一緒に取り組んでいるtest-unitの並列実行対応について紹介しました。これまでどうやって設計・実装してきたかが気になる人はアーカイブtest-unit/test-unit#235に残されている@tikkssのメモを参照してください。一緒に開発したい人はRed Data Toolsのチャットに来てください。