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
200
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
140
Scala-Matsuri-2023.pdf
xuwei_k
0
1.4k
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
130
Other Decks in Programming
See All in Programming
14 Years of iOS: Lessons and Key Points
seyfoyun
1
750
競技プログラミングへのお誘い@阪大BOOSTセミナー
kotamanegi
0
320
PipeCDの歩き方
kuro_kurorrr
4
150
MCP with Cloudflare Workers
yusukebe
2
190
【re:Growth 2024】 Aurora DSQL をちゃんと話します!
maroon1st
0
730
Jakarta EE meets AI
ivargrimstad
0
180
クリエイティブコーディングとRuby学習 / Creative Coding and Learning Ruby
chobishiba
0
3.8k
Discord Bot with AI -for English learners-
xin9le
1
120
短期間での新規プロダクト開発における「コスパの良い」Goのテスト戦略」 / kamakura.go
n3xem
2
150
Refactor your code - refactor yourself
xosofox
1
220
CSC305 Lecture 26
javiergs
PRO
0
130
なまけものオバケたち -PHP 8.4 に入った新機能の紹介-
tanakahisateru
1
110
Featured
See All Featured
What's in a price? How to price your products and services
michaelherold
243
12k
How STYLIGHT went responsive
nonsquared
95
5.2k
Measuring & Analyzing Core Web Vitals
bluesmoon
4
170
Large-scale JavaScript Application Architecture
addyosmani
510
110k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
Raft: Consensus for Rubyists
vanstee
136
6.7k
The Art of Programming - Codeland 2020
erikaheidi
53
13k
A Tale of Four Properties
chriscoyier
157
23k
Fireside Chat
paigeccino
34
3.1k
Intergalactic Javascript Robots from Outer Space
tanoku
270
27k
BBQ
matthewcrist
85
9.3k
Keith and Marios Guide to Fast Websites
keithpitt
410
22k
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