Em relação a uma métrica de suavidade da animação

Saiba como medir animações, avaliar os frames e a suavidade geral da página.

Behdad Bakhshinategh
Behdad Bakhshinategh
Jonathan Ross
Jonathan Ross
Michal Mocny
Michal Mocny

Você provavelmente já viu páginas que "gaguem" ou "congelar" durante a rolagem ou animações. Gostaríamos de dizer que essas experiências não são boas. Para o endereço esses tipos de problemas, a equipe do Chrome está trabalhando para adicionar mais suporte às ferramentas de laboratório para detecção de animações, além de fazer melhorias constantes até o diagnóstico do pipeline de renderização no Chromium.

Gostaríamos de compartilhar alguns progressos recentes, oferecer orientação concreta sobre as ferramentas e discutir ideias para métricas futuras de suavidade da animação. Como sempre, adoraríamos para ouvir seu feedback.

Esta postagem abordará três tópicos principais:

  • Uma rápida olhada em animações e frames de animação.
  • Nossas ideias atuais sobre como avaliar a suavidade geral da animação.
  • Confira algumas sugestões práticas para usar nas ferramentas do laboratório.

O que são animações?

As animações dão vida ao conteúdo! Fazendo o conteúdo se mover, especialmente em resposta às interações do usuário, as animações podem tornar a experiência mais natural, compreensível e divertida.

Mas animações mal implementadas, ou apenas o excesso de animações, podem degradar a experiência e torná-la decididamente sem graça. Provavelmente, todos nós interagimos com uma interface que acabou de adicionar muitas palavras "úteis" transição que se tornam hostis quando têm desempenho ruim. Por isso, alguns usuários podem preferir movimento reduzido, uma preferência do usuário que você deve respeitar.

Como as animações funcionam?

Recapitulando rapidamente, o pipeline de renderização consiste em algumas etapas sequenciais:

  1. Estilo:calcule o estilos que se aplicam aos elementos.
  2. Layout:gere o a geometria e a posição de cada elemento.
  3. Pintar:preencha o pixels de cada elemento em camadas.
  4. Composto:desenhe a camadas na tela.

Embora existam muitas maneiras de definir animações, todas elas funcionam fundamentalmente por meio de uma das seguintes opções:

  • Ajustar o layout propriedades.
  • Ajustar a pintura propriedades.
  • Ajuste do composto propriedades.

Como esses estágios são sequenciais, é importante definir animações de termos de propriedades que estão mais adiante no pipeline. Quanto mais cedo for a atualização acontece no processo, maiores são os custos e é menos provável que sejam lisas. Consulte Renderização performance para mais detalhes.

A animação de propriedades de layout pode ser conveniente, mas há custos para ao fazer isso, mesmo que esses custos não sejam imediatamente aparentes. As animações devem ser em termos de mudanças de propriedades compostas sempre que possível.

Definir animações CSS declarativas ou usar a Web Animações, e garantindo que a animação dos compostos do Compute Engine, é um ótimo primeiro passo para garantir animações suaves e eficientes. Mas ainda assim, isso por si só não garante a suavidade, porque até mesmo animações eficientes na Web têm limites de desempenho. Por isso é sempre importante medir.

O que são frames de animação?

As atualizações na representação visual de uma página levam algum tempo para aparecer. Um visual leva a um novo frame de animação, que é eventualmente renderizado na tela do usuário.

Exibe a atualização em algum intervalo, de modo que as atualizações visuais sejam agrupadas. Muitas telas em um intervalo fixo de tempo, como 60 vezes por segundo (ou seja, 60 Hz). Telas mais modernas têm taxas de atualização mais altas. (90 a 120 Hz estão se tornando comuns). Muitas vezes, essas telas podem se adaptar ativamente entre taxas de atualização, conforme necessário, ou até mesmo oferecer frame rates totalmente variáveis.

O objetivo de qualquer aplicativo, como um jogo ou navegador, é processar todos esses atualizações visuais em lote e produzem um frame de animação visualmente completo dentro o prazo, todas as vezes. Essa meta é totalmente diferente de outras tarefas importantes do navegador, como carregar rapidamente conteúdo da rede ou executar tarefas de JavaScript com eficiência.

