Slide 1

Slide 1 text

Supersonic Speed with JVM Args Dec 7th, 2023 Jason Pearsonโ€จ Senior Staff Engineer Formerly Hinge

Slide 2

Slide 2 text

First, about me:

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

CI experience since 2011. Built Android at Hinge, went from solo dev to 24 Android engineers. Also spent years in backend and fullstack roles across various companies.

Slide 7

Slide 7 text

Agenda Context ๐Ÿ’ป JVM Args Make it Faster

Slide 8

Slide 8 text

Make it Faster 12 9 6 3 0 Unit Tests Release R8 UI Tests Unit Tests Release R8 UI tests minutes

Slide 9

Slide 9 text

~400 Modules ๐Ÿ’ป 290k lines of Kotlin 24 active contributors Context Dagger Hilt (KAPT) ๐Ÿ—ก Gradle Kotlin Scripts KSP (except Dagger)

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

๐Ÿ’ป

Slide 12

Slide 12 text

๐Ÿ’ป

Slide 13

Slide 13 text

๐Ÿ’ป

Slide 14

Slide 14 text

๐Ÿ’ป

Slide 15

Slide 15 text

๐Ÿ’ป

Slide 16

Slide 16 text

๐Ÿ’ป

Slide 17

Slide 17 text

๐Ÿ’ป

Slide 18

Slide 18 text

๐Ÿ’ป ๐Ÿ’ป

Slide 19

Slide 19 text

๐Ÿ’ป ๐Ÿ’ป ๐Ÿ’ป ๐Ÿ’ป

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

โ€œBut why is it taking so long?โ€

Slide 23

Slide 23 text

๐Ÿ— Automate Building & Publishing โ€œBut why is it taking so long?โ€ โฐ

Slide 24

Slide 24 text

๐Ÿ— Automate Building & Publishing ๐Ÿ‘ฉ๐Ÿ”ฌ Automate Tests โ€œBut why is it taking so long?โ€ โฐ

Slide 25

Slide 25 text

๐Ÿ— Automate Building & Publishing ๐Ÿ‘ฉ๐Ÿ”ฌ Automate Tests ๐Ÿ” Automate Security โ€œBut why is it taking so long?โ€ โฐ

Slide 26

Slide 26 text

๐Ÿ— Automate Building & Publishing ๐Ÿ‘ฉ๐Ÿ”ฌ Automate Tests ๐Ÿ” Automate Security โ€œBut why is it taking so long?โ€ โฐ

Slide 27

Slide 27 text

๐Ÿ— Automate Building & Publishing ๐Ÿ‘ฉ๐Ÿ”ฌ Automate Tests ๐Ÿ” Automate Security โฐ ๐Ÿ“ฆ Caching JVM Args ๐Ÿฅท Shadow Jobs Original Problems Scale Problems

Slide 28

Slide 28 text

This is reasonable 12 9 6 3 0 Unit Tests Release R8 UI Tests Unit Tests Release R8 UI tests minutes

Slide 29

Slide 29 text

12 9 6 3 0 Unit Tests Release R8 UI Tests Unit Tests Release R8 UI tests minutes How did we get to this?

Slide 30

Slide 30 text

12 9 6 3 0 Unit Tests Release R8 UI Tests Unit Tests Release R8 UI tests minutes How did we get to this?

Slide 31

Slide 31 text

Control 40 30 20 10 0 Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change minutes cache save gradle execution gradle configuration cache restore git Docker ๐Ÿ‘ฉ๐Ÿ”ฌ Unit Tests on CI

Slide 32

Slide 32 text

Cache Dependencies ๐Ÿ“ฆ

Slide 33

Slide 33 text

Gradle Caches Build Cache Configuration Cache Dependency Cache Script Cache

Slide 34

Slide 34 text

Gradle Caches Build Cache EXECUTING Configuration Cache Dependency Cache Script Cache

Slide 35

Slide 35 text

Gradle Caches Build Cache EXECUTING Configuration Cache Dependency Cache Script Cache

Slide 36

Slide 36 text

Gradle Caches Build Cache EXECUTING Configuration Cache Dependency Cache Script Cache

Slide 37

Slide 37 text

Gradle Caches Build Cache CONFIGURING EXECUTING Configuration Cache Dependency Cache Script Cache

Slide 38

Slide 38 text

Gradle Caches Build Cache Configuration Cache Dependency Cache Script Cache

Slide 39

Slide 39 text

๐Ÿ’ป Local Support Gradle Caches Build Cache ๐Ÿ’ป ๐Ÿ’ป ๐Ÿ’ป Configuration Cache Dependency Cache Script Cache Local Support Local Support Local Support

Slide 40

Slide 40 text

๐Ÿ’ป Local Support Gradle Caches Build Cache ๐Ÿ’ป ๐Ÿ’ป ๐Ÿ’ป Configuration Cache Dependency Cache Script Cache Local Support Local Support Local Support

Slide 41

Slide 41 text

