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
2k
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
710
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
89
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
Amebaチョイス立ち上げの裏側 ~依存システムとの闘い~
daichi_igarashi
0
220
健康第一!MetricKitで始めるアプリの健康診断 / App Health Checkups Starting with MetricKit
nekowen
4
790
Prompt Cachingは本当に効果的なのか検証してみた.pdf
ttnyt8701
0
250
ゲームボーイアドバンスでSwiftを動かそう
k_koheyi
0
510
Uncharted packages (Laravel Live Denmark)
freekmurze
0
140
労務ドメインを快適に開発する方法 / How to Comfortably Develop in the Labor Domain
yuki21
1
250
Ebitengineの1vs1ゲーム WebRTCの活用
ponyo877
0
330
TypeScriptとGraphQLを活用した変化に強いプロダクト作り
bicstone
4
550
フロントエンドカンファレンス北海道2024 『小規模サイトでも使えるVite 〜HTMLコーディングをよりスマートに〜』長谷川広武(ハム)
h2ham
1
2.5k
iOSDC 2024 SMBファイル共有をSwiftで実装する
kishikawakatsumi
1
110
令和トラベルにおけるLLM活用事例:社内ツール開発から得た学びと実践
ippo012
0
110
Hono・Prisma・AWSでGeoなAPI開発
nokonoko1203
5
610
Featured
See All Featured
The Cost Of JavaScript in 2023
addyosmani
39
5.1k
How GitHub Uses GitHub to Build GitHub
holman
472
290k
A Tale of Four Properties
chriscoyier
155
22k
Stop Working from a Prison Cell
hatefulcrawdad
266
20k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
41
6.4k
Mobile First: as difficult as doing things right
swwweet
220
8.8k
KATA
mclloyd
27
13k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
165
48k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
248
20k
Optimising Largest Contentful Paint
csswizardry
28
2.7k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
27
1.6k
The Language of Interfaces
destraynor
153
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