Slide 1

Slide 1 text

Cache Me If You Can 2025.09.12 DroidKaigi 2025 RyuNen344

Slide 2

Slide 2 text

Cache Me If You Can 2025.09.12 DroidKaigi 2025 RyuNen344 🐘

Slide 3

Slide 3 text

Materials

Slide 4

Slide 4 text

Ice Break

Slide 5

Slide 5 text

͜Μͳܦݧ͋Γ·ͤΜ͔

Slide 6

Slide 6 text

ϚϧνϞδϡʔϧͳͷʹϏϧυ͕஗ ͍ɾɾɾɾ Cache͕ޮ͍ͯͳͦ͞͏ɾɾɾ

Slide 7

Slide 7 text

Android Gradle PluginΛ্͛ͨΒ Ϗϧυ͕յΕͨ

Slide 8

Slide 8 text

ΧελϜλεΫͷCache͕ޮ͔ͳ͍

Slide 9

Slide 9 text

GradleΑ͘Θ͔Βͳ͍ɾɾɾ

Slide 10

Slide 10 text

Agendas 1. Today's Goals 2. Why Gradle? How the Android Gradle Plugin works? 3. Lifecycle and Lifecycle-aware, everywhere 4. Cache of Gradle 5. Faster, Faster, Faster 6. Key Takeaways

Slide 11

Slide 11 text

Today’s Goal • Understands basic concepts of Gradle • Taming Android Gradle Plugin → The ABCs of Faster Gradle Builds

Slide 12

Slide 12 text

⚠ Caution ⚠ • ίϯηϓτɾߟ͑ํ͕ϝΠϯ • Ϗϧυ͕N෼୹͘ͳͬͨɾNˋߴ଎Խͨ͠ͳͲ͸φγ • GradleɾAndroid Gradle Pluginͷ͓࡞๏ʹ஫ྗ

Slide 13

Slide 13 text

Why Gradle?

Slide 14

Slide 14 text

Why Gradle? • Project and Task • Gradle can do anything • Easy to cache

Slide 15

Slide 15 text

Project and Task

Slide 16

Slide 16 text

Project and Task ./gradlew :sub-project-B:Task c Task c <- Task b <- Task 1

Slide 17

Slide 17 text

Project and Task • Extension as Gradle Plugin • Several Language Support by Of fi cial Gradle Plugin • C++, Swift and multiple JVM based languages C++

Slide 18

Slide 18 text

Gradle can do anything

Slide 19

Slide 19 text

Easy to cache • Gradle watches Task inputs/outputs • Developer just de fi ne deterministic input and Gradle Task action

Slide 20

Slide 20 text

How the Android Gradle Plugin works?

Slide 21

Slide 21 text

How AGP? :app:assembleDebug +--- :app:mergeDebugNativeDebugMetadata | \--- :app:preDebugBuild | \--- :app:preBuild \--- :app:packageDebug +--- :app:compileDebugJavaWithJavac +--- :app:compressDebugAssets +--- :app:l8DexDesugarLibDebug +--- :app:mergeDebugAssets * +--- :app:mergeDebugJavaResource +--- :app:mergeExtDexDebug +--- :app:mergeLibDexDebug +--- :app:mergeProjectDexDebug +--- :app:preDebugBuild * +--- :app:processDebugManifestForPackage +--- :app:processDebugResources * +--- :app:stripDebugDebugSymbols +--- :app:validateSigningDebug +--- :app:writeDebugAppMetadata \--- :app:writeDebugSigningConfigVersions • Assemble task depends on many tasks

Slide 22

Slide 22 text

How AGP? :app:assembleDebug +--- :app:mergeDebugNativeDebugMetadata | \--- :app:preDebugBuild | \--- :app:preBuild \--- :app:packageDebug +--- :app:compileDebugJavaWithJavac +--- :app:compressDebugAssets +--- :app:l8DexDesugarLibDebug +--- :app:mergeDebugAssets * +--- :app:mergeDebugJavaResource +--- :app:mergeExtDexDebug +--- :app:mergeLibDexDebug +--- :app:mergeProjectDexDebug +--- :app:preDebugBuild * +--- :app:processDebugManifestForPackage +--- :app:processDebugResources * +--- :app:stripDebugDebugSymbols +--- :app:validateSigningDebug +--- :app:writeDebugAppMetadata \--- :app:writeDebugSigningConfigVersions • Assemble task depends on many tasks • AGP tells Gradle what the inputs and output of the Assemble task

Slide 23

Slide 23 text