Em algum momento, pode ser muito difícil concluir todas as atualizações visuais dentro o prazo alocado atribuído pela tela. Quando isso acontece, o navegador descarta um frame. A tela não fica preta, apenas se repete. Você vê a mesma atualização visual por mais tempo, o mesmo frame de animação que foi apresentado na oportunidade de frame anterior.

Isso acontece com frequência. Nem sempre é perceptível, especialmente para conteúdo estático ou semelhante a documento, o que é comum na plataforma da Web em particular. Os frames descartados só ficam aparentes quando há elementos visuais importantes atualizações, como animações, para as quais precisamos de um fluxo constante de animações. atualizados para mostrar um movimento suave.

O que afeta os frames de animação?

Os desenvolvedores Web podem impactar muito a capacidade de um navegador de fazer isso de forma rápida e renderizar com eficiência e apresentar atualizações visuais.

Alguns exemplos:

  • Usar conteúdo muito grande ou que consuma muitos recursos para decodificar rapidamente na dispositivo de destino.
  • Uso de muitas camadas exigindo muita memória GPU.
  • Definir estilos CSS ou animações da Web muito complexos.
  • Usar antipadrões de design que desativam otimizações de renderização rápida.
  • Muito trabalho de JS na linha de execução principal, levando a tarefas longas que bloqueiam recursos visuais atualizações.

Mas como você pode saber quando um frame de animação perdeu o prazo e causou uma queda de frame?

Um método possível é usar requestAnimationFrame() com a sondagem, mas tem várias desvantagens. requestAnimationFrame() ou "rAF", informa ao navegador que você quer realizar uma animação e solicita uma antes da próxima etapa de pintura do pipeline de renderização. Se sua função de retorno de chamada não é chamada no momento esperado, isso significa que uma Paint não foi executada e um ou mais frames foram ignorados. Ao sondar e contando com que frequência o rAF é chamado, você pode calcular uma espécie de "quadros por segundo" (QPS).

let frameTimes = [];
function pollFramesPerSecond(now) {
  frameTimes = [...frameTimes.filter(t => t > now - 1000), now];
  requestAnimationFrame(pollFramesPerSecond);
  console.log('Frames per second:', frameTimes.length);
}
requestAnimationFrame(pollFramesPerSecond);

Usar a sondagem requestAnimationFrame() não é uma boa ideia por vários motivos:

  • Cada script precisa configurar o próprio loop de pesquisa.
  • Pode bloquear o caminho crítico.
  • Mesmo que a sondagem de rAF seja rápida, ela pode impedir requestIdleCallback() da capacidade de programar bloqueios longos de inatividade quando usados continuamente (blocos que ultrapassar um único frame).
  • Da mesma forma, a falta de blocos ociosos longos impede que o navegador programe outros tarefas de longa duração (como coleta de lixo mais longa e outro segundo plano ou trabalho especulativo).
  • Se a sondagem estiver ativada e desativada, você perderá casos em que o orçamento de frames foi excedido.
  • A enquete vai relatar falsos positivos nos casos em que o navegador estiver usando de frequência de atualização variável (por exemplo, devido à energia ou ao status de visibilidade).
  • E o mais importante: ele não captura todos os tipos de animação atualizações.

