Hatena::ブログ(Diary)

scalaとか・・・ このページをアンテナに追加 RSSフィード Twitter

2015-06-26

Scala2.11.7からのJava8に対応した新しいコンパイルオプションを試してみた

| 10:38 | Scala2.11.7からのJava8に対応した新しいコンパイルオプションを試してみたを含むブックマーク Scala2.11.7からのJava8に対応した新しいコンパイルオプションを試してみたのブックマークコメント

"新しい" とは、今まで全部無名classにコンパイルしてたラムダを、invoke dynamic使って動的に生成するようになるとかそういうやつ。


ラムダ以外の最適化もやってるようですが?詳しくは知りません。

Scala 2.12から正式に入るらしいですが、(これ書いてる時点から見て)つい昨日くらい(2015/06/25)に出たScala2.11.7でも、明示的にオプションを指定すれば、実験的オプションとして使えるそうです。

内部の仕組みは、以下のScaladays2015のスライド見るとか、あとは各自ググってください

公式に書いてありますが、2.11.7においてJava8のバックエンドを最大限(?)に有効活用する方法は

https://github.com/scala/make-release-notes/blob/0d392b1aa1cbdd4ece528620996352acad7fa8bc/experimental-backend.md

  • Scala2.11.7以上に設定する
  • いくつかコンパイルオプションを指定
  • libraryDependenciesに専用の依存指定

で、つまり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です。

結果、

  • 普通にコンパイル 10401808 byte
  • Java8用オプション指定でコンパイル 6686854 byte

という結果でした。

36%ほど削減されて、オプション指定なしのときと比べて64%くらいのサイズになりましたね。

3分の1くらいまで減るかな―と、長年期待していたのですが、思ったほどは減らなくて少しがっかりしています・・・(´・ω・`)


これ、まだ最適化の余地あって、2.12.0のfinalが出る頃には3分の1くらいになったりしないんですかね・・・。

まぁそれにしても、36%削減は、他の方法では実現できないのでありがたいです。


さて

「jarのサイズ小さくなるから、scalaz 7.2.x の Scala 2.11 は Java7サポートやめて、このオプション指定するようにしようぜっ!」

と、提案することを以前から考えていたんですが、なんとsbtがこのオプションつけると色々正しく動かないようです!???

https://github.com/sbt/sbt/issues/2076

cleanでも直らない(targetディレクトリ丸ごと削除とか再起動必要?)、というかなり酷い感じで実用的じゃなさそうなので、少なくともsbtがなおるまでは、scalazへのその提案はできないですね・・・。

トラックバック - http://d.hatena.ne.jp/xuwei/20150626/1435282696