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
730
Youtube like BottomNavigation
kobitokaba
0
180
Modularizing and Refactoring Android App with Clean Architecture
kobitokaba
0
210
Slice Your App
kobitokaba
2
1.1k
Inside Jetpack
kobitokaba
2
92
Generating and Transforming Kotlin code
kobitokaba
0
64
Conference Tourism
kobitokaba
0
230
Inside Jetpack Architecture Components
kobitokaba
0
190
Kotlinもう一歩
kobitokaba
8
15k
Other Decks in Programming
See All in Programming
C#/.NETのこれまでのふりかえり
tomokusaba
1
160
Googleのテストサイズを活用したテスト環境の構築
toms74209200
0
270
ECSのサービス間通信 4つの方法を比較する 〜Canary,Blue/Greenも添えて〜
tkikuc
11
2.3k
RailsのPull requestsのレビューの時に私が考えていること
yahonda
5
1.7k
約9000個の自動テストの 時間を50分->10分に短縮 Flakyテストを1%以下に抑えた話
hatsu38
23
11k
Content Security Policy入門 セキュリティ設定と 違反レポートのはじめ方 / Introduction to Content Security Policy Getting Started with Security Configuration and Violation Reporting
uskey512
1
420
カラム追加で増えるActiveRecordのメモリサイズ イメージできますか?
asayamakk
4
1.5k
デプロイを任されたので、教わった通りにデプロイしたら障害になった件 ~俺のやらかしを越えてゆけ~
techouse
52
32k
推し活の ハイトラフィックに立ち向かう Railsとアーキテクチャ - Kaigi on Rails 2024
falcon8823
6
2.2k
CSC509 Lecture 08
javiergs
PRO
0
110
『ドメイン駆動設計をはじめよう』のモデリングアプローチ
masuda220
PRO
7
430
Kubernetes for Data Engineers: Building Scalable, Reliable Data Pipelines
sucitw
1
200
Featured
See All Featured
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Into the Great Unknown - MozCon
thekraken
31
1.5k
For a Future-Friendly Web
brad_frost
175
9.4k
How To Stay Up To Date on Web Technology
chriscoyier
788
250k
Music & Morning Musume
bryan
46
6.1k
Rebuilding a faster, lazier Slack
samanthasiow
79
8.6k
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.5k
Raft: Consensus for Rubyists
vanstee
136
6.6k
Faster Mobile Websites
deanohume
304
30k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
Why You Should Never Use an ORM
jnunemaker
PRO
53
9k
Building Better People: How to give real-time feedback that sticks.
wjessup
363
19k
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