"新しい" とは、今まで全部無名classにコンパイルしてたラムダを、invoke dynamic使って動的に生成するようになるとかそういうやつ。
ラムダ以外の最適化もやってるようですが?詳しくは知りません。
Scala 2.12から正式に入るらしいですが、(これ書いてる時点から見て)つい昨日くらい(2015/06/25)に出たScala2.11.7でも、明示的にオプションを指定すれば、実験的オプションとしてですが、使えるそうです。
内部の仕組みは、以下のScaladays2015のスライド見るとか、あとは各自ググってください
公式に書いてありますが、2.11.7においてJava8のバックエンドを最大限(?)に有効活用する方法は
で、つまりsbtのbuild.sbtで言うと以下のような感じ
libraryDependencies += "org.scala-lang.modules" %% "scala-java8-compat" % "0.5.0" scalacOptions ++= List("-Ybackend:GenBCode", "-Ydelambdafy:method", "-target:jvm-1.8") scalaVersion := "2.11.7"
コンパイルオプション追加だけではあまり意味なくて(それでも新しいバックエンド使われて一部最適化されるらしいが)、2.11.7時点ではscala-java8-compatの依存を明示的に追加しないとラムダがinvoke dynamicになってjarサイズ削減の効果が得られないようです、注意しましょう。
コンパイラ側が
「コンパイルオプションが指定されていて、かつscala-java8-compatがpathにある場合」
という条件で最適化するようです
(つまりscala-java8-compatが存在するかどうかでコンパイラ自体の動作が全然異なるという、少し気持ち悪い?挙動)
さて、それでjarサイズが大きいことで有名な(?) Scalazをこれでコンパイルしてみました。使ったのは、これ書いてる現在の最新のtreeです。
結果、
という結果でした。
- https://github.com/xuwei-k/scalaz/commit/2ea3e735c1b19554d9de2ed4
- https://travis-ci.org/xuwei-k/scalaz/builds/68410963
36%ほど削減されて、オプション指定なしのときと比べて64%くらいのサイズになりましたね。
3分の1くらいまで減るかな―と、長年期待していたのですが、思ったほどは減らなくて少しがっかりしています・・・(´・ω・`)
これ、まだ最適化の余地あって、2.12.0のfinalが出る頃には3分の1くらいになったりしないんですかね・・・。
まぁそれにしても、36%削減は、他の方法では実現できないのでありがたいです。
さて
「jarのサイズ小さくなるから、scalaz 7.2.x の Scala 2.11 は Java7サポートやめて、このオプション指定するようにしようぜっ!」
と、提案することを以前から考えていたんですが、なんとScala2.11.7ではsbtがこのオプションつけると色々正しく動かないようです!???
追記: Scala2.11.8では直ったようです
https://github.com/sbt/sbt/issues/2076
cleanでも直らない(targetディレクトリ丸ごと削除とか再起動必要?)、というかなり酷い感じで実用的じゃなさそうなので、少なくともsbtがなおるまでは、scalazへのその提案はできないですね・・・。
他にも試したので追記