Gradle Cache directories ~/.gradle โ”œโ”€โ”€ caches โ”‚ โ”œโ”€โ”€ 8.1 โ”‚ โ”œโ”€โ”€ 8.2 โ”‚ โ”œโ”€โ”€ โ‹ฎ โ”‚ โ”œโ”€โ”€ buildcacheโ€”1 โ”‚ โ”œโ”€โ”€ jars-9 โ”‚ โ”œโ”€โ”€ journal-1 โ”‚ โ”œโ”€โ”€ modules-2 โ”‚ โ””โ”€โ”€ transforms-3 โ”‚ โ”œโ”€โ”€ โ‹ฎ

Slide 42

Slide 42 text

Gradle Cache directories ~/.gradle โ”œโ”€โ”€ caches โ”‚ โ”œโ”€โ”€ 8.1 โ”‚ โ”œโ”€โ”€ 8.2 โ”‚ โ”œโ”€โ”€ โ‹ฎ โ”‚ โ”œโ”€โ”€ buildcacheโ€”1 โ”‚ โ”œโ”€โ”€ jars-9 โ”‚ โ”œโ”€โ”€ journal-1 โ”‚ โ”œโ”€โ”€ modules-2 โ”‚ โ””โ”€โ”€ transforms-3 โ”‚ โ”œโ”€โ”€ โ‹ฎ Dependency Cache

Slide 43

Slide 43 text

Gradle Cache directories ~/.gradle โ”œโ”€โ”€ caches โ”‚ โ”œโ”€โ”€ 8.1 โ”‚ โ”œโ”€โ”€ 8.2 โ”‚ โ”‚ โ”œโ”€โ”€ generated-gradle-jars โ”‚ โ”‚ โ””โ”€โ”€ kotlin-dsl โ”‚ โ”œโ”€โ”€ โ‹ฎ โ”‚ โ”œโ”€โ”€ buildcacheโ€”1 โ”‚ โ”œโ”€โ”€ jars-9 โ”‚ โ”œโ”€โ”€ journal-1 โ”‚ โ”œโ”€โ”€ modules-2 โ”‚ โ””โ”€โ”€ transforms-3 โ”‚ Dependency Cache Script Cache

Slide 44

Slide 44 text

~/.gradle/caches/<< gradle_version >>/generated-gradle-jars ~/.gradle/caches/<< gradle_version >>/kotlin-dsl ~/.gradle/caches/modules-2 ci-cache.yml

Slide 45

Slide 45 text

๐Ÿ’ป Local Support Gradle Caches Build Cache ๐Ÿ’ป ๐Ÿ’ป ๐Ÿ’ป Configuration Cache Dependency Cache Script Cache Local Support Local Support Local Support

Slide 46

Slide 46 text

Gradle Caches Build Cache ๐Ÿ’ป Configuration Cache Dependency Cache Script Cache Local Support ๐Ÿ’ป Local Support Remote Support Remote Support

Slide 47

Slide 47 text

Control Cache build dependencies 40 30 20 10 0 Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change minutes cache save gradle execution gradle configuration cache restore git Docker

Slide 48

Slide 48 text

Control 40 30 20 10 0 Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change Cache build dependencies minutes cache save gradle execution gradle configuration cache restore git Docker

Slide 49

Slide 49 text

Gradle Properties Prioritizing quick one-liner quick wins None of these are defaults

Slide 50

Slide 50 text

# If you don't turn these on you aren't # getting any performance wins from # Gradle Build Cache or modularization. org.gradle.caching=true org.gradle.parallel=true gradle.properties

Slide 51

Slide 51 text

# Kotlin 1.7+ only # Good reason to upgrade if you are on # an older version. kotlin.incremental.useClasspathSnapshot =true gradle.properties

Slide 52

Slide 52 text

# Incremental compilation with KAPT. # Only if you still use KAPT. kapt.incremental.apt =true gradle.properties

Slide 53

Slide 53 text

# Stop generating BuildConfig Java stubs. # If this is the last Java in your codebase # you could see a decent performance win. android.enableBuildConfigAsBytecode =true gradle.properties

Slide 54

Slide 54 text

# Stop generating BuildConfig files # if you don't use them. android.defaults.buildfeatures.buildconfig =false gradle.properties

Slide 55

Slide 55 text

# Experimental flag for parallelizing # R8 work - only useful if you have # multiple R8 tasks. android.r8.maxWorkers =2 gradle.properties

Slide 56

Slide 56 text

# Summary org.gradle.caching=true org.gradle.parallel=true kotlin.incremental.useClasspathSnapshot=true kapt.incremental.apt=true android.enableBuildConfigAsBytecode=true android.defaults.buildfeatures.buildconfig=false android.r8.maxWorkers=2 gradle.properties

Slide 57

Slide 57 text

Gradle Properties

Slide 58

Slide 58 text

Gradle Properties Other engineers ask me, "Where do you find these?" github.com/androidx/androidx and other OSS projects

Slide 59

Slide 59 text

Control 40 30 20 10 0 Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change Gradle Properties minutes cache save gradle execution gradle configuration cache restore git Docker

Slide 60

Slide 60 text

Control 40 30 20 10 0 Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change minutes cache save gradle execution gradle configuration cache restore git Docker Gradle Properties