Muito trabalho na linha de execução principal pode afetar a capacidade de ver os frames de animação. Confira o Relatório de Exemplo para saber como um animação orientada por rAF, quando há muito trabalho no thread principal (como vai levar à queda de frames e menos callbacks de rAF e QPS mais baixo.

Quando a linha de execução principal fica sobrecarregada, as atualizações visuais começam a travar. Isso é instabilidade!

Muitas ferramentas de medição se concentraram amplamente na capacidade das principais para que ela seja gerada em tempo hábil e que os frames de animação funcionem sem problemas. Mas isso não é tudo! Veja o exemplo a seguir:

O vídeo acima mostra uma página que injeta tarefas longas periodicamente na interface principal fio Essas tarefas longas prejudicam completamente a capacidade da página de oferecer alguns tipos de atualizações visuais, e é possível ver, no canto superior esquerdo, queda correspondente de requestAnimationFrame() relatada como 0 QPS.

Mesmo assim, apesar dessas tarefas longas, a página continua rolando suavemente. Isso é porque, em navegadores modernos, a rolagem é frequentemente com conversas agrupadas, orientadas inteiramente pelo compositor.

Este é um exemplo que contém simultaneamente muitos frames descartados na interface principal linha de execução, mas ainda tem muitos frames de rolagem entregues com sucesso no linha de execução de compositor. Quando a tarefa longa for concluída, a atualização da pintura da linha de execução principal será feita. não oferece nenhuma mudança visual. a sondagem de rAF sugeriu uma queda de frame para 0, visualmente, o usuário não percebe a diferença.

Para frames de animação, a história não é tão simples.

Frames de animação: atualizações importantes

O exemplo acima mostra que há mais na história do que apenas requestAnimationFrame():

Então, quando as atualizações e os frames de animação são importantes? Aqui estão alguns critérios que estamos pensando e gostaríamos de receber feedback sobre:

  • Atualizações de linhas de execução principais e do compositor
  • Atualizações de pintura ausentes
  • Como detectar animações
  • Qualidade versus quantidade

Atualizações de linhas de execução principais e do compositor

As atualizações de frames de animação não são booleanas. Não é caso que os frames possam apenas ser totalmente descartado ou apresentado. Há muitas razões para uma animação o frame pode ser parcialmente apresentado. Em outras palavras, ele pode ter simultaneamente alguns conteúdos desatualizados e também têm algumas atualizações visuais que são apresentado.

O exemplo mais comum disso é quando o navegador não consegue produzir uma nova atualização da linha de execução principal dentro do prazo do frame, mas tem um novo thread do compositor. update (como o exemplo de rolagem encadeada anterior).

Um motivo importante para usar animações declarativas para animar conjuntos é que isso permite que uma animação seja conduzida inteiramente pelo thread do compositor, mesmo quando o thread principal está ocupado. Esses tipos de animações pode continuar produzindo atualizações visuais de forma em paralelo.

Por outro lado, pode haver casos em que uma atualização de linha de execução principal finalmente se torna disponível para apresentação, mas só depois de perder vários prazos de frame. Aqui o navegador terá alguma nova atualização, mas pode não ser a mais recente.

De modo geral, consideramos frames que contêm algumas novas atualizações visuais, sem todas as novas atualizações visuais, como um frame parcial. Frames parciais são razoavelmente comuns. O ideal é que as atualizações parciais incluam pelo menos as atualizações visuais, como animações, mas isso só pode acontecer se as animações forem orientada pelo thread do compositor.

Atualizações de pintura ausentes

Outro tipo de atualização parcial ocorre quando mídias como imagens não são concluídas decodificação e rasterização para a apresentação do frame.

Ou, mesmo que uma página seja perfeitamente estática, os navegadores ainda podem atrasar a renderização atualizações visuais durante a rolagem rápida. Isso acontece porque as execuções de pixels o conteúdo além da janela de visualização visível pode ser descartado para economizar memória da GPU. Ela demora para renderizar pixels e pode demorar mais do que um único frame para renderizar tudo depois de uma grande rolagem, como o movimento do dedo. Isso geralmente é feito também conhecido como quebra-cabeça.

A cada oportunidade de renderização de frames, é possível rastrear as atualizações visuais mais recentes realmente chegaram à tela. Medir a capacidade de fazer isso ao longo de vários frames (ou tempo) é conhecida como capacidade de processamento de frames.

Se a GPU estiver sobrecarregada, o navegador (ou a plataforma) poderá até começar ele acelera a taxa de tentativas de atualizações visuais e, portanto, diminui frame rates efetivos. Embora tecnicamente isso possa reduzir o número de atualizações de frame, ele ainda aparecerá visualmente como uma capacidade de processamento de frame menor.

No entanto, nem todos os tipos de baixa capacidade de processamento de frames são ruins. Se a página estiver quase inativa e não há animações ativas, um frame rate baixo é igualmente atraente como um frame rate alto (e pode economizar bateria).

Quando a capacidade de processamento de frames é importante?

Como detectar animações

A alta capacidade de processamento de frames é importante, principalmente em períodos com animações. Diferentes tipos de animação dependem das atualizações visuais de um linha de execução específica (principal, compositor ou um worker). Portanto, sua atualização visual é dependente de que o thread forneça a atualização dentro do prazo. Dizemos que um determinada linha de execução afeta a suavidade sempre que há uma animação ativa que depende dessa atualização do thread.

Alguns tipos de animação são mais fáceis de definir e detectar do que outros. Animações declarativas, ou animações com base na entrada do usuário, são mais claras de definir. animações baseadas em JavaScript, implementadas como atualizações periódicas propriedades de estilo.

Mesmo com requestAnimationFrame() você nem sempre pode presumir que cada chamada de rAF está necessariamente produzindo uma atualização ou animação. Por exemplo, usar a sondagem de rAF (rAF, na sigla em inglês) apenas para rastrear o frame rate (como mostrado acima) não deve afetar por si só as medidas de suavidade, pois não há nenhuma atualização visual.

Qualidade versus quantidade

Por fim, detectar animações e atualizações de frames de animação ainda é apenas parte do a história porque ela só captura a quantidade de atualizações de animação, não de qualidade.

Por exemplo, você pode ver uma taxa de quadros constante de 60 fps ao assistir um vídeo. Tecnicamente, isso é perfeitamente suave, mas o vídeo em si pode ter um baixa taxa de bits ou problemas com armazenamento em buffer de rede. Isso não é capturado pela métricas de suavidade da animação diretamente, mas ainda pode ser desagradável para usuário.

Ou um jogo que use o <canvas>, talvez até mesmo usando técnicas como fora da tela tela para garantir uma taxa de quadros estável) pode ser tecnicamente perfeita em termos de frames de animação com falha ao carregar recursos de jogo de alta qualidade na cena ou exibição de artefatos de renderização.

