Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Scalaプロジェクトの ビルド速度改善
Search
kenji yoshida
June 08, 2024
Programming
0
290
Scalaプロジェクトの ビルド速度改善
ScalaMatsuri 2024での発表
kenji yoshida
June 08, 2024
Tweet
Share
More Decks by kenji yoshida
See All by kenji yoshida
数十万行のプロジェクトを Scala 2から3に完全移行した
xuwei_k
0
1.3k
Scala-Matsuri-2023.pdf
xuwei_k
0
1.5k
WartremoverのScala 3対応
xuwei_k
0
160
アルプでのScala 3移⾏
xuwei_k
1
1.5k
ScalaでgRPC
xuwei_k
0
1.6k
scalaprops
xuwei_k
0
140
Other Decks in Programming
See All in Programming
GoとPHPのインターフェイスの違い
shimabox
2
220
Generating OpenAPI schema from serializers throughout the Rails stack - Kyobashi.rb #5
envek
1
440
Your Architecture as a Crime Scene:Forensic Analysis @bastacon 2025 in Frankfurt
manfredsteyer
PRO
0
130
楽しく向き合う例外対応
okutsu
0
760
運用しながらリアーキテクチャ
nealle
0
210
仕様変更に耐えるための"今の"DRY原則を考える
mkmk884
9
3.3k
CSS Linter による Baseline サポートの仕組み
ryo_manba
1
160
Kotlinの開発でも AIをいい感じに使いたい / Making the Most of AI in Kotlin Development
kohii00
5
2.1k
【AI 自走型】Figma からデザインコーディングを行うプロンプト
tetsuro_b
0
100
Datadog Workflow Automation で圧倒的価値提供
showwin
1
330
15分で学ぶDuckDBの可愛い使い方 DuckDBの最近の更新
notrogue
3
860
高セキュリティ・高耐障害性・サブシステム化。そして2億円
tasukulab280
2
360
Featured
See All Featured
Stop Working from a Prison Cell
hatefulcrawdad
268
20k
A designer walks into a library…
pauljervisheath
205
24k
Building Applications with DynamoDB
mza
93
6.3k
Adopting Sorbet at Scale
ufuk
75
9.2k
Building an army of robots
kneath
303
45k
Testing 201, or: Great Expectations
jmmastey
42
7.2k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
46
2.4k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
59k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.5k
Making Projects Easy
brettharned
116
6k
Git: the NoSQL Database
bkeepers
PRO
429
65k
Navigating Team Friction
lara
183
15k
Transcript
Scalaプロジェクトの ビルド速度改善 ScalaMatsuri 2024 2024-06-08 1 / 78
X(旧twitter) @xuwei_k github @xuwei-k blog https://xuwei-k.hatenablog.com 2 / 78
誰? Scala 2.8出る直前くらいから使ってる 2009年 仕事でのScala歴が13年以上? Scala 2本体その他色々なScala関連OSSの権限持 って貢献してる 3 /
78
前提の話 build速度とは? 扱わないこと、方向性 速度改善の目的 4 / 78
前提の話 どれが効果があるか?優先度高いか?は難しい 手法をひたすら色々紹介していく流れ 5 / 78
前提の話 そもそも普通にボトルネック探したらScalaやsbt に限らない部分の最適化の余地の方が多い場合も 多々 6 / 78
OSSか、それ以外か よほど巨大で活発でなければOSSではあまり問題に ならない? OSSの種類にもよる 広い意味でIOがないライブラリなら楽 7 / 78
OSSか、それ以外か OSSは大抵GitHub Actionsなどで無料の範囲で済 む よってOSSは富豪的に並列実行してることが多々 普通の?プロダクト開発とは全然異なる 8 / 78
普通の?プロダクト開発 通常CIのお金的コストがかかる 複数人で活発に開発 される場合がある CIは普通は速く終わるほど良いはず 9 / 78
扱うこと compileの速度とtest実行、その他含めた速度? ローカルにも恩恵はあるが主にCIでの速度 10 / 78
扱うこと 自分の経験や普段使用してる技術を元に話すので、 全てを網羅してるわけではない 主にsbt前提 他でも使えるがGitHub Actions(のような)CIの システム想定 11 / 78
目的やトレードオフ 速くなればお金はかかっていいのか? 速くなればビルドの設定が複雑になってもいいの か? 12 / 78
目的やトレードオフ 一時的に速くなっても継続的にメンテ不可能なほど ビルドが複雑になってしまったら駄目では 13 / 78
目的やトレードオフ 使うお金を増やさずに速度も全体の効率も改善した い? build速度改善のために、どの程度人間の工数かけ るのか? 14 / 78
扱わないこと Bazel gitのproject分ける Compiler内部の深い話 15 / 78
Bazelのような 差分buildとtest 究極的な理想としてはこれ 本気で巨大なmonorepoで頑張るなら潜在的な可能 性としては1番良い? 16 / 78
Bazelのような 差分buildとtest 2024年の時点のsbtで正確に徹底的にやるには厳し い部分が多い sbt 2にはそういう機能をもっと入れたいらしい 17 / 78
GitのProject分ける? monorepoのメリットは捨てたくない 18 / 78
基本 sbtのproject分ける ボトルネックの予想、把握、計測 sbtの設定見直す CIの設定見直す 19 / 78
sbtのproject を適切に分ける 一番大事かもしれない Scala compiler内部は一部しか並列化されていな い 大まかにはScala 2も3も同様 20 /
78
sbtのproject を適切に分ける CPUコアやメモリやネットワーク、ディクスのIOが ボトルネックでないなら、分割すればある程度まで スケールする 分割をし過ぎると別の辛さも発生する 21 / 78
sbtのproject を適切に分ける 分割する単位の目安は? 1つのsub projectで数万行単位? 22 / 78
sbtのproject を適切に分ける 本来は速度のためではなくコードの意味で分割する べき 個人的な経験として、少なくともsub project数は 百程度ならまだ普通に扱える 23 / 78
-Dsbt.traces=true 24 / 78
sbtで絶対に使うべき taskごとのtrace機能 https://github.com/sbt/sbt/pull/4576 デフォルトだと細かいtask全部記録して少し扱いづ らいので独自に改造して使ったりしてる 25 / 78
sbtで絶対に使うべき taskごとのtrace機能 それをGitHub Actionsでより手軽に記録して見る 方法も https://xuwei- k.hatenablog.com/entry/2024/06/01/103536 26 / 78
余計なsub project間の 依存削除や整理 必要ないのにdependsOnしない 必要ないのに "test->test" の依存をしない 27 / 78
基本? sbtやScalaはそれぞれ最新版を使う どの程度速度に直結するか?というと場合によるが 28 / 78
テストの並列度の理解や設定 https://xuwei- k.hatenablog.com/entry/2020/03/14/234758 https://xuwei- k.hatenablog.com/entry/2024/05/03/101725 29 / 78
テストの並列度の理解や設定 sub projectごとにforkするかしないか?がとて も重要 それによって設定も変わる 適切に並列実行するには、DBなどの外部のものが衝 突しないようにする工夫 30 / 78
DBなどの外部リソース もはやScalaやsbtに限らない話 適切な単位、タイミングで立ち上げて、それらの CPUやメモリやコネクション数も見てみる 31 / 78
DBなどの立ち上げ方 https://testcontainers.com testcontainersは便利だが、多過ぎると効率悪い 32 / 78
DBなどの立ち上げ方 複数のミドルウェアを使うなら、それを並列で立ち 上げるみたいな地味な工夫 数秒から数十秒節約 33 / 78
sbtはcommandを避け 全てtaskに commandは合成可能ではない commandは並列実行できない taskにしておけば並列実行可能 34 / 78
sbtはcommandを避け 全てtaskに sbt "all task1 task2 task3" のようにすれば可能な範囲で並列実行 inputTaskはtoTaskメソッドでtaskに変換可能 35
/ 78
sbtを立ち上げる回数を 出来るだけ減らす 1回立ち上げるごとに、数秒から、(巨大だと)数十 秒無駄になる もちろん、1回に詰め込み過ぎるとわかりづらくな るデメリットはある 36 / 78
wartremoverやscalafix のためのsemanticdb生成 遅い 他に代表的なlinterやcompiler plugin? 🤔 ある程度使うと、compile速度の半分がそれにな る!? 37 /
78
wartremover ここ数年自分がほぼメンテしてる 詳細は何度も過去に話をしたのでそちら参照 38 / 78
以前のscalafixや wartremoverの話 https://xuwei- k.github.io/slides/Matsuri-2020/ https://xuwei- k.github.io/slides/matsuri-2023/ https://xuwei- k.github.io/slides/wartremover-3/ 39 /
78
wartremover Scala 3の場合は、compileと別のタイミングで実 行可能だが、色々辛い compileと同時の時より遅い compileと同時とは稀に違う結果になる? 40 / 78
scalafixのための semanticdb生成 scalafixはSyntacticRuleならあまり影響ない 有効と無効を簡単に切り替えられるようにした方が いい 例えばCIでは有効化して、デプロイ時には無効化な ど? 41 / 78
sbtの細かいテクニック set key := value は若干遅い? インタラクティブにsettingを変更する方法 ローカルでたまに使うには便利だが 42 /
78
sbtの細かいテクニック sbt内部でのトポロジカルソートやり直し? sbt -Dkey=value で指定し sys.props で取得 がいい? あるいは環境変数 43
/ 78
sbtのExtracted.runTaskメ ソッド避ける そもそもsbtに多少詳しい人しか使わないと思う 同様のrunInputTaskなども 直接taskを実行できて便利だが、競合したり、無駄 に同じtaskが複数回実行される危険がある 44 / 78
sbtのrunTaskメソッド避ける 面倒でも必要に応じてDef.taskDynなど使いつ つ、普通のtaskとして依存関係を持たせて定義や実 行するべき 45 / 78
使ってないコードを 効率よく消す方法 直接速度に影響するほど大量でなければ、そこまで 大きく変わらないが 速度以外の側面でも無駄なコード少ないに越したこ とはない 46 / 78
使ってないコードを 効率よく消す方法 最近はIntelliJ IDEAが賢いのでそれ使うとわり と見つかる scalaのcompiler option指定でも 47 / 78
IntelliJ IDEAの使ってない コード検知機能 そのproject内部でグローバルに検知してくれる 多少誤検知ある companion objectにimplicitでinstance定義 したときにobjectが使ってない判定される 48 /
78
使ってないコード効率よく消す 自作ツール例 https://xuwei- k.hatenablog.com/entry/2023/02/08/115510 https://github.com/xuwei-k/unused-code https://xuwei- k.hatenablog.com/entry/2022/02/14/152706 49 / 78
compile速度 macroが必ず遅くなるわけではないが、結果的に macroが原因なことは多い compiler pluginも種類によっては注意 circeのautoのような再帰的に導出するものは、裏 で重複して展開される可能性が高まるって爆発する ので絶対ダメ 50 /
78
compile速度のプロファイル https://github.com/scala/scala/pull/7364 Scala 2のChrome traceを1度は実行してみまし ょう -Yprofile-trace 51 / 78
compile速度のプロファイル Scala 3にも入る? https://github.com/scala/scala3/pull/19897 52 / 78
Scala 3のinlineでの compile速度爆発との戦い 前にblog書いた https://xuwei- k.hatenablog.com/entry/2022/03/30/142529 53 / 78
compile速度のプロファイル Scala 3用で独自に作ったが、公式に前述のものが 入れば必要なくなりそう https://xuwei- k.hatenablog.com/entry/2022/11/12/160933 https://github.com/xuwei- k/scala3profile 54 /
78
compileとtestでJVMの profile 個人的によく使ってる https://visualvm.github.io/ その他JVMには色々あるので使えるものはなんでも 使おう 55 / 78
testでJVMのprofile 余計なスレッドや、スレッドプール、コネクション プールが作られ過ぎていないか? ActorSystem気軽に作ると結構無駄なので注意 56 / 78
testでのprofile CIでは、JVMとその他含めてメモリが効率的に使え ているか? 意味なくメモリなどを使い過ぎているプロセスはな いか? JVMには色々なツールが揃ってるのでフル活用 57 / 78
CI上での計測 GitHub Actionsだと、例えばこういうものも https://github.com/catchpoint/workflow- telemetry-action ただし、細かい部分不満がある、一部正しく取れな い 58 / 78
CIでのキャッシュ効率 独自にS3保存などの方がいい場合も? https://synamon.hatenablog.com/entry/2022/11 keyの設計を必ずしっかり https://xuwei- k.hatenablog.com/entry/2020/03/16/005728 59 / 78
CIでのキャッシュ効率 GitHub Actions公式の制約に注意 容量の制約 default branchで保存しないと他で使えない しっかりキャッシュがヒットしてるか定期的にログ などで確認 60 /
78
CIで並列job お金で時間を買う方法 効率は犠牲になるが、ある程度までなら簡単に速く なるので、人間が工夫を頑張る工数は節約 テスト名のhashでやるなど https://labs.septeni.co.jp/entry/2018/11/23/ 61 / 78
CIで並列job compileは1つでその後testなどは分岐? その場合にsbtのremote cacheではなく workspace丸ごとuploadしたほうが速い、といっ たノウハウ あるいは、相対的にcompileのコストが低いなら、 最初から富豪的にcompileも重複して実行? 62 /
78
sbt-projectmatrix の使用検討 https://github.com/sbt/sbt- projectmatrix デフォルトではsbtは "++ 3.x" などでscala versionを切り替えるが、これは状態を変更してい る
状態を変更しないと他のversionでbuildが出来な いのはデメリット 63 / 78
sbt-projectmatrix の使用検討 Scalaのversion以外でも他にも色々な意味で cross buildしたい場合 sbt 2ではこれがデフォルトになる? 普通に設定したら並列にできないものまで並列で可 能になるので 64
/ 78
sbt-projectmatrix の使用検討 全体としての効率重視したい場合? CIのjob分けるより、効率はいいはず? 65 / 78
sbtの concurrentRestrictions 以前のテストの並列の話のblogにも書いたが デフォルトのままではなく細かく変えた方がいい場 合は多々ある 66 / 78
個々のtest時間を集計してみる 例えばscalatestだと -oD のようなオプションが あります それをさらにいい感じに集計しないと・・・ これだけでボトルネックわかるか?というと 67 / 78
pipelineの有効化検討 ThisBuild / usePipelining := true Scala 2にも3にもある 3に入ったのは最近(2024年4月) https://github.com/scala/scala3/pull/18880
68 / 78
pipelineの有効化検討 今回のScala祭で話がある? 普通のcompile option設定ではなく、build toolと連携した特別な設定が必要 69 / 78
pipelineの有効化検討 最大、数割程度速くなる可能性? まだそこまで広く使われてないので、罠にハマる可 能性もありそう 70 / 78
buildファイルの Scala書き過ぎない sbtが多少?好きな人以外は、そもそもそこを頑張 らないと思うが 使わない部分も必ずcompileされるので sbtとしてのbuildファイルに書く必然性がないも のは他の場所に 71 / 78
使っているsbt plugin見直す 稀にsbt pluginせいで遅いことがある。あった ほぼ使ってないものや、メンテされてない古いもの は場合によって脱却しよう maven centralではなく古い非推奨なrepo.scala- sbt.orgのresolverに置いてあるものも注意 72
/ 78
テストの依存の工夫 https://xuwei- k.hatenablog.com/entry/2022/10/09/124418 73 / 78
数日前書いた記事 Scalaやsbt直接関係ない build時間の統計取ったり様々な角度から https://xuwei- k.hatenablog.com/entry/2024/06/07/074942 74 / 78
まとめ Scalaのcompileそのものが原因で遅いことはない とは言い切れないが、そこだけがボトルネックにな るのは非常に稀です 仮にcompileが遅くても、CI全体で見るとtest時 間も結構な割合を占めるはずで、そこはあまり Scala特有ではない 75 / 78
まとめ 色々やって、それでももっと速くしたい場合は、最 終的にはお金でスケールする余地を残して、作って るプロダクトがCI程度のお金が大したことないほど 儲ければ問題ないのでは? 76 / 78
まとめ 今回紹介したような手法ほぼ全て試してもまだ圧倒 的に遅いと感じるならば、他の言語やbuild tool を検討した方がいい可能性はある? 思っている以上に手段は数多くあるので、目的に応 じて適度に頑張りましょう 77 / 78
おわり 78 / 78