Commit 28a08fe
authored
chore(infra): optimize Android E2E build for lg runner (16 vCPUs, 48GB) (MetaMask#23869)
## **Description**
This PR optimizes Android E2E builds to prevent "Gradle Daemon
disappeared unexpectedly" crashes on the LG runner (16 vCPUs, 48GB RAM).
### Root Cause Analysis
The "Daemon disappeared" symptom is consistent with **process
termination under memory pressure** (e.g., OS OOM kill). On **lg
(48GB)**, the previous GitHub Actions Gradle config (`-Xmx16g`,
`workers.max=6`, `daemon=true`) could overlap with Node/Metro memory
usage and native compilation spikes.
### Solution: Optimized Gradle Memory Settings
Following [Gradle 8.10.2 Performance Best
Practices](https://docs.gradle.org/8.10.2/userguide/performance.html),
we tuned `gradle.properties.github` for the 48GB runner.
#### Improved Gradle Logging for E2E
- E2E builds now run Gradle with **`--stacktrace --info`** via
`scripts/build.sh` to provide more actionable logs when the build fails.
- Android CI uses **JDK 17** via `setup-e2e-env` defaults:
[setup-e2e-env
action](https://github.com/MetaMask/github-tools/blob/v1/.github/actions/setup-e2e-env/action.yml)
#### JVM Memory Changes
| Setting | Before | After | Reason |
|---------|--------|-------|--------|
| **Heap (`-Xmx`)** | 16GB | **12GB** | Leave room for Node.js/Metro |
| **Initial Heap (`-Xms`)** | (none) | **4GB** | Set JVM initial heap to
reduce early heap resizing: [Java launcher
docs](https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html)
|
| **MaxGCPauseMillis** | (none) | **500ms** | Tune G1 pause-time goal
for CI throughput: [G1 GC tuning
guide](https://docs.oracle.com/en/java/javase/17/gctuning/garbage-first-g1-garbage-collector1.html)
|
| **ExitOnOutOfMemoryError** | (none) | **enabled** | Fail fast on JVM
OOM: [Java launcher
docs](https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html)
|
| **file.encoding** | (none) | **UTF-8** | Pin JVM default charset (JDK
17 default can depend on OS/locale):
[Charset.defaultCharset()](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/nio/charset/Charset.html#defaultCharset())
|
| **OptimizeStringConcat** | enabled | **removed** | Remove non-standard
`-XX` tuning flag from baseline config (prefer defaults): [Java launcher
docs](https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html)
|
#### Gradle Settings Changes
| Setting | Before | After | Reason |
|---------|--------|-------|--------|
| **Workers** | 6 | **2** | Prevent memory contention |
| **Daemon** | true | **false** | Disable persistent daemon between CI
builds: [Gradle
Daemon](https://docs.gradle.org/8.10.2/userguide/gradle_daemon.html#sec:disabling_the_daemon)
|
| **configureondemand** | true | **removed** | Not recommended for
modern Gradle + Android builds: [Gradle performance
guide](https://docs.gradle.org/8.10.2/userguide/performance.html);
[Android/AGP
compatibility](https://stackoverflow.com/questions/49990933/configuration-on-demand-is-not-supported-by-the-current-version-of-the-android-g)
|
#### Unchanged Settings (kept as-is)
| Setting | Value | Why Kept |
|---------|-------|----------|
| `parallel` | true | [Recommended for multi-project
builds](https://docs.gradle.org/8.10.2/userguide/performance.html#parallel_execution)
|
| `caching` | true | [Recommended build cache
usage](https://docs.gradle.org/8.10.2/userguide/build_cache.html) |
| `vfs.watch` | false | Already disabled in baseline config; we keep it
disabled for CI |
| `MaxMetaspaceSize` | 1g | Kept from baseline config |
| `UseG1GC` | enabled | Kept from baseline config |
| `G1HeapRegionSize` | 16m | Kept from baseline config |
| `UseStringDeduplication` | enabled | Kept from baseline config |
### Memory Budget (48GB Runner)
> Note: rough budgeting (actual usage varies by task and input changes)
```
┌─────────────────────────────────────────────────────────┐
│ Component │ Allocation │
├─────────────────────────┼───────────────────────────────┤
│ Gradle Heap │ 12GB │
│ Gradle Metaspace │ 1GB │
│ Node.js (Metro) │ 8GB (--max-old-space-size) │
│ OS + System + native │ remainder │
└─────────────────────────┴───────────────────────────────┘
```
### Additional Optimizations
- **Skip AAB bundle for E2E** - E2E tests only use APK files.
- **Removed AAB references** from the E2E build workflow.
- **Runner moved from xl → lg** for this workflow after tuning: lg
(48GB) is sufficient.
### Documentation References
**Gradle 8.10.2:**
- [Performance
Guide](https://docs.gradle.org/8.10.2/userguide/performance.html)
- [Gradle
Daemon](https://docs.gradle.org/8.10.2/userguide/gradle_daemon.html)
- [Build
Cache](https://docs.gradle.org/8.10.2/userguide/build_cache.html)
**Java 17:**
- [Java launcher docs (heap, -X/-XX, OOM
behavior)](https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html)
-
[Charset.defaultCharset()](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/nio/charset/Charset.html#defaultCharset())
- [G1 GC tuning
guide](https://docs.oracle.com/en/java/javase/17/gctuning/garbage-first-g1-garbage-collector1.html)
### Official Runner Specs
([source](https://cirrus-runners.app/setup/#__tabbed_3_2))
| Runner | vCPUs | RAM | Disk |
|--------|-------|-----|------|
| **lg** | 16 | 48 GB | 200 GB |
| xl | 32 | 96 GB | 400 GB |
## **Changelog**
CHANGELOG entry: null
## **Related issues**
Fixes:
[INFRA-3174](https://consensyssoftware.atlassian.net/browse/INFRA-3174)
## **Manual testing steps**
```gherkin
Feature: Android E2E Build Optimization
Scenario: Build completes without daemon disappearance
Given the PR uses tuned Gradle memory settings
And Gradle runs with --stacktrace --info for E2E
When the Android E2E build workflow runs
Then the build completes without the "Daemon disappeared" failure
And APK artifacts are uploaded successfully
```
## **Screenshots/Recordings**
### **Before**
Build failing with:
```
Gradle build daemon disappeared unexpectedly (it may have been killed or may have crashed)
```
### **After**
Build results will be visible in PR checks after workflow runs.
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
[INFRA-3174]:
https://consensyssoftware.atlassian.net/browse/INFRA-3174?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ1 parent 17ef3b4 commit 28a08fe
4 files changed
Lines changed: 17 additions & 33 deletions
File tree
- .github/workflows
- android
- scripts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | 12 | | |
16 | 13 | | |
17 | 14 | | |
| |||
32 | 29 | | |
33 | 30 | | |
34 | 31 | | |
35 | | - | |
| 32 | + | |
36 | 33 | | |
37 | 34 | | |
38 | 35 | | |
39 | 36 | | |
40 | 37 | | |
41 | 38 | | |
42 | | - | |
43 | 39 | | |
44 | 40 | | |
45 | | - | |
46 | 41 | | |
47 | 42 | | |
48 | 43 | | |
| |||
88 | 83 | | |
89 | 84 | | |
90 | 85 | | |
91 | | - | |
92 | 86 | | |
93 | 87 | | |
94 | 88 | | |
95 | 89 | | |
96 | 90 | | |
97 | 91 | | |
98 | | - | |
99 | 92 | | |
100 | 93 | | |
101 | 94 | | |
| |||
110 | 103 | | |
111 | 104 | | |
112 | 105 | | |
113 | | - | |
114 | 106 | | |
115 | 107 | | |
116 | 108 | | |
| |||
241 | 233 | | |
242 | 234 | | |
243 | 235 | | |
244 | | - | |
245 | 236 | | |
246 | 237 | | |
247 | 238 | | |
| |||
264 | 255 | | |
265 | 256 | | |
266 | 257 | | |
267 | | - | |
268 | | - | |
269 | | - | |
270 | | - | |
271 | | - | |
272 | | - | |
273 | | - | |
274 | | - | |
275 | | - | |
276 | | - | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
56 | 56 | | |
57 | 57 | | |
58 | 58 | | |
59 | | - | |
60 | 59 | | |
61 | 60 | | |
62 | 61 | | |
| |||
131 | 130 | | |
132 | 131 | | |
133 | 132 | | |
134 | | - | |
135 | 133 | | |
136 | 134 | | |
137 | 135 | | |
138 | 136 | | |
139 | 137 | | |
140 | 138 | | |
141 | | - | |
142 | 139 | | |
143 | 140 | | |
144 | 141 | | |
| |||
152 | 149 | | |
153 | 150 | | |
154 | 151 | | |
155 | | - | |
156 | 152 | | |
157 | 153 | | |
158 | 154 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
5 | | - | |
6 | | - | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
10 | | - | |
11 | 11 | | |
12 | | - | |
13 | | - | |
| 12 | + | |
| 13 | + | |
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| |||
54 | 54 | | |
55 | 55 | | |
56 | 56 | | |
57 | | - | |
| 57 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
547 | 547 | | |
548 | 548 | | |
549 | 549 | | |
| 550 | + | |
| 551 | + | |
550 | 552 | | |
551 | 553 | | |
552 | 554 | | |
| |||
572 | 574 | | |
573 | 575 | | |
574 | 576 | | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
575 | 580 | | |
576 | 581 | | |
577 | 582 | | |
578 | 583 | | |
579 | 584 | | |
580 | | - | |
| 585 | + | |
581 | 586 | | |
582 | | - | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
583 | 590 | | |
584 | 591 | | |
585 | 592 | | |
| |||
0 commit comments