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
Build高速化の話
Search
kobito-kaba
November 20, 2017
Programming
4
2.1k
Build高速化の話
.droidconSFのJared Burrowsによる、"Make Your Build Great Again"を試してみたら、ビルド時間が半分になりましたので、まとめました
kobito-kaba
November 20, 2017
Tweet
Share
More Decks by kobito-kaba
See All by kobito-kaba
新規プロジェクトでやってよかったことまとめ
kobitokaba
1
760
Youtube like BottomNavigation
kobitokaba
0
190
Modularizing and Refactoring Android App with Clean Architecture
kobitokaba
0
220
Slice Your App
kobitokaba
2
1.1k
Inside Jetpack
kobitokaba
2
97
Generating and Transforming Kotlin code
kobitokaba
0
68
Conference Tourism
kobitokaba
0
230
Inside Jetpack Architecture Components
kobitokaba
0
190
Kotlinもう一歩
kobitokaba
8
15k
Other Decks in Programming
See All in Programming
Recoilを剥がしている話
kirik
5
6.6k
あれやってみてー駆動から成長を加速させる / areyattemite-driven
nashiusagi
1
200
似たもの同士のPerlとPHP
uzulla
1
130
htmxって知っていますか?次世代のHTML
hiro_ghap1
0
330
N.E.X.T LEVEL
pluu
2
300
今年一番支援させていただいたのは認証系サービスでした
satoshi256kbyte
1
250
layerx_20241129.pdf
kyoheig3
2
290
선언형 UI에서의 상태관리
l2hyunwoo
0
140
As an Engineers, let's build the CRM system via LINE Official Account 2.0
clonn
1
670
MCP with Cloudflare Workers
yusukebe
2
220
Effective Signals in Angular 19+: Rules and Helpers @ngbe2024
manfredsteyer
PRO
0
130
CSC305 Lecture 26
javiergs
PRO
0
140
Featured
See All Featured
Building Adaptive Systems
keathley
38
2.3k
How To Stay Up To Date on Web Technology
chriscoyier
789
250k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.2k
Documentation Writing (for coders)
carmenintech
66
4.5k
Code Reviewing Like a Champion
maltzj
520
39k
Making the Leap to Tech Lead
cromwellryan
133
9k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
GraphQLの誤解/rethinking-graphql
sonatard
67
10k
StorybookのUI Testing Handbookを読んだ
zakiyama
27
5.3k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
Speed Design
sergeychernyshev
25
670
Designing Experiences People Love
moore
138
23k
Transcript
Build高 化 お話 Yahoo! JAPAN 森 洋之
None
Make Your Build Great Again!
Jared Burrows Software Engineer @Microsoft Yammer for Android
Before After Reduction Time(min) 〜18+ 〜11 38.89%
ビルド 度 ために 最適化する対象
• ソフトウェア ◦ Gradle ◦ Android Gradle Plugin ◦ Android
Studio / IntelliJ • ハードウェア ◦ CPU ◦ メモリ
None
$4,999〜
探るべきも • 遅くなっている原因 • ボトルネックになっているタスク • 不要な依存関係・プラグイン • モジュール/build.gradle 構
スタート地点 • 一番ベースとなっているところから手を付けていく
スタート地点 • 一番ベースとなっているところから手を付けていく • PCを変える、ビルドエージェントを見直すなど
スタート地点 • 一番ベースとなっているところから手を付けていく • PCを変える、ビルドエージェントを見直すなど • Gradle 設定を最適化する
スタート地点 • 一番ベースとなっているところから手を付けていく • PCを変える、ビルドエージェントを見直すなど • Gradle 設定を最適化する • Android
Gradle Plugin 設定を最適化する
スタート地点 • 一番ベースとなっているところから手を付けていく • PCを変える、ビルドエージェントを見直すなど • Gradle 設定を最適化する • Android
Gradle Plugin 設定を最適化する • Android Studio 設定を最適化する
Gradle 設定
基本
ソフトウェアを最新にする • Gradle 4.3を使う
None
ソフトウェアを最新にする • Gradle 4.3を使う • マイナーバージョン間 互換性を維持する
ソフトウェアを最新にする • Gradle 4.3を使う • マイナーバージョン間 互換性を維持する • JVMも最新 も
を使う
gradle.properties
Gradle daemonを有効にする • Gradleを実行するたびに、新しいインスタンスを 立ち上げている • デーモンを使用することで、ビルドごとにJVMを起動す るコストを避けられる • 3.0〜
デフォルトで有効
gradle.properties org.gradle.daemon=true
daemon ヒープサイズを増やす • デフォルトで 1GB • Androidプロジェクト 、通常もっと使う • AGP
2.1以上だと、”Dex in Process”に 最低2GB 必要 • 大きなプロジェクトほど、メモリ 増設が効く
gradle.properties org.gradle.daemon=true
gradle.properties org.gradle.daemon=true org.gradle.jvmargs=-Xmx2048m
並列ビルドを有効にする • Gradleタスク 並列実行 ビルド 度を くする • モジュール分割されたプロジェクトで効果的 •
JavaCompileタスクを別プロセスで行うと良い • テストタスクも別プロセスが良い
gradle.properties org.gradle.daemon=true org.gradle.jvmargs=-Xmx2048m
gradle.properties org.gradle.daemon=true org.gradle.jvmargs=-Xmx2048m org.gradle.parallel=true
Javaコンパイルタスクを分離する tasks.withType(JavaCompile) { options.fork = true }
テストタスクを分離する tasks.withType(Test) { def maxCount = gradle.startParameter.maxWorkerCount maxParallelForks = (maxCount
< 2) ? 1 : maxCount / 2 forkEvery = 100 }
None
Configure on Demandを有効にする • 関係 あるモジュール/タスクで み Configurationを行う • モジュール分割されたプロジェクトで効果的
• こ 設定をしても、“subprojects”や”allprojects”で 設定を使うと無意味になる
gradle.properties org.gradle.daemon=true org.gradle.jvmargs=-Xmx2048m org.gradle.parallel=true
gradle.properties org.gradle.daemon=true org.gradle.jvmargs=-Xmx2048m org.gradle.parallel=true org.gradle.configureondemand=true
ビルドキャッシュを有効にする • インクリメンタルビルドによって、 無駄な再ビルドを減らすことができる • ブランチを変えたときにも効果的 • 異なるビルドフレーバーをビルドする時に効果的
gradle.properties org.gradle.daemon=true org.gradle.jvmargs=-Xmx2048m org.gradle.parallel=true org.gradle.configureondemand=true
gradle.properties org.gradle.daemon=true org.gradle.jvmargs=-Xmx2048m org.gradle.parallel=true org.gradle.configureondemand=true org.gradle.caching=true
build.gradle
プラグイン 適用 よく考えて • 必要なモジュールにだけプラグインを適用する • “subprojects” / “allprojects”を使う 、
本当に実際に使用しているプラグインだけにする
参照するリポジトリを減らす よくあるやつ • jcenter() • mavenCentral() • maven { url
“https://plugins.gradle.org/m2/” } • maven { url “https://maven.google.com” } • maven { url “https://jitpack.io” }
参照するリポジトリを減らす repositories { jcenter() mavenCentral() maven { url “https://plugins.gradle.org/m2/” }
google() maven { url “https://jitpack.io” } }
参照するリポジトリを減らす repositories { maven { url “https://plugins.gradle.org/m2/” } google() }
// これでいけるかも?
動的バージョン指定 避ける(+) • そもそも警告されていると思うが • 意図しないアップデートが発生する • バージョン比較 難しい •
毎回バージョンチェックして遅くなる
動的バージョン指定 避ける(+) dependencies { // ダメ implementation ‘com.android.support:appcompat-v7:+’ }
最新 バージョンを探す goo.gl/qy5uJa プロジェクト 依存ライブラリ 、 最新バージョンを探してレポートするプラグイン
動的バージョン指定 避ける(+) こうすると ./gradlew dependencyUpdates -Drevision=release
動的バージョン指定 避ける(+) ------------------------------------------------------------ : Project Dependency Updates (report to plain
text file) ------------------------------------------------------------ The following dependencies are using the latest release version: - com.android.support.test.espresso:espresso-core:3.0.1 - com.github.ben-manes:gradle-versions-plugin:0.17.0 - junit:junit:4.12 - com.android.support.test:runner:1.0.1 The following dependencies have later release versions: - com.android.support:appcompat-v7 [26.1.0 -> 27.0.1] - com.android.support.constraint:constraint-layout [1.0.2 -> 1.1.0-beta3] - com.android.tools.build:gradle [3.0.0 -> 3.1.0-alpha03] - org.jacoco:org.jacoco.agent [0.7.4.201502262128 -> 0.7.9] - org.jacoco:org.jacoco.ant [0.7.4.201502262128 -> 0.7.9]
動的バージョン指定 避ける(+) ------------------------------------------------------------ : Project Dependency Updates (report to plain
text file) ------------------------------------------------------------ The following dependencies are using the latest release version: - com.android.support.test.espresso:espresso-core:3.0.1 - com.github.ben-manes:gradle-versions-plugin:0.17.0 - junit:junit:4.12 - com.android.support.test:runner:1.0.1 The following dependencies have later release versions: - com.android.support:appcompat-v7 [26.1.0 -> 27.0.1] - com.android.support.constraint:constraint-layout [1.0.2 -> 1.1.0-beta3] - com.android.tools.build:gradle [3.0.0 -> 3.1.0-alpha03] - org.jacoco:org.jacoco.agent [0.7.4.201502262128 -> 0.7.9] - org.jacoco:org.jacoco.ant [0.7.4.201502262128 -> 0.7.9]
動的バージョン指定 避ける(+) ------------------------------------------------------------ : Project Dependency Updates (report to plain
text file) ------------------------------------------------------------ The following dependencies are using the latest release version: - com.android.support.test.espresso:espresso-core:3.0.1 - com.github.ben-manes:gradle-versions-plugin:0.17.0 - junit:junit:4.12 - com.android.support.test:runner:1.0.1 The following dependencies have later release versions: - com.android.support:appcompat-v7 [26.1.0 -> 27.0.1] - com.android.support.constraint:constraint-layout [1.0.2 -> 1.1.0-beta3] - com.android.tools.build:gradle [3.0.0 -> 3.1.0-alpha03] - org.jacoco:org.jacoco.agent [0.7.4.201502262128 -> 0.7.9] - org.jacoco:org.jacoco.ant [0.7.4.201502262128 -> 0.7.9]
不要な / 使用してないライブラリを避ける • でかいライブラリ 避ける • 同様 機能で、より軽量 ライブラリを使用する
Jacksonより 、Gson / Moshiを選ぶ Guava 使わない • 詳しく goo.gl/miu6aV
インクリメンタルビルドを有効にする • 修正したクラスと、それに依存するクラスだけ コンパイルする
インクリメンタルビルドを有効にする tasks.withType(JavaCompile) { options.fork = true }
インクリメンタルビルドを有効にする tasks.withType(JavaCompile) { options.incremental = true options.fork = true }
インクリメンタルビルドを有効にする • AutoValue / Glide / Butterknife / Dagger等、 APTを行うライブラリ
、インクリメンタルビルドを無効 化する • Android Gradle Plugin(AGP) 3.0〜 APTもサポートされている…?
None
Android Gradle Plugin
ソフトウェアを最新にする • AGP 3.0.0を使う • SDK tools / platform toolsも最新
も を使う
不要なリソース コンパイルを避ける • “resConfig”で、必要ないローカリゼーションを 除外することができる • 自分 とこ 、日本語リソースしかないけど? →外部ライブラリ
、そうでもない で ?
不要なリソース コンパイルを避ける android { defaultConfig { resConfigs “ja” } }
// 日本語だけ
不要なリソース コンパイルを避ける android { defaultConfig { resConfigs “ja”,”en” } }
// 日本語と英語
定数を使う android { compileSdkVersion 27 buildToolsVersion “27.0.0” defaultConfig { applicationId
“com.example.android.hmori.sample” versionCode new Date().format(“ddMMyyHHmm”).toInteger() versionName “1.0” minSdkVersion 19 targetSdkVersion 27 } }
定数を使う android { compileSdkVersion 27 buildToolsVersion “27.0.0” defaultConfig { applicationId
“com.example.android.hmori.sample” versionCode new Date().format(“ddMMyyHHmm”).toInteger() versionName “1.0” minSdkVersion 19 targetSdkVersion 27 } }
定数を使う def isRelease = project.hasProperty(“release”) android { compileSdkVersion 27 buildToolsVersion
“27.0.0” defaultConfig { applicationId “com.example.android.hmori.sample” versionCode isRelease ? new Date().format(“ddMMyyHHmm”).toInteger() : 1 versionName “1.0” minSdkVersion 19 targetSdkVersion 27 } }
ライブラリモジュールに分割する • Gradle 修正したモジュールだけコンパイルする • コンパイル結果 キャッシュされる • モジュール分割 +
“configurationOnDemand” + 並列ビルドが効果的
PNG crunchを無効にする • PNGをWebPに変換できないなら、 PNG crunchを使う • 無効にすることで、AGP ビルドごとにPNGを 再圧縮すること
なくなる • AGP 3.0.0〜、PNG crunch 、 ”debug”ビルド時に 、デフォルトで無効
PNG crunchを無効にする android { aaptOptions { cruncherEnabled = project.hasProperty(“ci”) }
}
lagacyなmultidexを避ける • minSdkVersion < 21 : legacyなmultidex • minSdkVersion >=
21 : ネイティブでmultidexがサポートされている • 開発時 み、minSdkVersionを21以上になるように すれ 、開発時 ビルドが くなる
lagacyなmultidexを避ける android { compileSdkVersion 27 buildToolsVersion “27.0.0” defaultConfig { applicationId
“com.example.android.hmori.sample” versionCode 1 versionName “1.0” minSdkVersion 19 targetSdkVersion 27 } }
lagacyなmultidexを避ける android { compileSdkVersion 27 buildToolsVersion “27.0.0” defaultConfig { applicationId
“com.example.android.hmori.sample” versionCode 1 versionName “1.0” minSdkVersion rootProject.hasProperty(“lollipop”) ? 21 : 19 targetSdkVersion 27 } }
CIで pre-dexライブラリを無効化する • pre-dex インクリメンタルビルドで 効果的 • CIでクリーンビルドするときに 無駄
CIで pre-dexライブラリを無効化する android { dexOptions { preDexLibraries = !project.hasProperty(“ci”) }
}
ビルドキャッシュを有効にする • AGP 幾つか 生成物をキャッシュする • AGP 2.3.0〜 デフォルトで有効
gradle.properties # Gradle specific org.gradle.daemon=true org.gradle.jvmargs=-Xmx2048m org.gradle.parallel=true org.gradle.configureondemand=true org.gradle.caching=true
gradle.properties # Gradle specific org.gradle.daemon=true org.gradle.jvmargs=-Xmx2048m org.gradle.parallel=true org.gradle.configureondemand=true org.gradle.caching=true #
Android specific android.enableBuildCache=true
新しいDEXコンパイラを有効にする • DEXコンパイラ 、.class → .dexに変換する • D8 より早く.dexファイルに変換する。 •
しかも生成物 より小さくなる • しかも実行時パフォーマンスも改善する • AGP 3.1.0〜デフォルトで有効
gradle.properties # Gradle specific org.gradle.daemon=true org.gradle.jvmargs=-Xmx2048m org.gradle.parallel=true org.gradle.configureondemand=true org.gradle.caching=true #
Android specific android.enableBuildCache=true
gradle.properties # Gradle specific org.gradle.daemon=true org.gradle.jvmargs=-Xmx2048m org.gradle.parallel=true org.gradle.configureondemand=true org.gradle.caching=true #
Android specific android.enableBuildCache=true android.enableD8=true
Android Studio 設定
画像をWebPにする • WebPにすることで、画像サイズを削減できる • ビルド時にやる必要 ない • ビルド前にやっておくことで、 ビルド時間 改善される
画像をWebPにする • “drawable”フォルダを右クリック
Instant Runを有効にする • 一定 コード追加やリソース修正で、 新しくAPKファイルを作成せずに実行できる • 特定 場合に 、アクティビティ
再起動さえ いらない
offline modeを有効にする • dependencyやプラグインを頻繁に更新しない な ら、offline modeで更新チェックを外すといい • ./gradlew --offline
offline modeを有効にする • Preferences ”Build, Execution, Deployment”
Profiling Your Build
ビルドプロセスをプロファイルする • “gradlew --profile” • “gradlew --scan”(goo.gl/UT1Qtb) • そ 他:
https://github.com/gradle/gradle-profiler
ビルドプロセスをプロファイルする • “gradlew clean assembleDebug --profile”
ビルドプロセスをプロファイルする • “gradlew clean assembleDebug --scan”
ビルドプロセスをプロファイルする
結果
1回目 2回目 3回目 4回目 5回目 Before 2 min 37.376 sec
1 min 43.3 sec 1 min 39.9 sec 1 min 37.8 sec 1 min 40.8 sec After 1 min 29 sec 1 min 11 sec 47 sec 46 sec 45 sec
None