CI Context
Single Docker image
Datadog, Umbra
Firebase Test Lab
Gradle Develocity
Self hosted EC2 Runners
Artifactory
GitLab CI
Slide 37
Slide 37 text
Very long MR pipeline times
Slide 38
Slide 38 text
β’ 3-4 minutes pipeline veri
fi
cation jobs
β’ 30 minutes in Lint
β’ 50+ minutes in Test
β’ ~30 minutes Building APKs
β’ ~15 minutes running integration tests that are unreliable
Very long MR pipeline times
Slide 39
Slide 39 text
The Journey to Performant Android CI
Slide 40
Slide 40 text
The Journey to Performant Android CI
Some caching via Develocity
π¦
All artifacts all the time
Full git clone via GitLab
Slow and flaky UI tests
Slide 41
Slide 41 text
The Journey to Performant Android CI
Some caching via Develocity
π¦
All artifacts all the time
Full git clone via GitLab
Slow and flaky UI tests
Slide 42
Slide 42 text
The Journey to Performant Android CI
Everything cached
π¦
All artifacts all the time
Full git clone via GitLab
Slow and flaky UI tests
Slide 43
Slide 43 text
The Journey to Performant Android CI
Everything cached
π¦
Minimize git overhead
All artifacts all the time
Slow and flaky UI tests
Slide 44
Slide 44 text
The Journey to Performant Android CI
Everything cached
π¦
Minimize git overhead
Fast & Reliable UI Tests
All artifacts all the time
Slide 45
Slide 45 text
The Journey to Performant Android CI
Everything cached
π¦
Only artifacts as needed
Fast & Reliable UI Tests
Minimize git overhead
Slide 46
Slide 46 text
Fast & Reliable
Laterβ¦
Minimize git overhead
The Journey to Performant Android CI
Everything cached
π¦
Only artifacts as needed
Slide 47
Slide 47 text
Fast & Reliable
Only artifacts as needed
Minimize git overhead
The Journey to Performant Android CI
Everything cached
π¦
Laterβ¦
Slide 48
Slide 48 text
Fast & Reliable
Only artifacts as needed
Minimize git overhead
The Journey to Performant Android CI
Everything cached
π¦
Laterβ¦
Slide 49
Slide 49 text
Fast & Reliable
Only artifacts as needed
Minimize git overhead
The Journey to Performant Android CI
Laterβ¦
Build & Cache Techniques
π¦
Slide 50
Slide 50 text
Fast & Reliable
Only artifacts as needed
The Journey to Performant Android CI
Laterβ¦
Build & Cache Techniques
π¦
Git Custom Checkout & Fetch
Slide 51
Slide 51 text
Fast & Reliable
Laterβ¦
CI Pipeline Design
The Journey to Performant Android CI
Git Custom Checkout & Fetch
Build & Cache Techniques
π¦
Slide 52
Slide 52 text
π¦
The Journey to Performant Android CI
Build & Cache Techniques
Slide 53
Slide 53 text
Build & Cache Techniques
π¦
Slide 54
Slide 54 text
JVM Memory Sizing
Heap Non-Heap
Slide 55
Slide 55 text
JVM Memory Sizing
Heap Non-Heap
Metaspace
CodeCache
Young & Old Gen
CompressedClassPointers
GC Buffers
Slide 56
Slide 56 text
JVM Memory Sizing
Heap Non-Heap
Metaspace
CodeCache
Young & Old Gen
CompressedClassPointers
GC Buffers
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
SoftRefLRUPolicyMSPerMB
JVM Memory Sizing
Slide 76
Slide 76 text
JVM Memory Sizing
Slide 77
Slide 77 text
JVM Memory Sizing
Coming Soon: Tool for Sizing
Slide 78
Slide 78 text
tcmalloc
malloc replacements
jemalloc
Freeing up as much memory as
possible.
Optimize for speed while keeping
memory usage steady.
Pending evaluationβ¦
Slide 79
Slide 79 text
Android Lint Best Practices
π
Slide 80
Slide 80 text
Android Lint Best Practices
π
https://googlesamples.github.io/android-custom-lint-rules/
β ignoreTestSources
β checkAllWarnings
β checkDependencies
Do the following:
β’ Reduce the number of inputs per task and
make them more stable
β’ Gradle build scans to observe performance
Gradle Build Cache
Slide 89
Slide 89 text
Gradle Build Cache
Slide 90
Slide 90 text
Gradle Configuration Cache on CI
Slide 91
Slide 91 text
2-3 min possible savings per job
Gradle Configuration Cache on CI
Slide 92
Slide 92 text
Relies on caching outputs of configuration phase,
which rely on all inputs used in the build.
So we need to:
1. Find all inputs
2. Hash them
3. Search cache provider
Gradle Configuration Cache on CI
Gradle Configuration Cache on CI
Reusing configuration cache.
Slide 97
Slide 97 text
Gradle Configuration Cache on CI
π
Slide 98
Slide 98 text
β .gradle git:(main) β du -sh 8.11.1
7.4M 8.11.1
β .gradle git:(main) β du -sh configuration-cache
1.7M configuration-cache
Gradle Configuration Cache on CI
Slide 99
Slide 99 text
β 8.11.1 du -sh transforms
1.1G transforms
β 8.11.1 du -sh generated-gradle-jars
177M generated-gradle-jars
β 8.11.1 du -sh kotlin-dsl
37M kotlin-dsl
β 8.11.1 du -sh dependencies-accessors
12M dependencies-accessors
Gradle Configuration Cache on CI
Slide 100
Slide 100 text
10
8
6
4
2
0
seconds
tar gzip pigz zstd lz4
Compression Options - against 1 GB
π
Slide 101
Slide 101 text
10
8
6
4
2
0
seconds
tar gzip pigz zstd lz4
Compression Options - against 1 GB
π
with multiple cores
Slide 102
Slide 102 text
10
8
6
4
2
0
seconds
tar gzip pigz zstd lz4
Compression Options - against 1 GB
π
with multiple cores
Slide 103
Slide 103 text
10
8
6
4
2
0
seconds
tar gzip pigz zstd lz4
Compression Options - against 1 GB
π
with multiple cores
Slide 104
Slide 104 text
10
8
6
4
2
0
seconds
tar gzip pigz zstd lz4
Compression Options - against 1 GB
π
with multiple cores
Slide 105
Slide 105 text
zstd at its fastest speed has better compression
than gzipped tar
lz4 is lossless, which means its compression is
almost nothing
Multi-threaded didnβt make a difference in
production
Compression Options
π
Slide 106
Slide 106 text
AWS S3 + ZSTD
# find sources via ripgrep
# dry run
# create zstd archives
# full run
$ upload zstd archives via AWS S3
Slide 107
Slide 107 text
Gradle Configuration Cache on CI
Slide 108
Slide 108 text
Gradle Configuration Cache on CI
Oops
Slide 109
Slide 109 text
Gradle Caches on CI
π€
Config Cache
Dependencies
Script Cache
Build Cache
Slide 110
Slide 110 text
Gradle Caches on CI
Config Cache
Dependencies
Script Cache
Build Cache
π‘
Task History
Slide 111
Slide 111 text
Gradle Caches on CI
Config Cache
Dependencies
Script Cache
Build Cache
π‘
Task History
Slide 112
Slide 112 text
Gradle User Home in Docker
COPY . /prebuild
Slide 113
Slide 113 text
Gradle User Home in Docker
Custom git checkout
Supporting Pipeline
Layered images
Track size & drift
Layered images
Building Real Estate Debug APK
Previously 30 minutes
Down to 2 minutes on complete cache hit
Slide 133
Slide 133 text
π§ͺ
Layered images
Android Unit Tests
Previously 50 minutes
Down to 4 minutes on complete cache hit
Slide 134
Slide 134 text
CI Pipeline Design
Slide 135
Slide 135 text
Automate building, publishing, using Docker images
Flatten to reduce negative space and parallelize work
Use downstream pipelines to organize and declutter
CI Pipeline Design
Slide 136
Slide 136 text
CI Pipeline Design: Iterations
Slide 137
Slide 137 text
CI Pipeline Design: Iterations
Slide 138
Slide 138 text
CI Pipeline Design: Iterations
Slide 139
Slide 139 text
CI Pipeline Design: Critical Checks
Group checks that always complete in 60 seconds or less.
Fail entire pipeline if critical check fails, but otherwise let
pipelines continue.
Slide 140
Slide 140 text
CI Pipeline Design: Critical Checks
Slide 141
Slide 141 text
CI Pipeline Design: Critical Checks
Slide 142
Slide 142 text
CI Pipeline Design: Team Jobs
Dynamically run team specific work.
Make it easy to keep author-team relationship up to date.
Slide 143
Slide 143 text
CI Pipeline Design: Team Jobs
Slide 144
Slide 144 text
CI Pipeline Design: Today
Slide 145
Slide 145 text
CI Pipeline Design: Today
Slide 146
Slide 146 text
CI Pipeline Design: Today
Slide 147
Slide 147 text
CI Pipeline Design: Today
Slide 148
Slide 148 text
CI Pipeline Design: Today
Slide 149
Slide 149 text
CI Pipeline Design: Downstream
Included Build Gradle Code Analysis Unit Tests