Slide 61

Slide 61 text

Cache Build Steps ๐Ÿ“ฆ

Slide 62

Slide 62 text

Gradle Caches Build Cache ๐Ÿ’ป Configuration Cache Dependency Cache Script Cache Local Support ๐Ÿ’ป Local Support Remote Support Remote Support

Slide 63

Slide 63 text

Gradle Caches Build Cache ๐Ÿ’ป Configuration Cache Dependency Cache Script Cache Local Support ๐Ÿ’ป Local Support Remote Support Remote Support

Slide 64

Slide 64 text

Gradle Build Cache - Cacheable Tasks

Slide 65

Slide 65 text

Gradle Build Cache - Modularize โ€ข Reduce the number of inputs per task and make them more stable โ€ข Watch Siggiโ€™s talk about graph theory โ€ข Gradle build scans to observe performance

Slide 66

Slide 66 text

Gradle Remote Cache โ€ข Do it: https://docs.gradle.com/build-cache-node/ โ€ข 90 Days, 300GB, use validation scripts โ€ข Most local and CI runs will benefit from build cache hits โ€ข Free

Slide 67

Slide 67 text

โ€ข Provides support for features beyond remote cache โ€ข Really helps figure out failures, cache misses, and performance issues across a team โ€ข Looking forward to using test prediction.

Slide 68

Slide 68 text

Gradle Caches Build Cache ๐Ÿ’ป Configuration Cache Dependency Cache Script Cache Local Support ๐Ÿ’ป Local Support Remote Support Remote Support

Slide 69

Slide 69 text

Gradle Caches Build Cache ๐Ÿ’ป Configuration Cache Dependency Cache Script Cache Remote Support Local Support Remote Support Remote Support

Slide 70

Slide 70 text

Control 40 30 20 10 0 Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change minutes cache save gradle execution gradle configuration cache restore git Docker Gradle Build Cache Optimization

Slide 71

Slide 71 text

Control 40 30 20 10 0 Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change minutes cache save gradle execution gradle configuration cache restore git Docker Gradle Build Cache Optimization

Slide 72

Slide 72 text

Is it worth it to use the latest JDK

Slide 73

Slide 73 text

Is it worth it to use the latest JDK Yes, 19+

Slide 74

Slide 74 text

โ€ข Yes, 19+ โ€ข 20 and 21 make incremental improvements to G1GC algorithm Is it worth it to use the latest JDK

Slide 75

Slide 75 text

Control JDK 11 -> JDK 19 40 30 20 10 0 Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change minutes cache save gradle execution gradle configuration cache restore git Docker

Slide 76

Slide 76 text

Control 40 30 20 10 0 Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change minutes cache save gradle execution gradle configuration cache restore git Docker JDK 11 -> JDK 19

Slide 77

Slide 77 text

Upgrade Tooling

Slide 78

Slide 78 text

Upgrade Tooling โ€œWill JDK 19โ€จ work on our project?โ€

Slide 79

Slide 79 text

Upgrade Tooling โ€œWill version X of dependency Y work on our project?โ€

Slide 80

Slide 80 text

๐Ÿฅท Shadow Jobs โ€œWill version X of dependency Y work on our project?โ€

Slide 81

Slide 81 text

๐Ÿฅท Shadow Jobs Run nightly checks against your project with latest snapshots of new versions. โ€œWill version X of dependency Y work on our project?โ€ Zac Sweers

Slide 82

Slide 82 text

๐Ÿฅท Shadow Jobs Run nightly checks against your project with latest snapshots of new versions. โ€œWill version X of dependency Y work on our project?โ€ Zac Sweers

Slide 83

Slide 83 text

JVM Argument Tuning

Slide 84

Slide 84 text

JVM Argument Tuning DISCLAIMER: I am not accountable for any of these settings. If they donโ€™t work for you there are so many reasons why your setup would handle them differently.

Slide 85

Slide 85 text

Garbage Collection Algo Tradeoff ๐Ÿ—‘

Slide 86

Slide 86 text

Garbage Collection Algo Tradeoff Each JVM GC algorithm makes a choice about what they optimize for and how much.

Slide 87

Slide 87 text

Garbage Collection Algo Tradeoff

Slide 88

Slide 88 text

Garbage Collection Algo Tradeoff Throughput Transactions per second

Slide 89

Slide 89 text

Garbage Collection Algo Tradeoff Throughput Latency Transactions per second Time spent in GC pauses

Slide 90

Slide 90 text

Garbage Collection Algo Tradeoff Throughput Footprint Latency Transactions per second Time spent in GC pauses Rough memory footprint size

Slide 91

Slide 91 text

Garbage Collection Algo Tradeoff Throughput Footprint Latency

Slide 92

Slide 92 text

Garbage Collection Algo Tradeoff Throughput Footprint Latency

Slide 93

Slide 93 text

Garbage Collection Algo Tradeoff Throughput Footprint Latency

Slide 94

Slide 94 text

Garbage Collection Algo Tradeoff Throughput Footprint Latency ParallelGC G1GC

Slide 95

Slide 95 text

