sbtは常駐させよう!

  • 19
    いいね
  • 0
    コメント

年末の今日この頃、皆様いかがお過ごしでしょうか。

今日はScalaのコンパイル速度に関する簡単な計測結果をお届けしたいと思います。

結論はタイトルに書いてあるとおりで、要はScalaのプログラムをコンパイルするときはsbtを毎回立ち上げるのではなく、sbtシェルを立ち上げたままにしようということです。なぜかというと、コンパイル速度が大体くらい違ってくるからです。

さて、今回はsbtを毎回立ち上げてソースをコンパイルした場合と、sbtシェルの中で繰り返しコンパイルをした場合のコンパイル速度の違いについての計測結果を調べてみました。

計測環境は以下の通りです:

  • CPU: Intel Core i5-6500 3.20GHz
  • MEM: 32GB
  • OS: Ubuntu Linux 16.04 64-bit LTS
  • Scala: 2.12.1
  • sbt: 0.13.13
  • JDK: 1.8.0_111

計測に使ったScalaコードは

https://github.com/onion-lang/onion

にあります(7632行(テスト込み))。まずは、コマンドラインから

$ sbt clean test:compile

とタイプしてコンパイルが終了するまでの時間です。これには、16secかかったので、コード行数をかかった時間で割ると、約477行/秒ということになります(厳密には、コマンドラインから起動するとbuild.sbtを読み込む初期化時間があるので若干割引く必要がありますが、sbtをいったん起動してからclean compileした時間はあまり変わりませんでした)。

一方、sbtシェル中で

> clean
> test:compile

を二度目以降に行った場合の時間ですが、7secでした。同じくコード行数をかかった時間で割ると、約1090行/秒となります。これはcleanして全コンパイルした場合の差であり、現実的には差分コンパイルになるため、そこまで極端な差は出ないと思いますが、それでも倍以上コンパイル速度に差が出るのは注目すべきです。

他のマシンでも同様の実験をしてみましたが、おおむね似たような結果でした。sbtシェル内でずっとコンパイルを繰り返しているとそのうちメモリが枯渇する、という現象が稀に起きるのでたまにsbtを再起動するのはいいかもしれませんが、基本的にはsbtは起動したままにしておくのが良い使い方だと言えるでしょう(また、これは好みにもよりますが、~compileなどを使っておけばコードが変更されたら即再コンパイルされるので良いです)。

おまけ:Kotlinのコンパイル速度

計測環境

  • CPU: Intel Core i5-6500 3.20GHz
  • MEM: 32GB
  • OS: Ubuntu Linux 16.04 64-bit LTS
  • Kotlin: 1.0.6
  • Gradle: 3.2.1 (org.gradle.daemon=true)

コードベースベースとしては、

https://github.com/kmizu/kollection

利用しました(2055行(テスト込み))

コマンドとしては、

$ gradle clean compileTestKotlin

で、Gradle Daemonが有効な状態で計測するため、2回目以降の値を取りました。結果として、すべてコンパイルするために3secかかったので、685行/秒となり、sbtを常駐させない状態のコンパイル速度よりは速いものの、sbtを常駐させた場合よりは遅いという結果になりました。Kotlinに対してコンパイル速度が遅いというイメージを抱いている方はそれほど多くないとは思いますが、Scalaといい勝負をするくらいにはコンパイルが遅い(あるいはイメージほどScalaのコンパイル速度は遅くない)のでした。

なお、実際には繰り返し計測を行っていますが、計測結果ごとのブレはそれほど大きくない印象です。Scalaのコードの場合、implicit parameterの多用具合などによってもコンパイル速度は変わり得るので、もっとがりがりとimplicit parameterなどを使った場合にどのようになるかも調べてみたいところですが、今日はここまで。

他の方による追試結果などもあれば教えていただけると嬉しいです。