Scalaでコンパイルが遅くなった場合にprofileを取る方法について検索すると Speeding Up Compilation Time with scalac-profiling | The Scala Programming Language という記事がでてきたり、 https://github.com/scalacenter/scalac-profiling を利用した方法がヒットしますが、ここにでてくるpluginはscala 2.13では(そのままでは)使えなかったり、もう少し楽な別の方法があったりするのでまとめました。
出力イメージ
こんな感じのグラフの生成を目指します。(といってもほぼ公式が提供してるツールだけで出来る)
某projectでScala 2.13で
— Kenji Yoshida (@xuwei_k) 2022年10月29日
scalacOptions ++= Seq("-Yprofile-trace", "適当なファイル名")
してgraph出したんですけど、左下に黄色く飛び出てるのがshapeless 2のGenericなどを使ったメタプロ部分です
(使い方気をつけないとすぐコンパイル速度遅い原因になる、つらい)https://t.co/q4LScHTtdO pic.twitter.com/iGRvEIOwGZ
shapeless 2のHListに対して、以下のようにindexアクセスをさせてprofileをとったときに、綺麗に数値の大きさに比例してcompile時間が伸びている様子
— Kenji Yoshida (@xuwei_k) 2022年11月6日
foo(
hlist(0),
hlist(1),
hlist(2),
hlist(3),
hlist(4),
hlist(5)
) pic.twitter.com/XkZJwx4sG5
出力方法
1. profile-trace というコンパイラオプションを利用することでprofile情報が出力されたjsonを取得する
以下を指定してビルドすれば出力されます
Compile / compile / scalacOptions ++= Seq("-Yprofile-trace", name.value + "-main.json"), Test / compile / scalacOptions ++= Seq("-Yprofile-trace", name.value + "-test.json"),
2. chromeのtrace機能に読み込ませる
Chromeを起動し、 chrome://tracing/ をURL欄に入力して遷移 > Loadボタンから先程のファイルを読み込む ことで上記のツイートのような解析結果が見られます
備考
jdk9以降を使っている場合は問題が出てしまう( 参考 のでjdk8でビルドするか以下のようにscala 2.13.11のsnapshotを利用するかなどの工夫が必要になります。
resolvers += "scala-snapshot" at "https://scala-ci.typesafe.com/artifactory/scala-pr-validation-snapshots/", ThisBuild / scalaVersion := "2.13.11-bin-7e2671b-SNAPSHOT"
おまけ
- sbtのsub projectが多い場合はコンパイルを並列化できてないこともあるので、これの解析のために
-Dsbt.traces=true
をつけてsbt buildを行うと良い。詳細は https://github.com/sbt/sbt/pull/4576
謝辞
全面的に https://mobile.twitter.com/xuwei_k さんに助けて頂きました。ありがとうございます🙏🙏🙏🙏🙏🙏🙏🙏