Garbage Collection Algo Tradeoff Throughput Footprint Latency ParallelGC G1GC

Slide 96

Slide 96 text

Garbage Collection Algo Tradeoff Throughput Footprint Latency ParallelGC G1GC

Slide 97

Slide 97 text

ParallelGC Garbage Collection Algo Tradeoff G1GC

Slide 98

Slide 98 text

ParallelGC Garbage Collection Algo Tradeoff G1GC โ€ข Optimize for speed โ€ข Maximum footprint โ€ข Might have longer GC pauses โ€ข Balance throughput โ€ข Lower footprint โ€ข Shorter GC pauses

Slide 99

Slide 99 text

ParallelGC Garbage Collection Algo Tradeoff G1GC โ€ข Optimize for speed โ€ข Maximum footprint โ€ข Might have longer GC pauses โ€ข Balance throughput โ€ข Lower footprint โ€ข Shorter GC pauses Probably safe bet to be stable and fastest for most projects Might be faster for some projects

Slide 100

Slide 100 text

ParallelGC Garbage Collection Algo Tradeoff G1GC โ€ข Optimize for speed โ€ข Maximum footprint โ€ข Might have longer GC pauses โ€ข Balance throughput โ€ข Lower footprint โ€ข Shorter GC pauses โ€ข JDK 20 + 21 improvements! Probably safe bet to be stable and fastest for most projects Might be faster for some projects

Slide 101

Slide 101 text

kotlin.daemon.jvm.options When passing arguments, follow these rules: Use the minus sign - only before the arguments Xmx, XX:MaxMetaspaceSize, and XX:ReservedCodeCacheSize. Separate arguments with commas (,) without spaces. Arguments that come after a space will be used for the Gradle daemon, not for the Kotlin daemon. Kotlin JVM Arguments

Slide 102

Slide 102 text

kotlin.daemon.jvm.options When passing arguments, follow these rules: Use the minus sign - only before the arguments Xmx, XX:MaxMetaspaceSize, and XX:ReservedCodeCacheSize. Separate arguments with commas (,) without spaces. Arguments that come after a space will be used for the Gradle daemon, not for the Kotlin daemon. Kotlin JVM Arguments

Slide 103

Slide 103 text

kotlin.daemon.jvm.options When passing arguments, follow these rules: Use the minus sign - only before the arguments Xmx, XX:MaxMetaspaceSize, and XX:ReservedCodeCacheSize. Separate arguments with commas (,) without spaces. Arguments that come after a space will be used for the Gradle daemon, not for the Kotlin daemon. Kotlin JVM Arguments

Slide 104

Slide 104 text

kotlin.daemon.jvmargs You can add the kotlin.daemon.jvmargs property in the gradle.properties fi le: kotlin.daemon.jvmargs=-Xmx1500m -Xms=500m Kotlin JVM Arguments

Slide 105

Slide 105 text

kotlin.daemon.jvmargs You can add the kotlin.daemon.jvmargs property in the gradle.properties fi le: kotlin.daemon.jvmargs=-Xmx1500m -Xms=500m Using spaces at the beginning will cause all arguments to be ignored Kotlin JVM Arguments

Slide 106

Slide 106 text

Xmx (max) JVM Heap Size Xms (min) โ€ข Amount of memory it takes to compile your biggest task / module. โ€ข For most projects this is going to be your main app moduleโ€™s minification step. โ€ข Somewhere between 80 and 100% of Xmx. โ€ข Heap only grows when GC happens, so increasing it avoids this penalty.

Slide 107

Slide 107 text

JVM Heap Size & Modularization are related

Slide 108

Slide 108 text

MaxMetaspaceSize Metaspace CompressedClassSpaceSize โ€ข class & non-class space โ€ข unlimited by default โ€ข virtual size of compressed classes โ€ข defaults to 1GB

Slide 109

Slide 109 text

Metaspace https://stuefe.de/posts/metaspace/analyze-metaspace-with-jcmd/

Slide 110

Slide 110 text

CompressedOops Metaspace CompressedClassPointers โ€ข Defaults on < 30GB heap โ€ข Uses 4 fewer bytes โ€ข Restricts memory heap to 32GB โ€ข Available if CompressedOops is on

Slide 111

Slide 111 text

What if we turn off CompressedClassSpace + CompressedOops? 20 15 10 5 0 On Off On Off minutes

Slide 112

Slide 112 text

Metaspace CompressedOops & unlimited MaxMetaspace is going to be better for majority of Android projects.

Slide 113

Slide 113 text

Metaspace CompressedOops & unlimited MaxMetaspace is going to be better for majority of Android projects. (so stick with the defaults)

Slide 114

Slide 114 text

Metaspace ~1GB Metaspace helps avoid early Metaspace-related GCs

Slide 115

Slide 115 text

Measuring Metaspace jcmp VM.metaspace

Slide 116

Slide 116 text

CodeCache Where the JVM stores its bytecode into compiled native code

Slide 117

Slide 117 text

CodeCache Where the JVM stores its bytecode into compiled native code

Slide 118

Slide 118 text