E, claro, um site pode ter algumas animações muito ruins 🙂

GIF das antigas em construção

Acho que eles foram bem legais para o tempo deles!

Estados de um único frame de animação

Porque os frames podem ser apresentados parcialmente ou a queda de frames pode ocorrer de maneiras que não afetam a suavidade, começamos a pensar em cada frame como tendo um pontuação de integridade ou suavidade.

Aqui está o espectro de maneiras pelas quais interpretamos o estado de uma única frame de animação, ordenado do melhor para o pior:

Nenhuma atualização desejada Tempo de inatividade, repetição do frame anterior.
Apresentação completa A atualização da linha de execução principal foi confirmada dentro do prazo ou não era necessário atualizar a linha de execução principal.
Parcialmente apresentado Somente compositor. a atualização atrasada da linha de execução principal não tinha elementos visuais mudar.
Parcialmente apresentado Somente compositor. a linha de execução principal teve uma atualização visual, mas isso atualização não incluiu uma animação que afeta a suavidade.
Parcialmente apresentado Somente compositor. a linha de execução principal teve uma atualização visual que afetava suavidade, mas um frame anteriormente obsoleto chegou e foi usado.
Parcialmente apresentado Somente compositor. sem a atualização principal desejada, e a a atualização do compositor tem uma animação que afeta a suavidade.
Parcialmente apresentado Somente o compositor, mas a atualização dele não tem um animação que afeta a suavidade.
Frame descartado Nenhuma atualização. Não havia uma atualização do compositor desejada, e a main foi atrasado.
Frame descartado Eu queria uma atualização do compositor, mas ela foi atrasada.
Frame desatualizado Uma atualização era esperada, ela foi produzida pelo renderizador, mas a A GPU ainda não a apresentou antes do prazo de vsync.

É possível transformar esses estados em uma pontuação. E talvez uma maneira interpretar essa pontuação é considerá-la uma probabilidade de ser observável o usuário. Um único frame descartado pode não ser muito observável, mas uma sequência de muitos frames perdidos afetando a suavidade em sequência, claro!

Como tudo funciona em conjunto: uma métrica de porcentagem de frames descartados

Embora às vezes seja necessário analisar profundamente o estado de cada quadro de animação, também é útil atribuir uma visão rápida pontuação para uma experiência.

Os frames podem ser parcialmente apresentados e até mesmo totalmente ignorados as atualizações de frames podem não afetar a suavidade. Queremos nos concentrar menos contando apenas frames e muito mais na extensão a que o navegador não consegue fornecer atualizações visualmente completas no momento certo.

O modelo mental deve partir de:

  1. Quadros por segundo a
  2. Detectar atualizações de animação importantes e ausentes para
  3. Porcentagem reduzida em um determinado período.