How AGP? :app:assembleDebug +--- :app:mergeDebugNativeDebugMetadata | \--- :app:preDebugBuild | \--- :app:preBuild \--- :app:packageDebug +--- :app:compileDebugJavaWithJavac +--- :app:compressDebugAssets +--- :app:l8DexDesugarLibDebug +--- :app:mergeDebugAssets * +--- :app:mergeDebugJavaResource +--- :app:mergeExtDexDebug +--- :app:mergeLibDexDebug +--- :app:mergeProjectDexDebug +--- :app:preDebugBuild * +--- :app:processDebugManifestForPackage +--- :app:processDebugResources * +--- :app:stripDebugDebugSymbols +--- :app:validateSigningDebug +--- :app:writeDebugAppMetadata \--- :app:writeDebugSigningConfigVersions • Assemble task depends on many tasks • AGP tells Gradle what the inputs and output of the Assemble task When and Where does AGP tell that to Gradle?

Slide 24

Slide 24 text

Lifecycle and Lifecycle-aware, everywhere Gradle has a lifecycle

Slide 25

Slide 25 text

Lifecycle and Lifecycle-aware, everywhere • Gradle has a lifecycle

Slide 26

Slide 26 text

Initialization Phase • Read settings.gradle and recognize project structure • Specify dependency resolution strategies • Apply settings plugin

Slide 27

Slide 27 text

Con fi guration Phase • Read project’s build.gradle • Apply plugin to project • plugin creates con fi guration and tasks • Resolve dependencies • Graph resolution phase • Artifact resolution phase • Execute build scripts

Slide 28

Slide 28 text

Execution Phase • Execute tasks • Determine which tasks to execute by the task execution graphs • UP-TO-DATE and FROM-CACHE mean that Gradle has skipped a task by using incremental builds or the build cache

Slide 29

Slide 29 text

Also, AGP has a lifecycle AGP's Lifecycle

Slide 30

Slide 30 text

AGP's Lifecycle • Key points to understand AGP's Lifecycle

Slide 31

Slide 31 text

AGP's Lifecycle

Slide 32

Slide 32 text

AGP's Lifecycle • In old Variant API could make a variant disabled after creation • This can break the Task Graph(DAG) • It’s not good for Build Cache(even Con fi guration Cache)

Slide 33

Slide 33 text

AGP's Lifecycle

Slide 34

Slide 34 text

Lifecycle and Lifecycle-aware, everywhere

Slide 35

Slide 35 text

Wrap-up Part 1 • Gradle has a lifecycle • Gradle manages task dependencies and forms a DAG • Gradle reuses task results based on task input/output • Android Gradle Plugin also has a lifecycle • Recent API changes in AGP are to conform to Gradle's lifecycle • Old Variant API is scheduled to be deprecated in AGP 9.0.0, removed in 10.0.0, so it's recommended to migrate to the new API now

Slide 36

Slide 36 text

Before We Get to the Cache of Gradle • Idempotence • same input must produce the same output • Performance • appropriate granularity of cache makes high cache hit rate • cache hit is faster than re-execution

Slide 37

Slide 37 text

Cache of Gradle

Slide 38

Slide 38 text

Cache of Gradle : UP-TO-DATE Incremental build: `UP-TO-DATE`

Slide 39

Slide 39 text

Cache of Gradle : UP-TO-DATE

Slide 40

Slide 40 text

Cache of Gradle : UP-TO-DATE

Slide 41

Slide 41 text

Cache of Gradle : FROM-CACHE

Slide 42

Slide 42 text

Cache of Gradle : FROM-CACHE • Based on: • Hash of the task implementation class • All declared inputs • Task Identi fi er • Normalized content hash of fi le inputs used as fi ngerprint • build script is also included in key calculations (e.g. `doFirst`, `doLast`) • Env and System Props will not include unless explicitly declared as input

Slide 43

Slide 43 text

Cache of Gradle : Reusing con fi guration cache

Slide 44

Slide 44 text

Cache of Gradle : Reusing con fi guration cache When hit con fi skip con fi Skip

Slide 45

Slide 45 text

Cache of Gradle : Reusing con fi guration cache • Based on: • GRADLE_USER_HOME • init script • included build scripts • Custom Value Source • System Property and environment • etc… • Requirements: • implements java.io.Serializable

Slide 46

Slide 46 text

Wrap-up Part 2 • Incremental build and Build cache • re-use task results based on task input/output • Con fi guration cache • re-use task graph based on con fi guration inputs • Gradle uses different scopes and targets of cache to speed up builds in multiple ways • Con fi guration Cache became the preferred execution mode • Update your API to prevent issues, same as AndroidComponents API

Slide 47

Slide 47 text

Faster, faster, faster

Slide 48

Slide 48 text

Faster, faster, faster • Make input/output/con fi gurations more deterministic • Optimize project structure

Slide 49

Slide 49 text

Faster, faster, faster • First of all, enabling cache features

Slide 50

Slide 50 text

Make input/output more deterministic • Make input/output/con fi gurations more deterministic • Optimize project structure

Slide 51

Slide 51 text

Make input/output more deterministic • De fi ne @Input and @Output • To enable incremental builds, de fi ne an output property even for tasks that don’t have output • Use Gradle Provider or Property API, instead of Primitive class

Slide 52

Slide 52 text

Make input/output more deterministic • When inputs have changed, outputs must change • Avoid using non-declared inputs (Do not use Env or system prop inside TaskAction) •Annotate with @CacheableTask