CodeCache ReservedCodeCacheSize is the maximum amount for cached bytecode

Slide 119

Slide 119 text

CodeCache So we gave ReservedCodeCacheSize 512mb

Slide 120

Slide 120 text

CodeCache To determine what number you should use, measure via JVM arg: โ€“XX:+PrintCodeCache

Slide 121

Slide 121 text

SoftRefLRUPolicyMSPerMB The number of milliseconds to hold onto soft references per MB of heap size, default 1000

Slide 122

Slide 122 text

SoftRefLRUPolicyMSPerMB The number of milliseconds to hold onto soft references per MB of heap size, default 1000 = 2h 16m 32s 8GB Heap @ 1000 MS Policy

Slide 123

Slide 123 text

SoftRefLRUPolicyMSPerMB The number of milliseconds to hold onto soft references per MB of heap size, default 1000 = 2h 16m 32s 8GB Heap @ 1000 MS Policy 8GB Heap @ 10 MS Policy = 0h 1m 22s

Slide 124

Slide 124 text

SoftRefLRUPolicyMSPerMB The number of milliseconds to hold onto soft references per MB of heap size, default 1000 = 2h 16m 32s 8GB Heap @ 1 MS Policy 8GB Heap @ 1000 MS Policy = 0h 0m 8s 8GB Heap @ 10 MS Policy = 0h 1m 22s

Slide 125

Slide 125 text

Gradle Max Workers --max-workers The maximum number of active workers to allow Should probably be number of performance cores, possibly 1-2 less Will not spawn more workers is memory heap requirements cannot be met

Slide 126

Slide 126 text

jemalloc / tcmalloc Memory fragmentation slows down builds, use a better malloc algorithm

Slide 127

Slide 127 text

malloc alternatives Memory fragmentation slows down builds, use a better malloc algorithm

Slide 128

Slide 128 text

malloc alternatives We saw no speed difference with jemalloc, but it did notice 10% less memory usage

Slide 129

Slide 129 text

malloc alternatives Therefore use jemalloc (or tcmalloc) to be able to run more daemons in parallel with less memory pressure.

Slide 130

Slide 130 text

What do we actually pick for JVM args?

Slide 131

Slide 131 text

๐Ÿฅท Shadow Jobs 1. Instrument your build with JVM args as parameters 2. Run parameterized tests 3. Profit What do we actually pick for JVM args?

Slide 132

Slide 132 text

โ€ข GC Algo = It Depends โ€ข SoftRefLRUPolicyMSPerMB = 1 โ€ข CodeCache = 256MB - 512MB โ€ข MaxMetaspace = Some GB or unlimited โ€ข Metaspace = 64MB - 1GB โ€ข Xmx = 4GB - 12GB โ€ข Xms = Xmx โ€ข Max Workers=Performance Cores - 2 What do we actually pick?

Slide 133

Slide 133 text

โ€ข jcmp for Metaspace โ€ข โ€“XX:+PrintCodeCache for CodeCache โ€ข Measure CPU & Memory resource usage, lots of tools available JVM Measurement Tools

Slide 134

Slide 134 text

Control JVM Optimizations 40 30 20 10 0 Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change minutes cache save gradle execution gradle configuration cache restore git Docker

Slide 135

Slide 135 text

Control 40 30 20 10 0 Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change minutes cache save gradle execution gradle configuration cache restore git Docker JVM Optimizations

Slide 136

Slide 136 text

Control 40 30 20 10 0 Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change minutes cache save gradle execution gradle configuration cache restore git Docker JVM Optimizations

Slide 137

Slide 137 text

Gradle Caches Build Cache Configuration Cache Dependency Cache Script Cache Remote Support Remote Support Remote Support ๐Ÿ’ป Local Support

Slide 138

Slide 138 text

Gradle Caches Build Cache Configuration Cache Dependency Cache Script Cache Remote Support Remote Support Remote Support ๐Ÿ’ป Local Support

Slide 139

Slide 139 text

# Enables the configuration cache: org.gradle.configuration-cache=true org.gradle.configuration-cache.problems=warn org.gradle.configuration-cache.inputs.unsafe.ignore.file-system- checks=(see github.com/androidx/androidx repo gradle.properties) gradle.properties

Slide 140

Slide 140 text

Gradle Cache directories ~/.gradle โ”œโ”€โ”€ caches โ”‚ โ””โ”€โ”€ โ‹ฎ Dependency Cache Script Cache

Slide 141

Slide 141 text

Gradle Cache directories ~/.gradle โ”œโ”€โ”€ caches โ”‚ โ””โ”€โ”€ โ‹ฎ ~/project โ”œโ”€โ”€ .gradle โ”œโ”€โ”€ app โ”œโ”€โ”€ build โ”œโ”€โ”€ gradle โ””โ”€โ”€ โ‹ฎ Dependency Cache Script Cache

Slide 142

Slide 142 text

Gradle Cache directories ~/project โ”œโ”€โ”€ .gradle โ”œโ”€โ”€ app โ”œโ”€โ”€ build โ”œโ”€โ”€ gradle โ””โ”€โ”€ โ‹ฎ

