Tuning Android build nodes for maximum throughput
Article Summary
Wealthfront's Android team cut their CI build times by rethinking how Gradle uses resources on AWS EC2 instances. Turns out, more workers doesn't always mean faster builds.
The Wealthfront engineering team shares their deep dive into optimizing Gradle performance on m7i.8xlarge EC2 instances (32 cores, 128GB RAM). They methodically tuned everything from daemon configuration to worker counts to squeeze maximum throughput from their Android CI pipeline.
Key Takeaways
- Reducing from 8 to 4 Gradle workers improved build times despite having 32 CPU cores
- Single-use daemons beat long-running ones for CI independence and memory efficiency
- Worker formula: max of 4 or CPU cores divided by 2 prevents memory issues
- Memory math matters: workers × parallel forks × heap size must fit available RAM
- Android Lint alone requires 10GB heap, constraining other optimization choices
Halving Gradle workers from the default CPU count improved build performance by avoiding memory bottlenecks, proving that resource tuning requires testing over assumptions.
About This Article
Wealthfront's Android team had trouble with memory overhead and unpredictable performance from Gradle daemon processes running on their CI infrastructure. Since builds happen hours apart, they never got the benefit of a warm cache.
They switched to single-use daemons that start fresh for each build and shut down when done. This eliminated the persistent memory overhead and kept each CI build independent from what came before.
Memory consumption on their m7i.8xlarge instances went down while build reliability stayed solid. They could now confidently use the remaining 128GB of RAM across Gradle workers, test heap sizes, and Jenkins executors without daemon-related memory leaks piling up over time.