Slide 1

Slide 1 text

Speeding up your Android Gradle builds 2017/06/16 Umeda.apk #3 @ctake0005

Slide 2

Slide 2 text

https://www.youtube.com/watch?v=7ll-rkLCtyk

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

https://goo.gl/7zOH9H

Slide 5

Slide 5 text

Making the most out of Android Gradle Plugin 3.0

Slide 6

Slide 6 text

Multi-module project

Slide 7

Slide 7 text

Code change impact (before 3.0) ● lib2 で コードに変更を加えると、直接参照している lib1 だけでなく 間接的(推移的)に参照している app も recompile される

Slide 8

Slide 8 text

Compilation avoidance ● ABI (Application Binary Interface) の概念 ○ ABI change ■ public フィールドやメソッドの追加・削除 ■ public フィールドやメソッド IF の変更 ■ 参照モジュールの recompile のトリガーになる ○ Non ABI change ■ private ( 外部に影響のない ) 変更 ■ public メソッドの内部実装の変更 ■ 参照モジュールを recompile しない

Slide 9

Slide 9 text

Non-Abi code change impact (3.0) ● lib1, app は recompile されない

Slide 10

Slide 10 text

ABI code change impact ● lib1, app を recompile する  ( ※ ‘compile’ のままだと )

Slide 11

Slide 11 text

New dependency config in 3.0 ● compile is now deprecated ● Replace with api or implementation dependencies { compile project(':libY') compile project(':libZ') api project(':libY') implementation project(':libZ') }

Slide 12

Slide 12 text

api vs implementation ● api ○ compile と同等の動作をする ■ because → compile を api に置き換えれば動作はする but → オススメはしない ○ 参照 モジュールの public API が、自身の API の一部になる場合に使 用

Slide 13

Slide 13 text

api vs implementation ● implementation ○ 参照 モジュール を公開しない場合 ○ 自身を参照するモジュールには、 ”implementation” で取り込んだモ ジュールの public API は見えない ○ Application モジュールは基本的に implementation を使えば良い ■ テストを別モジュールで構成したりしている場合は api を使わない とならないケースもある

Slide 14

Slide 14 text

public class LibXLibYWrapper { private final LibYClass1 y1Obj; public LibXLibYWrapper(LibYClass1 y1Obj) { this.y1Obj = y1Obj; } public void LibXPublic1() { LibYClass2 y2Obj = new LibYClass2(val); int type = LibXPrivate1(y2Obj); LibZExecute(type) ~~~~~ } private int LibXPrivate1(LibYClass2 method) { ~~~~~ } } dependencies { compile project(':libY') compile project(':libZ') api project(':libY') implementation project(':libZ') } Dependencies of LibX LibYのクラスをLibXの public API の一部と して使っている → api で参照する必要がある LibZのメソッドを public API で使っている が、内部でしか使っていない → implementation で参照すれば良い LibX LibY LibZ App

Slide 15

Slide 15 text

New dependency config in 3.0 New configuration Deprecated configuration Behavior implementation compile 前述 api compile 前述 compileOnly provided provided と同等 compile 時にのみ使用する runtimeOnly apk apk と同等 package 時のみ使用する ● compile, provided, apk は次のメジャーバージョンアップ( 4.0 ? )で無くなるらしい

Slide 16

Slide 16 text

Non-Abi code change ● lib1, app は recompile されない

Slide 17

Slide 17 text

ABI code change ● lib1 のみを recompile する

Slide 18

Slide 18 text

Conclusion ● Compilation avoidance ○ ABI change / Non ABI change の概念を導入したことによって無駄な recompile が発生しない ● api / implementation configurations ○ api / implementation を使い分けること(極力 implementation で済む ように実装すること)で、無駄な recompile が発生しない ⇒ Faster builds !!

Slide 19

Slide 19 text

Debugging & Profiling Build Performance Issues

Slide 20

Slide 20 text

Slow builds are not normal ● full build が数分以内に終わらない ○ 10 分かかったら普通じゃない、らしい ● Incremental build が full build と比べてそれほど速くない ● 何も変更せずに Incremental build をしても、 up-to-date タスク(実行がス キップされるタスク)がほとんどない

Slide 21

Slide 21 text

Any Help ? ● ./gradlew [ex. assembleDebug] --dry-run ○ gradle タスクの空実行 ○ 何のタスクがどの順番で実行されているかがわかる ○ 通常数秒で終わる ○ これが 10 秒以上かかるような場合は、 plugin などが悪さをしている可能 性がある

Slide 22

Slide 22 text

Any Help ? ● ./gradlew [ex. assembleDebug] --info ○ 何のタスクがなぜ走っているかを教えてくれる ○ 例えば、何も変更せずに Incremental build をして、なぜタスクがスキッ プされないかをなどがわかる

Slide 23

Slide 23 text

Any Help ? ● ./gradlew [ex. assembleDebug] --profile ○ 各タスクの実行にどのくらい時間がかかっているかを html で出力して くれる ○ build/reports/profile の中に下記の様な html が出力される ex) profile-2017-06-16-19-30-00.html

Slide 24

Slide 24 text

Any Help ? ● Gradle profiler (https://github.com/gradle/gradle-profiler) ○ Gradle ビルドのベンチマークの収集やプロファイリングを自動的に行っ てくれるツール ○ Benchmarking ○ Profiling

Slide 25

Slide 25 text

Filing performance bugs ● gradle-profiler で Yourkit というプロファイラを使ってプロファイルした結果 を提出すれば、なぜ Build が遅いのかを調べてくれるらしい ○ ただし、このセッションで説明したことを全て実践したけど、 まだ遅い、自分で調べてもわからない、という場合に限る! ● > gradle-profiler --profile yourkit --yourkit-memory --project-dir . clean assembleDebug みたいな感じで、調査したいタスクに対してプロファイルを実行すると、 『 profile-out-X.log 』が吐き出されるのでそれを送るっぽい。

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

More Info ● Google I/O 2017 Session Movie ○ https://www.youtube.com/watch?v=7ll-rkLCtyk ● Optimize your build speed ○ https://developer.android.com/studio/build/optimize-your-build.html ● Migration Guide to Android Gradle plugin 3.0 ○ https://developer.android.com/studio/preview/features/new-android-plugin-migration.html#apply_p lugin ● Gradle profiler ○ https://github.com/gradle/gradle-profiler ● Tips for faster development builds (my slide) ○ https://goo.gl/7zOH9H

Slide 28

Slide 28 text

Thank you