Este guia descreve como usar o Android Dynamic Performance Framework (ADPF) para otimizar jogos com base nos recursos dinâmicos de gerenciamento de temperatura, CPU e GPU no Android. Os jogos são o foco, mas você também pode usar os recursos para outros apps que exigem alta performance.
O ADPF é um conjunto de APIs que permitem que jogos e apps de alta performance interajam mais diretamente com os sistemas térmicos e de energia de dispositivos Android. Com essas APIs, você pode monitorar o comportamento dinâmico nos sistemas Android e otimizar a performance de jogos em um nível sustentável que não superaqueça os dispositivos.
Os SoCs para dispositivos móveis e o Android têm comportamentos mais dinâmicos de performance do que computadores e consoles. Esses comportamentos incluem gerenciamento de estado térmico, relógios variados de CPU e GPU e tipos de núcleo de CPU variados. Isso, combinado à topologia de núcleo cada vez mais diversificada dos SoCs, gera desafios ao tentar garantir que o jogo possa aproveitar esse comportamento sem afetar negativamente a performance do dispositivo. O ADPF fornece algumas dessas informações para deixar a performance mais previsível.
Estes são os principais recursos do ADPF:
Monitoramento do estado térmico: monitora o estado térmico de um dispositivo e ajusta a performance proativamente antes que ele fique insustentável.
Dicas de performance da CPU: dá dicas de performance para que o Android escolha os relógios e tipos de núcleo de CPU corretos em vez de deixar que o Android escolha com base nas cargas de trabalho anteriores.
Modo de performance fixa: ativa esse modo em um dispositivo durante o benchmarking para receber medições que não são alteradas pelo relógio dinâmico da CPU.
Monitoramento do estado térmico
Lançamento: Android 11 (API de nível 30)
Obrigatório em todos os dispositivos: Android 13 (API de nível 33) ou mais recente
A performance em potencial do app é limitada pelo estado térmico do dispositivo, que pode variar de acordo com características como clima, uso recente e o design térmico do aparelho. Altos níveis de performance só são mantidos pelos dispositivos por um período específico antes de serem limitados termicamente. Um objetivo importante da implementação precisa ser atingir as metas de performance sem exceder as limitações térmicas. Além disso, ao depurar problemas de performance, é importante saber quando o estado térmico de um dispositivo a limita.
Os mecanismos de jogo geralmente têm parâmetros de performance relacionados ao tempo de execução que podem ajustar o tanto de recursos do dispositivo usados pelo mecanismo. Por exemplo, esses parâmetros podem definir o número de linhas de execução de worker, afinidade entre linha de execução e worker para núcleos grandes e pequenos, opções de fidelidade de GPU e resoluções de framebuffer.
Quando um dispositivo se aproxima de um estado térmico não seguro, o jogo pode evitar a limitação, reduzindo a carga de trabalho por esses parâmetros. Para evitar a limitação, monitore o estado térmico do dispositivo e ajuste de forma proativa a carga de trabalho do mecanismo de jogo. Depois que o dispositivo superaquece, a carga de trabalho precisa ficar abaixo do nível de performance sustentável para dissipar o calor.
PowerManager
O ADPF fornece a classe
PowerManager
para monitorar o
estado térmico de um dispositivo. Estes são os principais elementos:
Se o dispositivo não estiver sob limitação térmica:
Alguma limitação, mas sem afetar muito a performance:
Limitação significativa que afeta a performance:
Vinculação nativa para a API Thermal (NDK):
Para monitorar o estado térmico do dispositivo, pesquise o
método
getThermalHeadroom
. Ele determina por quanto tempo o dispositivo pode manter o nível de
performance atual sem superaquecimento. Se o tempo for menor que a quantidade
necessária para executar a carga de trabalho, o jogo vai precisar diminuir essa carga a um
nível sustentável. Por exemplo, o jogo pode mudar para núcleos menores, reduzir o
frame rate ou diminuir a fidelidade.
Dicas de performance da CPU
Lançamento: Android 12 (API de nível 31)
Obrigatório em todos os dispositivos: ainda não é obrigatório
Com as dicas de performance da CPU, um jogo pode influenciar o comportamento dinâmico da performance da CPU sem superaquecer o dispositivo e desperdiçar energia. Na maioria dos dispositivos, o Android ajusta dinamicamente a velocidade do relógio e o tipo de núcleo da CPU de uma carga de trabalho com base nas demandas anteriores. Se a carga usar mais recursos da CPU, a velocidade do relógio vai aumentar e a carga de trabalho será movida para um núcleo maior. Se a carga usar menos recursos, o Android vai diminuir a alocação deles.
Velocidade do relógio
Quando os dispositivos Android ajustam dinamicamente a velocidade do relógio da CPU, a frequência pode mudar o impacto na performance do relógio. É importante projetar um código que aborde a velocidade dinâmica do relógio para maximizar a performance, manter um estado térmico seguro e usar a energia de forma eficiente. Você pode reduzir a instabilidade temporariamente e aumentar a capacidade de resposta executando seu jogo em velocidades de relógio máximas, mas isso consome energia e acaba levando à limitação térmica dos relógios. Quando os relógios de CPU ou GPU são limitados, eles têm performance abaixo do nível sustentável.
Não é possível atribuir frequências de CPU diretamente no código do app. Como resultado, uma maneira comum de os apps tentarem ser executados em velocidades mais altas do relógio da CPU é com um loop ocupado em uma linha de execução em segundo plano. Assim, a carga de trabalho parece mais exigente. Isso desperdiça energia e aumenta a carga térmica no dispositivo quando o app não está usando os recursos extras.
Tipos de núcleo
Os tipos de núcleo da CPU em que seu jogo é executado são outro fator de performance importante. Os dispositivos Android geralmente mudam o núcleo da CPU atribuído a uma linha de execução de forma dinâmica com base no comportamento recente da carga de trabalho. A atribuição de núcleo da CPU é ainda mais complexa em SoCs com vários tipos de núcleo. Em alguns desses dispositivos, os núcleos maiores só podem ser usados de forma breve, porque atingem rapidamente um estado térmico insustentável.
Seu jogo não deve tentar definir a afinidade de núcleo da CPU pelos seguintes motivos:
O melhor tipo de núcleo para a carga de trabalho varia de acordo com o modelo do dispositivo.
A sustentabilidade da execução de núcleos maiores varia de acordo com o SoC e as diversas soluções térmicas fornecidas por cada modelo de dispositivo.
O impacto ambiental no estado térmico pode complicar ainda mais a escolha do núcleo. Por exemplo, o clima ou uma capa de smartphone pode mudar o estado térmico de um dispositivo.
A seleção do núcleo não acomoda novos dispositivos com recursos térmicos e de performance extras. Como resultado, os dispositivos geralmente ignoram a afinidade entre o processador e um jogo.
PeformanceHintManager
O ADPF fornece a classe
PerformanceHintManager
para que os jogos possam dar dicas de performance ao Android quanto à velocidade do relógio e
tipo de núcleo da CPU. Então, o SO pode decidir a melhor forma de usar as dicas com base no SoC e
na solução térmica do dispositivo. Se o app usa essa API com o monitoramento
de estado térmico, ele pode fornecer dicas mais fundamentadas para o SO, em vez de
usar loops ocupados e outras técnicas de programação que podem causar limitações.
Veja como um jogo usa as dicas de performance:
Cria sessões de dicas para linhas de execução importantes que se comportam de forma semelhante. Exemplo:
- As linhas de execução de renderização recebem uma sessão
- As linhas de execução de E/S recebem outra sessão
- As linhas de execução de áudio recebem uma terceira sessão
O jogo precisa fazer isso pelo menos 2ms ou, de preferência, mais de 4ms antes de uma sessão exigir mais recursos do sistema.
Estima a duração necessária para cada sessão de dica. A duração típica é equivalente a um intervalo de frames, mas o app pode usar um intervalo menor caso a carga de trabalho não varie significativamente entre frames.
Modo de performance fixa
Lançamento: Android 11 (API de nível 30)
Obrigatório em todos os dispositivos: ainda não é obrigatório
Os dispositivos Android podem mudar o relógio de forma dinâmica com base na carga do sistema. Esse comportamento é bom para economia de energia durante o uso, mas pode dificultar a coleta de dados confiáveis de performance. Se você está tentando determinar a velocidade em que um fragmento de código pode ser executado para evitar a regressão ou se uma otimização pode ser repetida, seus resultados não são confiáveis caso não tenham sido testados em velocidades fixas do relógio. Com relógios fixos, é possível realizar testes A/B precisos de performance sem que as mudanças na frequência da CPU sejam um fator.
O modo de performance fixa define relógios de CPU e GPU com limites superior e inferior. Esse modo não desativa outros comportamentos dinâmicos de performance, como a seleção de núcleo.
Você pode ativar o modo de performance fixa com o seguinte comando do adb:
adb shell cmd power set-fixed-performance-mode-enabled [true|false]
Um dispositivo em execução no modo de performance fixa ainda pode superaquecer, porque o modo não o coloca em um estado de temperatura sustentável. Por isso, recomendamos o seguinte para execuções de benchmark:
Aguarde o dispositivo retornar a um estado de temperatura sustentável antes de iniciar a execução.
Monitore o estado térmico do dispositivo durante o teste para diferenciar o impacto entre o código de benchmark e os eventos térmicos.
App de exemplo
O
app de exemplo (link em inglês)
do ADPF demonstra o uso básico da API ADPF. O exemplo mostra o status
térmico do dispositivo usando a API ADPF
getThermalHeadroom
e a API de
status térmico. O app também muda dinamicamente a carga de trabalho com base na dica da API e
na API PerformanceHintManager
para controlar a performance da linha de execução de renderização.