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をGroovyServ上で常駐実行させた場合
これをGroovyServから呼び出してみます。前準備としては以下のようにscalaのjarを~/.groovy/lib/にコピー。
CLASSPATH通してもいいんだけど面倒なんで。
さて、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 ScalaのJVM上で動くプログラムなんだから、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つです。できないかもしれませんが。