Optimiza el rendimiento térmico y de CPU con el framework de rendimiento dinámico de Android

En esta guía, se describe cómo usar el framework de rendimiento dinámico de Android (ADPF) para optimizar juegos según las funciones dinámicas de administración térmica, de CPU y de GPU en Android. Aunque el enfoque es en los juegos, también puedes usar las funciones para otras apps de alto rendimiento.

ADPF es un conjunto de APIs que permiten que los juegos y las apps de alto rendimiento interactúen de forma más directa con los sistemas térmicos y de alimentación de los dispositivos Android. Con estas APIs, puedes supervisar el comportamiento dinámico en sistemas Android y optimizar el rendimiento del juego en un nivel sostenible que no sobrecaliente los dispositivos.

Los SoCs y Android de dispositivos móviles tienen comportamientos de rendimiento más dinámicos que las computadoras de escritorio y las consolas. Estos comportamientos incluyen la administración del estado térmico, relojes de CPU y GPU variables y tipos de núcleos de CPU variables. Esto, combinado con la topología cada vez más diversa de los SoCs, genera desafíos cuando se intenta asegurar de que el juego pueda aprovechar este comportamiento sin afectar negativamente el rendimiento del dispositivo. ADPF proporciona parte de esta información para que el rendimiento sea más predecible.

Estas son las funciones principales de ADPF:

  • Supervisión del estado térmico: Supervisa el estado térmico de un dispositivo y, luego, ajusta de forma proactiva el rendimiento antes de que sea insostenible.

  • Sugerencias de rendimiento de CPU: Proporciona sugerencias de rendimiento que le permiten a Android elegir los tipos de núcleos y relojes de CPU correctos en lugar de que Android elija según las cargas de trabajo anteriores.

  • Modo de rendimiento fijo: Habilita el modo de rendimiento fijo en un dispositivo durante las comparativas para obtener mediciones que no se ven afectadas por la sincronización dinámica de la CPU.

Supervisión del estado térmico

Versión: Android 11 (nivel de API 30)
Obligatoria en todos los dispositivos: Android 13 (nivel de API 33) o versiones posteriores

El rendimiento potencial de tu app está limitado por el estado térmico del dispositivo, que puede variar según las características, como el clima, el uso reciente y el diseño térmico del dispositivo. Los dispositivos solo pueden mantener niveles altos de rendimiento durante un tiempo limitado antes de que se los limite térmicamente. Un objetivo clave de la implementación debe ser alcanzar los objetivos de rendimiento sin exceder las limitaciones térmicas. Además, cuando depuras problemas de rendimiento, es importante saber cuándo el estado térmico de un dispositivo limita el rendimiento.

Por lo general, los motores de juegos tienen parámetros de rendimiento del entorno de ejecución que pueden ajustar la carga de trabajo que el motor coloca en el dispositivo. Por ejemplo, estos parámetros pueden establecer la cantidad de subprocesos de trabajo, afinidad de subprocesos de trabajo para núcleos grandes y pequeños, opciones de fidelidad de GPU y resoluciones de búfer de fotogramas.

Cuando un dispositivo se acerca a un estado térmico inseguro, el juego puede evitar ser limitado al disminuir la carga de trabajo a través de estos parámetros. Para evitar la limitación, se debe supervisar el estado térmico del dispositivo y ajustar la carga de trabajo del motor de juego de forma proactiva. Una vez que el dispositivo se sobrecalienta, la carga de trabajo debe caer por debajo del nivel de rendimiento sostenible para disipar el calor.

PowerManager

ADPF proporciona la clase PowerManager para supervisar el estado térmico de un dispositivo. Estos son los elementos principales:

Puedes supervisar el estado térmico del dispositivo mediante un sondeo del método getThermalHeadroom. Este método determina cuánto tiempo el dispositivo puede mantener el nivel de rendimiento actual sin sobrecalentarse. Si el tiempo es menor que la cantidad necesaria para ejecutar la carga de trabajo, el juego debe disminuirla a un nivel sostenible. Por ejemplo, el juego puede cambiar a núcleos más pequeños, reducir la velocidad de fotogramas o reducir la fidelidad.

Sugerencias de rendimiento de CPU

Versión: Android 12 (nivel de API 31)
Obligatorio en todos los dispositivos: Aún no es obligatorio

Con las sugerencias de rendimiento de CPU, un juego puede influir en el comportamiento dinámico del rendimiento de la CPU sin sobrecalentar el dispositivo ni desperdiciar energía. En la mayoría de los dispositivos, Android ajusta de forma dinámica la velocidad del reloj de la CPU y el tipo de núcleo para una carga de trabajo según las demandas anteriores. Si una carga de trabajo usa más recursos de CPU, la velocidad del reloj aumenta y la carga de trabajo se traslada a un núcleo más grande. Si la carga de trabajo usa menos recursos, Android reduce la asignación de recursos.

Velocidad de reloj

