Taxa de quadros

QPS médio

Um frame rate estável e sem problemas é fundamental para oferecer uma experiência de jogo de alta qualidade em dispositivos Android. Ao medir a performance do jogo, você precisa medir o QPS médio como uma referência para ter uma compreensão básica da experiência. Otimize o jogo para atender ao frame rate médio de 60 QPS e garantir uma ótima experiência de jogo.

QPS P90 e P99 para estabilidade

Mesmo com uma média de 60 QPS, um jogo ainda pode apresentar problemas intermitentes, micro-travamentos e atraso de entrada imprevisível, resultando em uma experiência ruim para o jogador.

Portanto, a estabilidade do frame é tão importante quanto o rastreamento do frame rate médio. É aqui que você precisa medir as métricas de frame rate P90 e P99 como a referência consistente e o indicador de travamento, respectivamente. Essas métricas capturam a "parte final" da performance para que você otimize a suavidade da experiência do jogador.

Métricas

  • QPS médio (referência): essa métrica fundamental fornece uma referência geral da performance do jogo. Embora seja um benchmark padrão, o cálculo médio significa que quedas de frame intermitentes e micro-travamentos não podem ser detectados, o que a torna insuficiente para representar a experiência do jogador por conta própria.
  • QPS P90 (referência consistente no percentil 10): isso indica que 90% dos frames excederam essa referência consistente e apenas os 10% mais lentos demoraram mais para serem renderizados. Se o frame rate P90 for alto e próximo da média, o jogo estará funcionando bem de forma consistente para a grande maioria da sessão.
  • QPS P99 (indicador de travamento no percentil 1): isso indica que 99% dos frames excederam esse indicador de travamento, isolando especificamente o 1% mais lento dos frames. Essa métrica é essencial para detectar micro-travamentos, atrasos no carregamento de recursos e picos repentinos de renderização de recursos pesados que causam problemas visíveis.

Exemplos

Ao comparar o QPS médio com as métricas P90 e P99, você pode diagnosticar com precisão o comportamento subjacente de um jogo.

Situação 1: uma curva ideal (jogo otimizado)

  • Média: 60 QPS (16,6 ms)
  • P90: 58 QPS (17,2 ms)
  • P99: 52 QPS (19,2 ms)
  • Análise: as métricas estão bem agrupadas. O jogo parece incrivelmente suave e consistente. Não há micro-travamentos, e até mesmo o pior 1% dos frames é quase imperceptível ao olho humano.

Situação 2: gargalo de carga (vinculado à CPU/GPU)

  • Média: 45 QPS (22,2 ms)
  • P90: 40 QPS (25,0 ms)
  • P99: 38 QPS (26,3 ms)
  • Análise: o frame rate médio é menor, mas de forma consistente. O P99 não cai drasticamente em comparação com a média. Isso indica que o sistema está essencialmente sobrecarregado por configurações gráficas ou restrições de resolução. O jogo não vai parecer com renderização lenta, mas sim lento. A redução das configurações gráficas geralmente aumenta essas métricas de maneira uniforme.

Situação 3: 60 QPS instáveis (compilação de sombreador / travamentos de streaming de recursos)

  • Média: 60 QPS (16,6 ms)
  • P90: 45 QPS (22,2 ms)
  • P99: 15 QPS (66,6 ms)
  • Análise: esse é o pior cenário. Embora o frame rate médio pareça excelente, o P99 revela um problema crítico. O P99 em 66,6 ms significa que o jogo está congelando completamente por vários frames de cada vez. Isso aponta para valores atípicos graves, geralmente causados por gargalos de CPU, atrasos no streaming de recursos (por exemplo, RAM ou armazenamento lento) ou problemas causados pela compilação de sombreadores.

Avaliação

Para medir com eficácia o QPS médio, P90 e P99, use os dois métodos a seguir. O primeiro método é analisar rastros do sistema usando o Android Performance Analyzer (APA), uma ferramenta de criação de perfil de performance. O segundo método é usar o comando adb dumpsys SurfaceFlinger --timestats.

1. Medir usando o APA