Slide 53

Slide 53 text

Make input/output more deterministic • Avoid using random value as inputs • Use abstracted fi le paths so that the cache does not depend on the environment • Do not edit task output in build script

Slide 54

Slide 54 text

Make input/output more deterministic https://docs.gradle.org/current/userguide/incremental_build.html#sec:task_input_output_annotations

Slide 55

Slide 55 text

Make con fi guration more deterministic • Can't build project, after adding `org.gradle.con fi guration- cache=true` 😇

Slide 56

Slide 56 text

Make con fi guration more deterministic • Do not use `afterEvaluate` block • `afterEvaluate` block executes after con fi guration phase • `afterEvaluate` can break con fi guration phase result

Slide 57

Slide 57 text

Make con fi guration more deterministic • Do not touch non- serializable objects in execution time

Slide 58

Slide 58 text

Make con fi guration more deterministic • Use `ProjectLayout` or `BuildLayout` API to access fi les instead of `project` • Use injected `{FileSystem| Archive|Exec}`Operations to access fi les instead of `project`

Slide 59

Slide 59 text

Make con fi guration more deterministic • Use `ProviderFactory` API to access environment variables, system properties, external process results instead of `System` or direct execution

Slide 60

Slide 60 text

Make con fi gurations more deterministic https://docs.gradle.org/current/userguide/ con fi guration_cache_requirements.html#con fi g_cache:requirements:use_project_during_execution

Slide 61

Slide 61 text

Use AndroidComponents API • Use AndroidComponents API for deterministic con fi guration

Slide 62

Slide 62 text

Use AndroidComponents API • AndroidComponents API enables correct integration into the build process

Slide 63

Slide 63 text

Use Android Components API https://github.com/android/gradle-recipes

Slide 64

Slide 64 text

Optimize project structure • Android app developer needs fast build 1. Adoption of Jetpack Compose 2. Multi-module as a prerequisite

Slide 65

Slide 65 text

Optimize project structure 1.Remove redundant Gradle plugin from sub-project 2.Remove redundant dependency (library or project) 3.Do not con fi gure build variant/project fl avor on library module, use DI

Slide 66

Slide 66 text

Optimize project structure

Slide 67

Slide 67 text

Optimize project structure Improve cache hit rate & Narrow re-compile scope

Slide 68

Slide 68 text

Optimize project structure

Slide 69

Slide 69 text

Optimize project structure

Slide 70

Slide 70 text

Optimize project structure

Slide 71

Slide 71 text

Use Build Scan® • Gradle Knows Gradle Better Than You Know about Gradle • Visualize parallelism on Web UI

Slide 72

Slide 72 text

Use Develocity® Plugin • You can visualize without metadata publication • Visualize parallelism on IntelliJ and Android Studio

Slide 73

Slide 73 text

Key Takeaways • Gradle has a lifecycle, AGP also has a lifecycle • Gradle has different scopes and targets of cache to speed up builds in multiple ways • Make input/output/con fi gurations more deterministic • Use Gradle's provided APIs instead of `project` or `System` • Modify artifacts through AndroidComponents API • Optimize project structure to reduce re-compilation scope and increase parallelism • Use Build Scan and Develocity Plugin

Slide 74

Slide 74 text

About Me • Bunjiro Miyoshi (id: RyuNen344) • KMPΛֶΜͩΒͳ͔ͥGradleͷ஌͕ࣝ૿͑ͨ • Kodee͘Μݟ͔͚ͨΒͥͻ #KodeeEverywhere ͷϋογϡλάΛ͚ͭͯᄁ͖Λʂ

Slide 75

Slide 75 text

Appendix

Slide 76

Slide 76 text

Q. What’s next ? A. Lazy Con fi guration • Gradle 8.14.3 : Con fi gurations are initialized lazily • https://docs.gradle.org/8.14.3/ release- notes.html#con fi gurations-are- initialized-lazily • AGP 8.12.0 supports lazy con fi guration • https://issuetracker.google.com/ issues/416349489

Slide 77

Slide 77 text

Q. What’s next ? A. Isolated Projects • https://docs.gradle.org/current/userguide/isolated_projects.html • Isolated Projects extends the con fi guration cache • the con fi guration model of Gradle projects are "isolated" from each other • Make con fi guration cache more immutable • Make con fi guration cache safely run in parallel

Slide 78

Slide 78 text

Improvements of o ff i cial documents • JetBrains - Working with Gradle • https://www.jetbrains.com/guide/java/tutorials/working-with-gradle/ • Android Developers - Con fi gure your build • https://developer.android.com/studio/build • Android Developers - Write Gradle plugins • https://developer.android.com/build/extend-agp • Gradle - Improve the Performance of Gradle Builds • https://docs.gradle.org/current/userguide/performance.html • Gradle - Cookbook • https://cookbook.gradle.org/

Slide 79

Slide 79 text

EOF