Slide 143

Slide 143 text

Gradle Cache directories ~/project โ”œโ”€โ”€ .gradle โ”‚ โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ app โ”œโ”€โ”€ build โ”œโ”€โ”€ gradle โ””โ”€โ”€ โ‹ฎ

Slide 144

Slide 144 text

Gradle Cache directories ~/project โ”œโ”€โ”€ .gradle โ”‚ โ”œโ”€โ”€ 8.1 โ”‚ โ”œโ”€โ”€ 8.2 โ”‚ โ”œโ”€โ”€ โ‹ฎ โ”‚ โ””โ”€โ”€ configuration-cache โ”œโ”€โ”€ app โ”œโ”€โ”€ build โ”œโ”€โ”€ gradle โ””โ”€โ”€ โ‹ฎ

Slide 145

Slide 145 text

~/project โ”œโ”€โ”€ .gradle โ”‚ โ”œโ”€โ”€ 8.1 โ”‚ โ”œโ”€โ”€ 8.2 โ”‚ โ”œโ”€โ”€ โ‹ฎ โ”‚ โ””โ”€โ”€ configuration-cache โ”œโ”€โ”€ app โ”œโ”€โ”€ build โ”œโ”€โ”€ gradle โ””โ”€โ”€ โ‹ฎ Configuration Cache Gradle Cache directories

Slide 146

Slide 146 text

~/.gradle/caches/<< gradle_version >>/generated-gradle-jars ~/.gradle/caches/<< gradle_version >>/kotlin-dsl ~/.gradle/caches/modules-2 .gradle/<< gradle_version >> .gradle/configuration-cache ci-cache.yml

Slide 147

Slide 147 text

As of Gradle 8.1 encryption was added. Asking Gradle support - configuration cache on CI is unsupported Gradle Configuration Cache on CI

Slide 148

Slide 148 text

As of Gradle 8.1 encryption was added. Gradle's response has been that configuration cache on CI is not supported Gradle Configuration Cache on CI

Slide 149

Slide 149 text

As of Gradle 8.1 encryption was added. Gradle's response has been that configuration cache on CI is not supported. But we persisted anyway... Gradle Configuration Cache on CI

Slide 150

Slide 150 text

Gradle Configuration Cache on CI Environment Variable Environment Variables Prefixed File system Entry File System property Value from custom source 35 1 2007 4 52 5 build/reports/configuration-cache/4tnz..i67j/27o6..b0jl/configuration-cache-report.html We looked at the reports for all inputs

Slide 151

Slide 151 text

But despite everything 100% of inputs being consistent we continued to get an unhelpful error message: Gradle Configuration Cache on CI

Slide 152

Slide 152 text

Gradle Configuration Cache on CI Calculating task graph as no configuration cache is available for tasks

Slide 153

Slide 153 text

Gradle Configuration Cache on CI โ€œYou need to cache the encryption key.โ€ โ€” Inaki Villar

Slide 154

Slide 154 text

Gradle Configuration Cache on CI Caveat to this method - you will be caching any secrets used by this build, so either: โ€ข Only use this for builds that do not rely on secrets โ€ข Knowingly store this with the security risk

Slide 155

Slide 155 text

No content

Slide 156

Slide 156 text

Gradle Configuration Cache on CI

Slide 157

Slide 157 text

Gradle User Home directory ~/.gradle โ”œโ”€โ”€ caches โ”‚ โ”œโ”€โ”€ 8.1 โ”‚ โ”‚ โ€ฆ โ”‚ โ”œโ”€โ”€ 8.4 โ”‚ โ”‚ โ””โ”€โ”€ cc-keystore โ”‚ โ”‚ โ”œโ”€โ”€ cache.properties โ”‚ โ”‚ โ”œโ”€โ”€ cc-keystore.lock โ”‚ โ”‚ โ””โ”€โ”€ gradle.keystore โ”‚ โ”œโ”€โ”€ โ”‚ โ”œโ”€โ”€ buildcacheโ€”1 โ”‚ โ”œโ”€โ”€ jars-9 โ”‚ โ”œโ”€โ”€ journal-1 Configuration Cache Encryption

Slide 158

Slide 158 text

~/.gradle/caches/<< gradle_version >>/generated-gradle-jars ~/.gradle/caches/<< gradle_version >>/kotlin-dsl ~/.gradle/caches/modules-2 .gradle/<< gradle_version >> .gradle/configuration-cache ci-cache.yml

Slide 159

Slide 159 text

~/.gradle/caches/<< gradle_version >>/generated-gradle-jars ~/.gradle/caches/<< gradle_version >>/kotlin-dsl ~/.gradle/caches/<< gradle_version >>/cc-keystore ~/.gradle/caches/modules-2 .gradle/<< gradle_version >> .gradle/configuration-cache ci-cache.yml

Slide 160

Slide 160 text

Gradle Configuration Cache on CI Calculating task graph as no configuration cache is available for tasks

Slide 161

Slide 161 text