Com o APA, você pode gravar um rastro do sistema e analisar com precisão os dados de frame usando consultas SQL. Siga estas etapas para medir suas métricas:

  1. Capturar o rastro com o APA: execute o jogo e use o APA para capturar um rastro do sistema durante o segmento que você quer analisar (por exemplo, um ponto durante o jogo em que você suspeita de quedas de frame). Depois que o dispositivo estiver conectado e a gravação do rastro for concluída, os dados do rastro serão carregados na interface do APA.

    Tela de captura de rastro ou tela de rastro carregada
  2. Clique na guia SQL no APA: depois que a tela de análise de rastro for aberta, clique na guia SQL na área de navegação superior ou lateral da interface para abrir o ambiente do processador de rastros, em que você pode consultar os dados diretamente.

  3. Cole a consulta SQL na guia SQL do APA: copie a consulta SQL a seguir e cole-a no campo de entrada de consulta. Essa consulta identifica o processo do SurfaceFlinger, calcula os intervalos de frame com base nos carimbos de data/hora de atualização da tela real e deriva o QPS médio, o QPS dos 10% inferiores (P90) e o QPS dos 1% inferiores (P99).

    WITH target_process AS (
    -- 1. Get SurfaceFlinger process ID where frames were identified in debugging step 3
    SELECT upid
    FROM process
    WHERE name = '/system/bin/surfaceflinger'
    ),
    actual_present_times AS (
    -- 2. Calculate the hardware display timestamps when SurfaceFlinger actually updated the screen
    SELECT
        (ts + dur) AS present_ts
    FROM actual_frame_timeline_slice
    WHERE upid IN (SELECT upid FROM target_process)
        AND dur > 0
    ),
    present_intervals AS (
    -- 3. Calculate intervals between physical screen refreshes
    SELECT
        (LEAD(present_ts) OVER (ORDER BY present_ts ASC) - present_ts) / 1000000.0 AS p2p_ms
    FROM actual_present_times
    ),
    valid_intervals AS (
    -- 4. Filter for valid frame intervals
    SELECT p2p_ms
    FROM present_intervals
    WHERE p2p_ms IS NOT NULL AND p2p_ms > 0
    ),
    ordered_frames AS (
    -- 5. Sort in ascending order to calculate percentiles
    SELECT
        p2p_ms,
        ROW_NUMBER() OVER (ORDER BY p2p_ms ASC) AS row_num,
        COUNT(1) OVER () AS total_frames
    FROM valid_intervals
    )
    -- 6. Output final metrics
    SELECT
    (SELECT COUNT(1) FROM valid_intervals) AS total_presented_frames,
    ROUND(1000.0 / NULLIF((SELECT AVG(p2p_ms) FROM valid_intervals), 0), 2) AS average_fps,
    ROUND(1000.0 / NULLIF((SELECT p2p_ms FROM ordered_frames WHERE row_num = CAST(total_frames * 0.90 AS INT)), 0), 2) AS low_10_fps,
    ROUND(1000.0 / NULLIF((SELECT p2p_ms FROM ordered_frames WHERE row_num = CAST(total_frames * 0.99 AS INT)), 0), 2) AS low_1_fps;
    
  4. Clique em "Executar consulta": clique no botão Executar consulta (ou no ícone de execução) perto do campo de entrada de consulta. Quando a execução da consulta for concluída, o total de frames medidos (total_presented_frames), o frame rate médio (average_fps), o QPS dos 10% inferiores (low_10_fps) e o QPS dos 1% inferiores (low_1_fps) serão exibidos em uma tabela no painel de resultados.

    Tela mostrando a consulta SQL executada e as quatro métricas resultantes exibidas em uma tabela

2. Medir usando o adb (dumpsys SurfaceFlinger)

Para medir com eficácia o QPS médio, P90 e P99, use o comando Android dumpsys surfaceflinger timestats. Essa ferramenta fornece o QPS médio e um histograma de tempo presentToPresent para todas as camadas que estão sendo renderizadas. O tempo presentToPresent de um frame é o intervalo entre o frame atual e o frame anterior que está sendo desenhado.

