Rendimiento de Jetpack Compose

Jetpack Compose tiene como objetivo ofrecer un rendimiento excelente de uso inmediato. En esta página, se muestra cómo escribir y configurar tu app para obtener un mejor rendimiento, y se muestran algunos patrones que debes evitar.

Te recomendamos que primero te familiarices con los conceptos básicos de Compose en Acerca de Compose.

Configura tu app de forma correcta

Si el rendimiento de tu app es deficiente, es posible que haya un problema de configuración. Un buen primer paso es verificar las siguientes opciones de configuración.

Compila en el modo de lanzamiento y usa R8

Si tienes problemas de rendimiento, intenta ejecutar tu app en el modo de lanzamiento. El modo de depuración es útil para detectar muchos problemas, pero implica un costo de rendimiento significativo y puede dificultar la detección de otros problemas de código que podrían afectar el rendimiento. Te recomendamos que también habilites la optimización y reducción con el compilador R8 para garantizar una compilación de lanzamiento eficiente y de buen rendimiento.

Usa un perfil de Baseline

Los perfiles de Baseline mejoran la velocidad de ejecución del código en aproximadamente un 30% desde el primer lanzamiento, ya que evitan la interpretación y los pasos de compilación justo a tiempo (JIT) para las instrucciones de código incluidas. Cuando se envía un perfil de Baseline a una app o biblioteca, Android Runtime (ART) puede optimizar las instrucciones de código incluidas a través de la compilación anticipada (AOT), lo que brinda mejoras de rendimiento para cada instalación nueva de la app y con cada actualización de la app. Esta optimización guiada por perfil (PGO) permite que las apps optimicen el inicio, reduzcan los bloqueos de interacción y mejoren el rendimiento general del entorno de ejecución para los usuarios finales desde el primer lanzamiento.

Compose se distribuye como biblioteca, en lugar de formar parte de la plataforma de Android. Este enfoque permite que el equipo de Compose actualice Compose con frecuencia y admita versiones anteriores de Android. Sin embargo, distribuir Compose como biblioteca implica un costo. El código de la plataforma de Android ya está compilado e instalado en el dispositivo. Sin embargo, las bibliotecas deben cargarse cuando se inicia la app y se deben interpretar JIT cuando se necesita la funcionalidad. Esto puede ralentizar la app durante el inicio y cuando usa una función de la biblioteca por primera vez.

Puedes mejorar el rendimiento mediante la definición de perfiles de Baseline. Estos perfiles definen las clases y los métodos necesarios en los recorridos críticos del usuario y se distribuyen con el APK o el AAB de tu app. Durante la instalación de la app, ART compila este código crítico AOT para que esté listo para usarse cuando se inicie la app.

No siempre es sencillo definir un buen perfil de Baseline y, por lo tanto, Compose se envía con uno de forma predeterminada. Es posible que no tengas que hacer nada para ver este beneficio. Sin embargo, el perfil de Baseline que se incluye con Compose solo contiene optimizaciones para el código dentro de la biblioteca de Compose. Para obtener la mejor optimización, es mejor crear un perfil de Baseline para tu app que use Macrobenchmark para cubrir los recorridos críticos del usuario. Cuando defines tu propio perfil, debes probarlo para verificar que te ayude. Una buena forma de hacerlo es escribir pruebas de Macrobenchmark para tu app y verificar los resultados mientras escribes y revisas tu perfil de Baseline. Si deseas ver un ejemplo de cómo escribir pruebas de macrocomparativas para tu IU de Compose, consulta este ejemplo de Compose.

Para obtener un desglose detallado de los efectos del modo de lanzamiento, R8 y los perfiles de Baseline, consulta la entrada de blog ¿Por qué siempre deberías probar el rendimiento de Compose durante el lanzamiento?

Cómo afectan al rendimiento las tres fases de Compose

Como se explica en Fases de Jetpack Compose, cuando Compose actualiza un fotograma, atraviesa por tres fases:

  • Composición: Compose determina qué mostrar. Ejecuta funciones de componibilidad y compila el árbol de IU.
  • Diseño: Compose determina el tamaño y la posición de cada elemento en el árbol de IU.
  • Dibujo: En realidad, Compose renderiza los elementos individuales de la IU.

Compose puede omitir de manera inteligente cualquiera de esas fases si no es necesaria. Por ejemplo, supongamos que un solo elemento gráfico cambia entre dos íconos del mismo tamaño. Como este elemento no cambia de tamaño y no se agregan ni quitan elementos del árbol de IU, Compose puede omitir las fases de composición y diseño, y volver a dibujar este elemento.

Sin embargo, algunos errores de codificación pueden dificultar que Compose sepa las fases que puede omitir con seguridad. Si tienes dudas, Compose ejecuta las tres fases, lo que puede ralentizar tu IU. Por lo tanto, muchas de las prácticas recomendadas de rendimiento son para ayudar a Compose a omitir las fases que no necesita.

Se deben seguir algunos principios generales que pueden mejorar el rendimiento en general:

  • Siempre que sea posible, quita los cálculos de las funciones de componibilidad. Es posible que debas volver a ejecutar las funciones de componibilidad cada vez que cambie la IU. Cualquier código que coloques en el elemento componible se volverá a ejecutar, posiblemente para cada fotograma de una animación. Limita el código del elemento componible solo a lo que necesita para compilar la IU.

  • Aplaza las lecturas de estado el mayor tiempo posible. Si mueves la lectura de estado a un elemento secundario componible o a una fase posterior, puedes minimizar la recomposición, o bien omitir la fase de composición por completo. Para ello, puedes pasar las funciones lambda en lugar del valor de estado para el estado que cambia con frecuencia y optar por modificadores basados en lambda cuando pases un estado que cambia con frecuencia. Puedes ver un ejemplo de esta técnica en la sección Aplaza las lecturas el mayor tiempo posible.