unit_tests: docker: - image: circleci/android:api-34-node steps: - run: name: Clean Gradle Cache command: | find . -type f -name '*.lock' -delete find . -type f -name 'gc.properties' -delete find ~/.gradle -type f -name '*.lock' -delete find ~/.gradle -type f -name 'gc.properties' -delete when: always - save_cache: paths: - ~/.gradle/caches/<< parameters.gradle_version >>/ generated-gradle-jars - ~/.gradle/caches/<< parameters.gradle_version >>/ kotlin-dsl - .gradle/configuration-cache - ~/.gradle/caches/<< parameters.gradle_version >>/ cc-keystore - .gradle/<< parameters.gradle_version >> config.yml

Slide 162

Slide 162 text

unit_tests: docker: - image: circleci/android:api-34-node steps: - run: name: Clean Gradle Cache command: | find . -type f -name '*.lock' -delete find . -type f -name 'gc.properties' -delete find ~/.gradle -type f -name '*.lock' -delete find ~/.gradle -type f -name 'gc.properties' -delete when: always - save_cache: paths: - ~/.gradle/caches/<< parameters.gradle_version >>/ generated-gradle-jars - ~/.gradle/caches/<< parameters.gradle_version >>/ kotlin-dsl - .gradle/configuration-cache - ~/.gradle/caches/<< parameters.gradle_version >>/ cc-keystore - .gradle/<< parameters.gradle_version >> config.yml ๐Ÿคฆ

Slide 163

Slide 163 text

Gradle Configuration Cache on CI Calculating task graph as configuration cache cannot be reused because an input to task โ€˜:gradle-plugin:generateExternalPluginSpecBuilders' has changed.

Slide 164

Slide 164 text

Gradle Configuration Cache on CI Calculating task graph as configuration cache cannot be reused because an input to task โ€˜:gradle-plugin:generateExternalPluginSpecBuilders' has changed.

Slide 165

Slide 165 text

โ€œGradle has compilation avoidance for non- ABI changes in included builds, but due to a bug any inline function would cause all build scripts to be recompiled even when there is a non-ABI change.โ€ - Nicklas Ansman Gradle Configuration Cache on CI

Slide 166

Slide 166 text

~/.gradle/caches/<< gradle_version >>/generated-gradle-jars ~/.gradle/caches/<< gradle_version >>/kotlin-dsl ~/.gradle/caches/<< gradle_version >>/cc-keystore ~/.gradle/caches/modules-2 .gradle/<< gradle_version >> .gradle/configuration-cache gradle-plugin/build/pluginDescriptors ci-cache.yml

Slide 167

Slide 167 text

Gradle Configuration Cache on CI Could not load the value of field `patterns` of `org.gradle.configurationcache.serialization.codecs.DirectoryTree Spec` bean found in field `fileSystemInputs` of `org.gradle.configurationcache.fingerprint.ConfigurationCacheFing erprint$WorkInputs` bean found in Gradle runtime. > Failed to instrument class org/jetbrains/kotlin/gradle/tasks/ KotlinCompile$ScriptFilterSpec in ClassLoaderScopeIdentifier.Id{coreAndPlugins:settings[:gradle- plugin]:buildSrc[:gradle-plugin]:root-project[:gradle-plugin] (export)}

Slide 168

Slide 168 text

Gradle Configuration Cache on CI Could not load the value of field `patterns` of `org.gradle.configurationcache.serialization.codecs.DirectoryTree Spec` bean found in field `fileSystemInputs` of `org.gradle.configurationcache.fingerprint.ConfigurationCacheFing erprint$WorkInputs` bean found in Gradle runtime. > Failed to instrument class org/jetbrains/kotlin/gradle/tasks/ KotlinCompile$ScriptFilterSpec in ClassLoaderScopeIdentifier.Id{coreAndPlugins:settings[:gradle- plugin]:buildSrc[:gradle-plugin]:root-project[:gradle-plugin] (export)}

Slide 169

Slide 169 text

~/.gradle/caches/<< gradle_version >>/generated-gradle-jars ~/.gradle/caches/<< gradle_version >>/kotlin-dsl ~/.gradle/caches/<< gradle_version >>/cc-keystore ~/.gradle/caches/modules-2 .gradle/<< gradle_version >> .gradle/configuration-cache gradle-plugin/build/pluginDescriptors ci-cache.yml

Slide 170

Slide 170 text

~/.gradle/caches/<< gradle_version >>/generated-gradle-jars ~/.gradle/caches/<< gradle_version >>/kotlin-dsl ~/.gradle/caches/<< gradle_version >>/cc-keystore ~/.gradle/caches/modules-2 .gradle/<< gradle_version >> .gradle/configuration-cache gradle-plugin/build ci-cache.yml

Slide 171

Slide 171 text

~/.gradle/caches/<< gradle_version >>/generated-gradle-jars ~/.gradle/caches/<< gradle_version >>/kotlin-dsl ~/.gradle/caches/<< gradle_version >>/cc-keystore ~/.gradle/caches/modules-2 ~/.gradle/caches/jars-9 ~/.gradle/caches/transforms-3 .gradle/<< gradle_version >> .gradle/configuration-cache gradle-plugin/build ci-cache.yml