Confira as instruções detalhadas para coletar e calcular essas métricas para seu jogo:

  1. Começar a captura: execute o comando a seguir com as flags "enable" e "clear" para começar a capturar informações:

    adb shell dumpsys SurfaceFlinger --timestats -clear -enable
    
  2. Despejar informações: quando o jogo tiver sido jogado por tempo suficiente, execute o comando novamente com a flag "dump" para gerar as informações:

    adb shell dumpsys SurfaceFlinger --timestats -dump
    
  3. Filtrar por camada: as informações despejadas fornecem dados para todas as camadas renderizadas pelo SurfaceFlinger. Você precisa encontrar a seção correspondente ao jogo filtrando com base no layerName (por exemplo, layerName = SurfaceView[com.example.yourgame...]).

    layerName = SurfaceView[com.google.test/com.devrel.MainActivity]@0(BLAST)#132833
    
  4. Identificar o QPS médio: o QPS médio de cada camada é calculado automaticamente e mostrado diretamente na saída de despejo (por exemplo, averageFPS = 30.179).

    ...
    averageFPS = 30.179
    ...
    
  5. Calcular o QPS P90 e P99: para encontrar as métricas P90 e P99, você precisa analisar o totalFrames e o histograma de tempo presentToPresent fornecido no despejo.

    totalFrames = 1000
    ...
    presentToPresent histogram is as below:
    0ms=0 1ms=0 2ms=0 3ms=0 4ms=0 5ms=0 6ms=0 7ms=0 8ms=0 9ms=0 10ms=0 11ms=0 12ms=0
    13ms=0 14ms=0 15ms=0 16ms=850 17ms=0 18ms=0 19ms=0 20ms=0 21ms=0 22ms=0 23ms=0
    24ms=0 25ms=0 26ms=0 27ms=0 28ms=0 29ms=0 30ms=0 31ms=0 32ms=0 33ms=100 34ms=0
    36ms=0 38ms=0 40ms=0 42ms=0 44ms=0 46ms=0 48ms=0 50ms=35 54ms=0 58ms=0 62ms=0
    66ms=10 70ms=0 74ms=0 78ms=0 82ms=0 86ms=0 90ms=0 94ms=0 98ms=0 102ms=5 106ms=0
    110ms=0 114ms=0 118ms=0 122ms=0 126ms=0 130ms=0 134ms=0 138ms=0 142ms=0 146ms=0
    150ms=0 200ms=0 250ms=0 300ms=0 350ms=0 400ms=0 450ms=0 500ms=0 550ms=0 600ms=0
    650ms=0 700ms=0 750ms=0 800ms=0 850ms=0 900ms=0 950ms=0 1000ms=0
    

    A. Exemplo conceitual (tabela de distribuição cumulativa) Suponha que a sessão de jogo tenha registrado uma contagem de totalFrames de 1.000. Para encontrar P90 e P99, calcule os limites de milissegundos em que a contagem cumulativa de frames atinge 900 frames (90%) e 990 frames (99%), respectivamente, contando a partir do bucket de milissegundos mais baixo.

    Tempo de frame (ms) Contagem de frames (histograma) Contagem cumulativa de frames Status / cálculo do percentil
    16ms 850 850 85,0%
    33ms 100 950 95,0%
    (P90 de 900 atingido! → 1000/33 = 30,3 QPS)
    50ms 35 985 98,5%
    66ms 10 995 99,5%
    (P99 de 990 atingido! → 1000/66 = 15,1 QPS)
    102ms 5 1.000 100%

    B. Lógica de implementação (pseudocódigo) Se você estiver automatizando essa análise usando um script Python ou um analisador de registros, a lógica para extrair valores P90 e P99 do histograma poderá ser implementada da seguinte maneira:

    # Define target thresholds based on total frame count
    p90_target = totalFrames * 0.90
    p99_target = totalFrames * 0.99
    
    cumulative_frames = 0
    p90_fps = None
    p99_fps = None
    
    # Iterate through the parsed SurfaceFlinger histogram data (sorted by millisecond)
    for ms_bucket, frame_count in present_to_present_histogram:
        cumulative_frames += frame_count
    
        # Capture P90 when cumulative frames cross the 90% threshold
        if p90_fps is None and cumulative_frames >= p90_target:
            p90_fps = 1000 / ms_bucket
    
        # Capture P99 when cumulative frames cross the 99% threshold
        if p99_fps is None and cumulative_frames >= p99_target:
            p99_fps = 1000 / ms_bucket
            break # Optimization: stop iterating once both targets are found
    
  6. Parar a captura: depois de coletar todas as informações necessárias, você deve desativar as estatísticas de tempo usando a flag "disable":

    adb shell dumpsys SurfaceFlinger --timestats -disable
    

Sessões lentas

As sessões lentas identificam problemas de performance generalizados no mundo real. Uma sessão é "lenta" se mais de 25% dos frames caírem abaixo de um limite (por exemplo, 20 QPS). Embora seja útil para detectar problemas críticos de build, essa métrica sozinha não garante uma experiência sustentável e de alta qualidade. Um jogo pode evitar o limite de sessão lenta, mas ainda sofrer micro-travamentos que comprometem uma experiência suave de 60 QPS.

Embora ambos sejam derivados de tempos de frame, "Sessão lenta" e "Frame rate" têm funções diferentes. As métricas de QPS médio, P90 e P99 medem a qualidade e a sustentabilidade da performance, detectando quedas instantâneas e ritmo inconsistente que a métrica de sessão lenta pode ignorar.

Conclusão

A otimização de performance bem-sucedida requer uma estratégia abrangente. Os desenvolvedores precisam usar as sessões lentas como um radar principal para detectar degradação grave de performance e, em seguida, examinar o QPS médio, P90 e P99 para diagnosticar as causas subjacentes e verificar a suavidade real da jogabilidade. Ao integrar essas métricas, você pode garantir que seu aplicativo ofereça uma experiência do usuário excepcional e sustentável.

Outros recursos

Para saber mais sobre técnicas avançadas de criação de perfil, implementação da API Frame Pacing e estratégias de otimização específicas do mecanismo, consulte a documentação oficial para desenvolvedores Android:

  • Android vitals: sessões lentas: entenda como o Google Play mede e informa períodos prolongados de renderização lenta, o que afeta diretamente a experiência do usuário. Uma "sessão lenta" é definida como uma sessão do usuário em que mais de 25% dos frames são lentos (por exemplo, demoram mais de 50 ms, o que equivale a 20 QPS).
  • Desenvolvedores Android: otimizar a performance do jogo: confira o hub central para otimização de jogos Android. Este guia abrangente aborda práticas recomendadas e ferramentas de criação de perfil (como APA e Perfetto) para ajudar você a maximizar a performance geral do jogo.