Hoy vamos a contaros cómo hemos conseguido bajar los tiempos de compilación de nuestra aplicación Android en un 60%. Nuestros tiempos de compilación no paraban de crecer hasta el punto de que una build limpia nos llegaba a tardar unos cinco minutos.
La aplicación Android de idealista tiene bastantes años, es un proyecto antiguo y bastante grande. Es un proyecto de más de 400.000 líneas de código repartidas en cuatro módulos y mezcla de código Java y Kotlin. Además, tenemos muchas dependencias de librerías de terceros lo que añade aún más complejidad en el proceso de compilación.
Así que nos pusimos manos a la obra para intentar reducir esos tiempos de compilación tan aburridos y poder trabajar más :D. Para ello seguimos los consejos expuestos en la charla Speeding up your Android Gradle builds. Esto es lo que hemos aprendido (y algún que otro consejo extra).
El primer paso para entender por qué suben los tiempos de compilación es ver qué tareas se están ejecutando, en qué orden y el tiempo que tarda cada una. En gradle se puede añadir el parámetro ‘-profile’ a las builds, el cual genera un html en el que se puede ver qué tareas se ejecutan y cuánto tardan. Es muy útil para saber dónde se está yendo el tiempo y buscar soluciones.
Sin más, vamos a enumerar los pasos para mejorar los tiempos de nuestras builds.
- Actualizar la versión del Android Gradle plugin a la versión 3.0.1 o posterior. Si vienes de una versión 2.3.3 o anterior, este cambio es bastante grande y requiere tiempo; ya que es un cambio de major version. Google ha actualizado la forma de declarar las dependencias y, una buena gestión de éstas, hace que el tiempo de compilación baje considerablemente. Es necesario seguir la guía de Google –Migrate to Android Plugin for Gradle 3.0.0– y, para entender las nuevas posibilidades de declarar dependencias, el siguiente post:
Implementation Vs Api in Android Gradle plugin 3.0. - Crear un nuevo flavor que usaremos mientras estemos desarrollando. En el mismo incorporaremos los cambios necesarios para mejorar los tiempos de compilación.
Nosotros vamos a llamar a nuestro flavor fast, en un alarde de originalidad :) - Subir el minSdkVersion hasta la versión 21 o posterior. Una de las tareas que más tiempo consumen es multidex. Ojo: si el minSdkVersion es menor a 21, fuerza a usar una versión legacy de multidex. Por ello, es importante subir esta versión hasta la 21 para poder favorecernos del nuevo y más rápido Multidex. No es necesario subirlo para toda la aplicación, porque para eso hemos creado el nuevo flavor.

- Eliminar la generación multiapk. Esta opción es necesaria para el APK que subimos al PlayStore. Así nuestros usuarios reciben un APK de menos tamaño, ya que se generan varios dependiendo de su ABI o la densidad de pantalla de su dispositivo. Sin embargo, la generación de estos APK’s supone tiempo y no son necesarios. La forma de evitarlo es añadir este código en el apartado android del build.gradle:

Como veis, es necesario añadir el párametro ‘fast’ cuando compilamos. Desde línea de comandos sería ‘./gradlew assembleFastDebug -Pfast’, pero también se puede añadir a Android Studio para que lo añada en cada build.
- Añadir recursos de un único lenguaje y densidad de pantalla. Para desarrollar no es necesario que el APK incluya todos los lenguajes y todos los recursos. En nuestro nuevo flavor podemos especificar qué lenguaje y qué tipo de recursos queremos incluir.

- Deshabilitar ‘crunch’ de las imágenes del proyecto. Esta opción hace que el tamaño del APK sea menor optimizando las imágenes. Sin embargo, de nuevo para el desarrollo no nos importa el tamaño del APK y si el tiempo que debemos esperar a que termine de procesar las imágenes.

- Evitar que Fabric actualice su ‘buildId’ en cada build. Este ‘buildId’ se añade al Manifest de la aplicación, lo que provoca una actualización en cada build y por tanto que se recompile todo el módulo de nuevo aunque no se haya cambiado nada.

- Activar la caché y la ejecución de tareas en paralelo en el fichero gradle.properties.

- Deshabilitar el plugin de firebase-performance. Este plugin lo utilizamos para saber cómo es el rendimiento de algunos métodos en clases que pensamos que son el core de la aplicación. Es interesante para ver si tras un refactor, el tiempo que tarda dicho método ha mejorado, o la hemos liado y tarda mucho más :D. Durante la compilación, este plugin busca en cada uno de los ficheros donde hay anotaciones para posteriormente añadir código que le permita medir el tiempo que se tarda en ejecutar dicho método. Por tanto, abrir cada uno de los ficheros -y si encuentra dichas anotaciones añadir código-, son tareas muy pesadas que hacen subir mucho los tiempos de compilación. Para el desarrollo no es necesario, y deshabilitarlo nos hace ganar tiempo.

Show me the results!
Los tiempos antes de estos cambios, eran:
- Build limpia: 4 minutos y 35 segundos
- Compilación tras un cambio: 1 minuto y 20 segundos
Ahora los tiempos que tenemos tras los cambios son:
- Build limpia: 3 minutos y 30 segundos
- Compilación tras un cambio: ~30 segundos

Por tanto, tras los cambios hemos llegado a obtener una mejora de casi el 60% en las builds consecutivas que son las que solemos realizar más a menudo.








Hola! He tenido algún problema con añadir un minSdkVersion exclusivamente al flavor porque gradle no me lo reconocía, asi que he solucionado el tema añadiendo esto a defaultConfig:
defaultConfig {
if (gradle.startParameter.taskNames.contains(‘fast’)) {
minSdkVersion 21
}else{
minSdkVersion 16
}
}
Por si a alguien le sirve.