Slide 172

Slide 172 text

Reusing configuration cache. Gradle Configuration Cache on CI

Slide 173

Slide 173 text

Gradle Configuration Cache on CI

Slide 174

Slide 174 text

Gradle Configuration Cache on CI

Slide 175

Slide 175 text

โ€œWow, I was prepared for a faster PR time but that was blazingโ€ - Jacob Duron Gradle Configuration Cache on CI

Slide 176

Slide 176 text

Gradle Configuration Cache Update

Slide 177

Slide 177 text

โ€œI believe its in the interest of Gradle and the community to support a method to share the configuration cache between machines that doesn't expose build secretsโ€ - me Gradle Configuration Cache Update

Slide 178

Slide 178 text

TLDR; Wait for Gradle 8.6 and a new GitHub Gradle Build Action Gradle Configuration Cache Update

Slide 179

Slide 179 text

Gradle Caches Build Cache Configuration Cache Dependency Cache Script Cache Remote Support Remote Support Remote Support ๐Ÿ’ป Local Support

Slide 180

Slide 180 text

Gradle Caches Build Cache Configuration Cache Dependency Cache Script Cache Remote Support Remote Support Remote Support Remote Support

Slide 181

Slide 181 text

Control Gradle Configuration Cache Reuse 40 30 20 10 0 Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change minutes cache save gradle execution gradle configuration cache restore git Docker

Slide 182

Slide 182 text

Control Gradle Configuration Cache Reuse 40 30 20 10 0 Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change minutes cache save gradle execution gradle configuration cache restore git Docker

Slide 183

Slide 183 text

40 30 20 10 0 Gradle Configuration Cache Reuse Control Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change minutes cache save gradle execution gradle configuration cache restore git Docker

Slide 184

Slide 184 text

Overhead Cost Optimizations ๐Ÿ“ฆ git clone pulls 400 MB big images (2.5 GB) Minutes to save cache ~60 seconds to restore cache

Slide 185

Slide 185 text

GitHub Actions ๐Ÿ“ฆ pulls run at 200mb/s base images are cached better cache restore and save operations runs 2-5x faster

Slide 186

Slide 186 text

Control Present Day Unit Test Runs 40 30 20 10 0 Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change minutes cache save gradle execution gradle configuration cache restore git Docker

Slide 187

Slide 187 text

40 30 20 10 0 Control Partial Cache Hit Cache Hit Core Change Cache Hit Leaf Change minutes cache save gradle execution gradle configuration cache restore git Docker Present Day Unit Test Runs

Slide 188

Slide 188 text

CI Speed Optimizations Cache Dependencies Cache Build Tasks Cache Configuration JVM Tuning Compiler Flags ๐Ÿ‹ ๐Ÿ“ฆ ๐Ÿšฉ

Slide 189

Slide 189 text

CI Speed Optimizations Cache Dependencies Cache Build Tasks Cache Configuration JVM Tuning Compiler Flags ๐Ÿ‹ ๐Ÿ“ฆ ๐Ÿšฉ โœ…

Slide 190

Slide 190 text

CI Speed Optimizations Cache Dependencies Cache Build Tasks Cache Configuration JVM Tuning Compiler Flags ๐Ÿ‹ ๐Ÿ“ฆ ๐Ÿšฉ โœ… โœ…

Slide 191

Slide 191 text

Questions? kaeawc / android-ci Proof of Concept:

Slide 192

Slide 192 text

Metaspace Citations Thomas Stรผfe Blog https://stuefe.de/posts/metaspace/what-is-metaspace/ https://stuefe.de/posts/metaspace/metaspace-architecture/ https://stuefe.de/posts/metaspace/what-is-compressed-class-space/ https://stuefe.de/posts/metaspace/sizing-metaspace/ https://stuefe.de/posts/metaspace/analyze-metaspace-with-jcmd/ Oracle Class Metadata, PermGen and changes to native memory allocation

Slide 193

Slide 193 text

Gradle Documentation Gradle Files & Directories https://docs.gradle.org/current/userguide/directory_layout.html Gradle CI Ephemeral Best Practices https://docs.gradle.org/current/userguide/ dependency_resolution.html#sub:ephemeral-ci-cache Gradle Recommends using Daemons for CI https://docs.gradle.org/current/userguide/ gradle_daemon.html#continuous_integration

Slide 194

Slide 194 text

Kotlin JVM Args Documentation New Method https://kotlinlang.org/docs/gradle-compilation-and-caches.html#kotlin- daemon-jvmargs-property Deprecated Method https://kotlinlang.org/docs/gradle-compilation-and-caches.html#kotlin- daemon-jvm-options-system-property

Slide 195

Slide 195 text

JDK Version Documentation JDK Release Notes Summaries for GC Algo Changes 19 | 20 | 21 JVM SoftReferences Tuning CodeCache

Slide 196

Slide 196 text

JVM SoftReferences JVM SoftReferences

Slide 197

Slide 197 text

JVM CodeCache Tuning CodeCache

Slide 198

Slide 198 text

Shadow Jobs by Zac Sweers https://slack.engineering/shadow-jobs/