15
9

More than 5 years have passed since last update.

RailsのRSpecにとってDocker for Macはどれぐらい遅いのか?

Posted at

Railsを開発しているとRSpecの実行時間が遅くて開発効率が悪くなることがあります。
これは開発環境にDocker For Macを使っているからでしょうか?

背景

Docker For Macは遅いと言われます。

これは現在のDocker For Macでも遅いのでしょうか?

rawフォーマットは試していません

また、最新のDocker For Macでは速くなっているようです。

Docker for Macのディスクスループットを約2倍にする - Qiita

Docker Community Edition 17.12.0-ce-mac46 2018-01-09 (Stable)の更新で、ディスクスループットが320MiB/secから600MiB/secになるらしいので適用する。

APFS, SSD, High Sierraで有効。

現在Sierraを使っているので、試していません。

実行環境

  • MacBook Pro Late 2013
  • macOS Sierra 10.12.6
  • Docker Community Edition 17.12.0-ce-mac49 (21995)

手段

AWS EC2のAmazon Linux2インスタンスを使って試します。

Dockerの起動時間を抜いて計測するために

docker-compose run --service-ports web bash

を実行し、Docker上で

time bundle exec rspec spec/models/hoge_spec.rb

を実行します。

bash-4.3# time bundle exec rspec spec/models/hoge_spec.rb
No DRb server is running. Running in local process instead ...
Rack::File headers parameter replaces cache_control after Rack 1.5.
....................................................................................................................................................................................

Finished in 5.15 seconds
180 examples, 0 failures

real    0m23.581s
user    0m0.010s
sys 0m0.000s

realの値がtimeコマンドの結果です。
rspecコマンドの起動から終了までの実時間です。
これは「Rails環境の読み込み」時間を含みます。

Finished in 5.15 secondsがRSpecのテストの実行時間です。
差の18.4秒は「Rails環境の読み込み時間」です。

結果

以下の環境で試しました。

  • Docker For Mac
  • t2.micro
  • c4.large

いずれもDockerとdocker-composeでRailsアプリケーションを構成しています。

環境 real rspec real比率 rspec比率 Rails環境読み込み比率
Docker For Mac 0m23.581s 5.15 seconds - - -
t2.micro 0m14.258s 2.9 seconds 60% 56% 62%
c4.large 0m11.456s 2.52 seconds 49% 49% 48%

EC2上では40〜50%の時間短縮が計測されました。
単純にDocker for Macを使うとLinux上でDockerを使う場合の、2倍の時間が掛かると考えて良いでしょう。

Docker For Mac

bash-4.3# time bundle exec rspec spec/models/hoge_spec.rb
No DRb server is running. Running in local process instead ...
Rack::File headers parameter replaces cache_control after Rack 1.5.
....................................................................................................................................................................................

Finished in 5.15 seconds
180 examples, 0 failures

real    0m23.581s
user    0m0.010s
sys 0m0.000s

t2.micro

bash-4.3# time bundle exec rspec spec/models/hoge_spec.rb
No DRb server is running. Running in local process instead ...
Rack::File headers parameter replaces cache_control after Rack 1.5.
....................................................................................................................................................................................

Finished in 2.9 seconds
180 examples, 0 failures

real    0m14.258s
user    0m0.000s
sys 0m0.000s

c4.large

bash-4.3# time bundle exec rspec spec/models/hoge_spec.rb
No DRb server is running. Running in local process instead ...
Rack::File headers parameter replaces cache_control after Rack 1.5.
....................................................................................................................................................................................

Finished in 2.52 seconds
180 examples, 0 failures

real    0m11.456s
user    0m0.000s
sys 0m0.000s

考察

EC2の方が2倍近く速い

Docker For MacのDisk I/Oの遅さが原因に思えます。

Docker for Macのディスクスループットを約2倍にする - Qiita の効果とも一致します。
ファイルシステムのraw format化で、解消されることが期待できます。

c4.largeがt2.microより15%速い

他のインスタンスタイプ、例えば

  • t2.small
  • m4.large
  • c3.large

を使っても、t2.microとは差がありません。
これはc4.largeが(標準で)EBS 最適化インスタンスだからです。

C5、C4、M5、M4、P3、P2、G3、および D2 の各インスタンスの場合、この機能はデフォルトで有効になっており、追加料金は発生しません。

やはり、RailsのRSpecでは、Disk I/Oがボトルネックのようです。

その他の高速化

Rails application preloader

例えば、Springを使うと「Rails環境のロード時間」をスキップできます。

今回のテストのように、Rspecの実実行時間の8割が「Rails環境のロード時間」に使われている場合は、Rails application preloaderを使うと、テストの繰り返しやすさに効果的です。

 参考

スローテストを解消する

RailsのRSpecは、Rails環境のロード時間を除いても、遅いことが多いです。
特にモデルのテストの場合は、it毎にDBにテスト用のレコードを用意するためのinsert文を発行するためです。
必要なレコードが20件ある場合は、体感でわかるぐらい遅くなりました。

テスト数が多いと線形に遅くなります。
簡単に20秒掛かるテストセットが作れます。
Mac上で20秒掛かるテストが、Linux上で10秒になっても、テスト待ちのストレスはあまり解消されません。
ローカル環境とリモート環境を切り替える手間を考えると、テストの繰り返しやすさは上がりません。
地道にスローテストを解消した方が、テストの繰り返しやすさには効果が高いです。

before :allで複数のテストでまとめてテストデータを用意したり、FactoryGirl.createの代わりにFactoryGirl.buildを使ったりして、DBのレコード追加削除を減らすのが効果的です。

参考

15
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
9