uehaj's blog

Grな日々 - GroovyとかGrailsとかElmとかRustとかHaskellとかReactとかFregeとかJavaとか -

GroovyServの小技シリーズ2 scalacを高速化する

つい昨日0.4がリリースされたGroovyServですが、相当バグフィックス入ってるのでお薦めです。

GroovyServはGroovyスクリプトの起動を高速化するものですが、Groovyから呼び出すものはGroovyに限りません。つまりJVM上で動くものならなんでも起動の高速化が理論的には*1可能です。

たとえば、scalaの処理系とかscalaで書かれたプログラムもその例外ではないです。

scalaには、scalacというコマンドがあってscalaコードをコンパイルします。まずscalacを常駐させて起動を高速化してみましょう。

その前にオリジナルのscalacの実行速度。(Mac OS X, Scala 2.8.0-final使用)
コンパイル対象(hello.scala)は以下の通り。

object HelloWorld {
  def main(args: Array[String]) {
    println("Hello Scala World!")
  }
}

オリジナルのscalacの実行速度

コンパイルしてみます。

$ time scalac hello.scala
real 0m7.431s

7秒以上かかります*2。結構な待たされ感があります。

scalacをGroovyServ上で常駐実行させた場合

これをGroovyServから呼び出してみます。前準備としては以下のようにscalaのjarを~/.groovy/lib/にコピー。
CLASSPATH通してもいいんだけど面倒なんで。

cp $SCALA_HOME/lib/scala*.jar ~/.groovy/lib/

さて、scalacをGroovyServで実行してみますと。

$ time groovyclient -Dscala.home=$SCALA_HOME -e 'scala.tools.nsc.Main.main(args);' -- hello.scala

real 0m1.256s

7秒が1秒少しに短縮されてます。なかなかです。あ、やってることはscalacのシェルスクリプトの中身を除いて、main()を含むクラスを呼び出しているだけです。

fscの場合

さて、当然ここでfsc(Fast Scala Compiler)はどうなの、という話になりますね。
fscは、scalacを常駐させてコンパイルを速くするものです。GroovyServと似てますが、scalaソースコードのコンパイル専門であり、かつクライアントもJavaじゃなくてScalaか、で書かれているという違いがあります。
やってみます。

$ time fsc hello.scala

real 0m1.071s

1秒ぐらいですね。GroovyServがやや負けてますが、まあ「汎用対専用」ということで、汎用としてはいい線いってるんではないでしょうか。

fscをGroovyServ上で常駐実行させた場合

以上。とも思ったのですが、ここで終わると記事にならないので考える。

・・・いやまてよ、fsc自体Pure JavaのというよりPure ScalaJVM上で動くプログラムなんだから、fscをGroovyServで常駐させたらどうなるんだろう?ということで実験。

$ time groovyclient -Dscala.home=$SCALA_HOME -e 'scala.tools.nsc.CompileClient.main(args);' -- hello.scala

real 0m0.337s

0.3秒台!爆速達成!
このぐらい違うと体感でかなりちがってきます。

ちなみにJVMプロセスが2個常駐していることになります。

考察

高速化した理由は、推測ですが,初期化処理も分離されるからだと思われます。
scalacは、

  • 1. 起動
  • 2. 初期化
  • 3. コンパイル

というようにつくられていて、GroovyServだけでは1が削減されるだけなので2,3は減らない。
fscでは、2がスキップされるように作られているが、1,3は減らない。

GroovyServとfscを組み合わせることで、1,2が削減され、3だけ実行するようになります。

(゚Д゚)ウマー

以降は、できてもいないなのであまり良くないことですが、可能性としてだけ。あくまで可能性ですが、うまいことGroovyコード断片を書いて、都度は3から実行できるようにすれば、GroovyServだけで同等の高速化ができる可能性があります。柔軟なGroovyであるがゆえです。ここらへんがNailGunとの差別化ポイントとなるところの1つです。できないかもしれませんが。

*1:いろいろな都合で実際にはできないものもあります。

*2:以下、時間は3〜4回やって4回目ぐらいの値です。