Reducing the build time of BlaBlaCar’s Android app

Patrick Brochado
BlaBlaCar
Published in
8 min readNov 18, 2021

How the BlaBlaCar Android team went from 13 min build time to …

Android app build can be very time-consuming and sometimes painful for developers. At BlaBlaCar, we decided to tackle this serious issue by using build analysis tools and implementing solutions to reduce the build time drastically.

“Patience has its limits. Take it too far, and it’s cowardice.” — George Jackson

Every time we make changes in the code, we need to perform a new build in order to run the application. The more changes we make or the deeper these changes are, the higher the build time is, particularly when we need to switch to another Git branch. The build time is constantly increasing as we introduce new features in the application 🏗️

The build time of our application was very long, sometimes more than 10 minutes if there were a lot of changes. It has a direct impact on team productivity.

I made a survey to gather data from the team and it shows that the average build time in the team was about 40 minutes per day. That means that the team loses 8 hours of productivity every day (40min x 12 developers = 480min).

The build time data was collected with this plugin.

Gradle is the default build tool for Android projects, this is the main lever on which we can work to reduce the build time. This tool is really powerful but also very complex to master as it offers tons of configuration options.

I will share some insights to configure it properly in order to optimize the build but before exploring solutions to improve the build time, it’s important to know how to precisely measure your build time in order to evaluate the impact of your optimizations.

So, there is the plan:
1. Let’s measure our build time
2. A list of toolboxes to decrease the build time
3. What are our key learnings?

Let’s measure our build time

There are several tools that allow you to analyze and measure your build time but also provide you with some insights to help you optimize it.

Build Scan for Gradle

Build scans provide through a web interface a record of what happened during the build process. Build scans provide detailed insights about your build, allowing you to find and address performance issues and identify where are the bottlenecks.

The timeline view provides an overview of which tasks are executed, how long they took, how well your build parallelized etc.

Timeline view of BlaBlaCar app build scan

The performance view will show you details about configuration time and other hints on how to make your build faster.

Performance view of BlaBlaCar app build scan

You can simply create a build scan by adding the option --scan to your Gradle build command. Gradle will provide you a link to access it easily.

Gradle also offers a paid service Gradle Enterprise which offers a deeper analysis of your project and the possibility of comparing your scans easily

Pros:
• Persistent and shareable
• Timeline view ⏳

Cons:
• Not able to compare builds without paying 💸

Build Analyzer

Each time you build your app with Android Studio, it generates a Build Analyzer report. This report is accessible directly in your IDE, so it’s a very convenient way to analyze the performance of your build.

The Tasks section helps you identify the most time-consuming tasks but also gives you some insights like the reason why a task is executed.

Build Analyzer Tasks

The Warnings section helps you identify bad practices and provides some tips to improve your build time.

Build Analyzer Warnings

Pros:
• Integrated into Android Studio
• Executed during each build
• Tips to optimize your build

Cons:
• No timeline

Gradle profiler

Gradle profiler is another tool provided by Gradle that allows you to create build scenarios and perform benchmarks in order to find the most optimized configuration for your build.

Example of Gradle profiler scenario

Gradle profiler offers 2 different modes:

  • Benchmarking mode: this mode executes the build several times for each scenario defined and calculates a mean time. It allows you to make before/after comparisons after applying some changes in your configuration
  • Profiling mode: this mode allows you to deep dive into the build process by collecting a large amount of data useful to identify performance issues.
Benchmark results for Java’s Garbage Collector scenario

Pros:
• Great to benchmark scenarios
• 2 complementary modes

Cons:
• Data collected are hard to read 🙈

The use of these tools allowed us to better identify weaknesses and areas for improvement and we were thus able to optimize our build by making some changes.

We defined a procedure to be able to measure build time precisely and to avoid data bias. Benchmarks were performed on a reference machine. We started with a reference time of 13 minutes.

Incremental Change vs. “Big Bang” Change

It is possible to improve the performance of the build by making quick wins, but the architecture of the app has a considerable impact on it. Indeed, an app based on a monolithic architecture will necessarily take longer to build than a modular app. Gradle offers a caching system that allows you to build only modules with changes. The cache efficiency will be limited if the app is not modularized.