Cuando los dispositivos Android ajustan dinámicamente la velocidad del reloj de la CPU, la frecuencia puede cambiar el impacto en el rendimiento del código. Diseñar un código que aborde las velocidades dinámicas del reloj es importante para maximizar el rendimiento, mantener un estado térmico seguro y usar la energía de manera eficiente. Puedes reducir los bloqueos temporalmente y aumentar la capacidad de respuesta al ejecutar el juego en las velocidades de reloj máximas, pero hacer esto agota la energía y, finalmente, conduce a la regulación térmica de los relojes. Cuando se limita la CPU o la GPU, su rendimiento es inferior al nivel sostenible.

No se puede asignar frecuencias de CPU directamente en el código de la app. Como resultado, una forma común para que las apps intenten ejecutarse a velocidades de reloj de CPU más altas es ejecutar un bucle ocupado en un subproceso en segundo plano a fin de que la carga de trabajo parezca más exigente. Esto desperdicia energía y aumenta la carga térmica del dispositivo cuando la app no usa los recursos adicionales.

Tipos principales

Los tipos de núcleo de CPU en los que se ejecuta el juego son otro factor de rendimiento importante. Los dispositivos Android suelen cambiar el núcleo de CPU asignado a un subproceso de forma dinámica según el comportamiento reciente de la carga de trabajo. La asignación de núcleo de CPU es aún más compleja en SoCs con varios tipos de núcleo. En algunos de estos dispositivos, los núcleos más grandes solo se pueden usar brevemente sin pasar a un estado térmico insostenible.

El juego no debería intentar establecer la afinidad de núcleo de CPU por los siguientes motivos:

  • El mejor tipo de núcleo para una carga de trabajo varía según el modelo de dispositivo.

  • La sostenibilidad de ejecutar núcleos más grandes varía según el SoC y las diversas soluciones térmicas proporcionadas por cada modelo de dispositivo.

  • El impacto ambiental en el estado térmico puede complicar aún más la elección principal. Por ejemplo, el clima o una funda de teléfono pueden cambiar el estado térmico de un dispositivo.

  • La selección de núcleo no admite dispositivos nuevos con rendimiento y capacidades térmicas adicionales. Como resultado, los dispositivos a menudo ignoran la afinidad de procesador de un juego.

PeformanceHintManager

ADPF proporciona la clase PerformanceHintManager a fin de que los juegos puedan hacer sugerencias de rendimiento a Android sobre la velocidad del reloj de la CPU y el tipo de núcleo. Luego, el SO puede decidir la mejor manera de usar las sugerencias basadas en el SoC y la solución térmica del dispositivo. Si la app usa esta API junto con la supervisión de estado térmico, se puede proporcionar sugerencias más fundamentadas al SO en lugar de usar bucles ocupados y otras técnicas de codificación que puedan causar limitaciones.

Así es como un juego usa sugerencias de rendimiento:

  1. Crea sesiones de sugerencias para subprocesos clave que se comporten de manera similar. Por ejemplo:

    • Los subprocesos de renderización obtienen una sesión
    • Los subprocesos de IO obtienen otra sesión
    • Los subprocesos de audio obtienen una tercera sesion

    El juego debe hacer esto con tiempo, al menos 2 ms y preferentemente más de 4 ms antes de que una sesión necesite aumentar los recursos del sistema.

  2. En cada sesión de sugerencias, se predice la duración necesaria para que cada sesión se ejecute. La duración típica es equivalente a un intervalo de fotogramas, pero la app puede usar un intervalo más corto si la carga de trabajo no varía significativamente entre los marcos.

Modo de rendimiento fijo

Versión: Android 11 (nivel de API 30)
Obligatorio en todos los dispositivos: Aún no es obligatorio

Los dispositivos Android pueden cambiar el reloj de forma dinámica según la carga del sistema. Este comportamiento es bueno para el ahorro de energía durante el uso, pero puede dificultar la obtención de datos de rendimiento confiables. Si intentas determinar qué tan rápido se puede ejecutar un fragmento de código para prevenir la regresión o si una optimización es repetible, tus resultados no serán confiables si no se prueban a velocidades de reloj fijas. Con los relojes fijos, puedes realizar pruebas A/B del rendimiento con precisión, sin que la frecuencia de la CPU sea un factor.

El modo de rendimiento fijo establece los relojes de la CPU y la GPU en un límite inferior y superior. Este modo no inhabilita otros comportamientos de rendimiento dinámicos, como la selección de núcleos.

Puedes habilitar el modo de rendimiento fijo con el siguiente comando adb:

adb shell cmd power set-fixed-performance-mode-enabled [true|false]

Un dispositivo que se ejecuta en modo de rendimiento fijo aún puede sobrecalentarse porque el modo no coloca al dispositivo en un estado térmico sostenible. Por este motivo, recomendamos lo siguiente para las ejecuciones de comparativas:

  • Espera a que el dispositivo vuelva a un estado térmico sostenible antes de comenzar la ejecución.

  • Supervisa el estado térmico del dispositivo durante las pruebas para diferenciar el impacto entre el código de comparativas y los eventos térmicos.

App de ejemplo

La app de ejemplo de ADPF demuestra el uso básico de la API de ADPF. En la muestra, se muestra el estado térmico del dispositivo mediante la API de getThermalHeadroom de ADPF y la API de estado térmico. La app también cambia la carga de trabajo de forma dinámica según la sugerencia de la API y la API de PerformanceHintManager para controlar el rendimiento del subproceso de renderización.