O que importa é: a proporção de tempo que você espera para tarefas importantes atualizações. Acreditamos que isso corresponde à maneira natural que os usuários experimentam a suavidade de conteúdo da Web na prática. Até agora, usamos o seguinte como conjunto inicial de métricas:

  • Porcentagem média de queda: para todos os frames de animação não inativos no linha do tempo inteira
  • Pior caso de porcentagem de frames descartados: conforme medido ao longo de um segundo deslizante janelas de tempo.
  • 95o percentil da porcentagem de frames descartados:medido em um segundo janelas deslizantes de tempo.

Atualmente, é possível encontrar essas pontuações em algumas ferramentas para desenvolvedores do Chrome. Embora esses se concentram apenas na capacidade geral de processamento de frames, também estamos avaliando como a latência de frames.

Teste você mesmo usando as ferramentas para desenvolvedores!

HUD de desempenho

O Chromium tem um HUD de desempenho organizado atrás de uma bandeira (chrome://flags/#show-performance-metrics-hud). Nele, você encontra pontuações para itens como as Core Web Vitals e também algumas definições experimentais para a suavidade da animação com base no percentual de frames descartados ao longo do tempo.

HUD de desempenho

Estatísticas de renderização de frames

Ative a "Renderização de frames" Estatísticas" no DevTools pelas configurações de renderização para ter uma visualização ao vivo dos novos frames de animação, que são codificados por cores para diferenciar atualizações parciais de frames totalmente descartados atualizações. O QPS informado é somente para frames totalmente apresentados.

Estatísticas de renderização de frames

Frame Viewer nas gravações do perfil de desempenho do DevTools

A página Desempenho do DevTools painel tem há muito tempo um Frames leitor. No entanto, ficou um pouco fora de sincronia com a forma como o pipeline moderno de renderização realmente funciona. Houve muitas melhorias recentes, mesmo na Chrome Canary, que facilita muito a depuração de problemas com animações.

Hoje você vai descobrir que os frames no visualizador de frames estão mais alinhados limites de vsync e codificados por cores com base no status. Ainda não há visualização de todas as nuances descritas acima, mas estamos planejando adicionar mais em breve.

Visualizador de frames no Chrome DevTools

Rastreamento do Chrome

Por fim, com o Rastreamento do Chrome, a ferramenta preferida para mergulhar fundo nos detalhes, grave uma "renderização de conteúdo da Web" rastros com o novo Perfetto IU (ou about:tracing) e nos aprofundaremos nas pipeline de gráficos. Pode ser uma tarefa assustadora, mas há algumas coisas adicionadas recentemente ao Chromium para facilitar. Você pode ter uma visão geral disponíveis na Life of a Moldura documento.

Com os eventos de rastreamento, é possível determinar definitivamente:

  • Quais animações estão em execução (usando eventos chamados TrackerValidation).
  • Acessar a linha do tempo exata dos frames de animação (usando eventos chamados PipelineReporter).
  • Para atualizações de animação instáveis, descubra exatamente o que está bloqueando que a animação seja mais rápida (usando os detalhamentos de eventos PipelineReporter).
  • Para animações com base em entradas, confira quanto tempo leva para receber uma atualização visual (usando eventos com o nome EventLatency).

Gerador de relatórios de pipeline do Rastreamento do Chrome

A seguir

O objetivo da iniciativa Métricas da Web é fornecer métricas e orientações para para criar ótimas experiências do usuário na Web. Métricas baseadas em laboratório, como Total o tempo de bloqueio (TBT, na sigla em inglês) são essenciais para detectar e diagnosticar possíveis problemas de interatividade. Estamos planejando criar uma métrica semelhante baseada em laboratório para a suavidade da animação.

Manteremos vocês informados à medida que continuamos a trabalhar em ideias para criar um métrica abrangente com base em dados de frames de animação individuais.

No futuro, queremos também projetar APIs que permitam medir suavidade da animação com bom desempenho para usuários reais , assim como no laboratório. Fique de olho nas atualizações!

Feedback

Estamos animados com as melhorias recentes e as ferramentas para desenvolvedores que foram lançadas enviados no Chrome para medir a suavidade da animação. Experimente essas ferramentas, compare suas animações e informe aonde elas levam.

Você pode enviar seus comentários para web-vitals-feedback Google grupo com "[Smoothness Metrics]" na linha de assunto. Estamos realmente procurando Quero saber sua opinião!