At BlaBlaCar, we already decided to put effort to modularized our app but this process is very long as our codebase is massive. This kind of change has a significant cost but you can also gain a lot with measured effort.

“80% of consequences come from 20% of the causes”

Pareto principle also known as 80/20 Rule

While waiting to benefit from the advantage of modularization, we decided to focus on quick wins in order to reduce the build time as much as possible by putting less effort.

Step 1: Gradle dependencies declaration

Android Gradle Plugin 3.0 introduced api and implementation keywords in order to declare your module dependencies.

Read this excellent story for more details

Bad use of these keywords can have a negative impact on the build time. You should optimize your classpath by putting only artifacts that really need to be on the compile classpath (api) and putting all the others go on the runtime classpath (implementation). By doing this, you’ll benefit from faster compilation due to a cleaner classpath and less recompilation as we don’t need to recompile artifacts on the runtime classpath.

This optimization allowed us to reduce the build time by 30 seconds, it is not so much but it is already a good start.

Step 2: Upgrade dependencies version

Most of Gradle, Android Gradle plugin, and other Android tools updates come with build optimizations and new features. To take advantage of the latest optimizations, keeping dependencies up to date is a necessary step.

The most recent versions of the popular dependencies based on annotation processors such as Dagger or Room include the incremental annotation processing support which offers a significant performance gain (more details here).

“Incremental annotation processing significantly increases the effectiveness of incremental compilation when annotation processors are present”

Gradle 5.0 release note

This optimization allowed us to reduce the build time by 2 minutes, its impact is very significant.

Step 3: Gradle daemon 😈

The Gradle daemon is a long-lived process that caches information about project structure, files, tasks, and more in memory. It improves build speed by reusing computations from previous builds.

If you use both Android Studio and the command line to build your app, Gradle may not be able to reuse the daemon and restart it. If it does so, you’ll lose the benefit to use it. In order to use the same Gradle daemon on both Android Studio and terminal, you must perform the following checks:

  1. Check JAVA_HOME is correctly set in your terminal
λ echo $JAVA_HOME
C:\Users\PatrickBrochado\workspace\tools\java\jdk8

2. Use the same folder in Android Studio > Module settings > SDK Location > JDK Location

Step 4: Gradle configuration cache and file-system watching

Gradle recently introduced 2 features that optimize build time:

  • File system watching 👀: By activating this feature, the Gradle daemon will be notified by the OS when there are modified files, preventing unnecessary disk I/O during the build
  • Configuration cache: This feature caches the result of the configuration phase and reuses it for subsequent builds. The configuration phase can be skipped entirely if nothing that affects the build configuration, such as build scripts, has changed.

The combination of these two options allowed us to reduce our build time by 1 minute 30 seconds.

Step 5: Antivirus optimization

Google provides some recommendations in order to reduce the impact of antivirus on build time by using a whitelisted folder. At BlaBlaCar, the antivirus got a huge impact on the build time as all created or modified were scanned by the antivirus 🦠

The application of these recommendations allowed us to reduce our build time by 5 minutes, so this step should not to be neglected.

(Bonus step) Upgrade the hardware 🎁

As you may know, the performance of computer has a direct impact on the build time. For example, we had fairly heterogeneous computers within our team and build times were twice as long on the less powerful computers.

You should consider cleaning up your computer or upgrading it if it’s too old. Choose machines with a maximum of cores to take advantage of parallelization and with a lot of RAM in order to be able to increase the size of the Gradle cache 🚀

Please consider refurbished retailer when acquiring a new computer to reduce your carbon footprint when acquiring new material ♻️

Also, make sure your computer doesn’t overheat, it could switch to security mode and thus reduce its performance 🔥

These optimizations allowed us to reduce our build time to about 4 minutes, or approximately… 70% less than before 🎉

What’s next?

We succeeded in reducing our pain due to the build time but we still maintain our goal to migrate our app to a fully modularized architecture. This will be a huge benefit for our build time but it will also allow us to unlock dynamic feature delivery, but that’s another story 📚✨

--

--