Em direção a uma melhor métrica de capacidade de resposta

Saiba mais sobre nossas ideias para medir a capacidade de resposta e envie seu feedback.

Annie Sullivan
Annie Sullivan
Hongbo Song
Hongbo Song
Nicolás Peña Moreno
Nicolás Peña Moreno

Na equipe de Métricas de velocidade do Chrome, estamos trabalhando para aprofundar nosso conhecimento sobre a rapidez com que as páginas respondem à entrada do usuário. Gostaríamos de compartilhar algumas ideias para melhorar as métricas de capacidade de resposta e ouvir seu feedback.

Esta postagem abordará dois tópicos principais:

  1. Revise nossa métrica de capacidade de resposta atual, First Input Delay (FID), e explique por que escolhemos a FID em vez de algumas das alternativas.
  2. Apresente algumas melhorias que estamos considerando e que devem capturar melhor o e a latência de eventos individuais. Essas melhorias também visam capturar uma visão holística da capacidade de resposta geral de uma página ao longo de sua vida útil.

O que é First Input Delay?

A métrica First Input Delay (FID) mede quanto tempo o navegador leva para começar processando a primeira interação do usuário em uma página. Em particular, ele mede a diferença entre a hora em que o usuário interage com o dispositivo e a hora em que o navegador consegue iniciar o processamento de manipuladores de eventos. A FID é medida apenas por toques e pressionamentos de tecla, ou seja, considera apenas a primeira ocorrência dos seguintes eventos:

  • click
  • keydown
  • mousedown
  • pointerdown (somente se for seguida por pointerup)

O diagrama a seguir ilustra a FID:

First Input Delay
desde quando a entrada ocorre até quando ela pode ser processada

A FID não inclui o tempo gasto na execução desses manipuladores de eventos nem qualquer trabalho realizado pelo navegador. depois para atualizar a tela. Ela mede por quanto tempo a linha de execução principal ficou ocupada antes de ter a chance de lidar com uma entrada. Esse tempo de bloqueio geralmente é causado por tarefas JavaScript longas, pois eles não podem ser interrompidos a qualquer momento. Portanto, a tarefa atual deve ser concluída antes que o navegador possa começar a processar a entrada.

Por que escolhemos a FID?

Acreditamos que é importante avaliar a experiência real do usuário para garantir que as melhorias feitas o resultado da métrica em benefícios reais para o usuário. Escolhemos a FID porque ela representa parte da experiência do usuário quando ele decide interagir com um site que acabou de ser carregado. A FID captura parte do tempo que o usuário precisa aguardar para ver uma resposta do com um site. Em outras palavras, a FID é um limite inferior no tempo que um usuário espera. depois da interação.

Outras métricas, como Tempo total de bloqueio (TBT, na sigla em inglês) e Tempo para interação da página (TTI, na sigla em inglês), são baseadas em tarefas longas e, como FID, também medir o tempo de bloqueio da linha de execução principal durante o carregamento. Como essas métricas podem ser medidas no campo e no laboratório, muitos desenvolvedores perguntaram por que não preferimos um desses em vez da FID.

Há várias razões para isso acontecer. Talvez o motivo mais importante seja que essas métricas não medir a experiência do usuário diretamente. Todas essas métricas avaliam quanto JavaScript é executado na página. Embora o JavaScript de longa duração tende a causar problemas aos sites, essas tarefas não afetariam necessariamente a experiência do usuário se ele não estivesse interagindo com a página quando isso ocorre. Uma página pode ter uma ótima pontuação no TBT e no TTI, mas parecer lenta ou ter uma pontuação ruim enquanto se sentir rápido para os usuários. De acordo com nossa experiência, essas medições indiretas resultam em métricas que funcionam muito bem para em alguns sites, mas não na maioria deles. Em resumo, o fato de que tarefas longas e TTI não são centrados no usuário esses candidatos mais fracos.

Embora a medição de laboratórios seja importante inestimável para o diagnóstico, o que realmente importa é a experiência dos usuários nos sites. Ao ter um centrada no usuário que reflita as condições reais do usuário, você certamente vai capturar algo significativa sobre a experiência. Decidimos começar com uma pequena parte dessa experiência, mesmo embora saibamos que esta parte não representa a experiência completa. É por isso que estamos trabalhando capturam uma parte maior do tempo que um usuário espera até que as entradas sejam processadas.

Medir o TTI em usuários reais em campo é problemático porque ocorre muito tarde na página carregar. É necessária uma janela silenciosa de rede de cinco segundos para que o TTI possa ser calculado. No laboratório, poderá optar por descarregar a página sempre que tiver todos os dados necessários, mas esse não é o caso. com monitoramento de usuários reais em campo. Um usuário pode optar por sair da página ou interagir com ela em a qualquer momento. Em particular, os usuários podem optar por deixar páginas que demoram para carregar e uma o TTI preciso não será registrado nesses casos. Quando medimos a TTI para usuários reais no Chrome, descobriu que apenas cerca da metade dos carregamentos de página alcançavam o TTI.

Que melhorias estamos considerando?

Gostaríamos de desenvolver uma nova métrica que estenda as medidas atuais da FID, mas que ainda mantenha uma conexão forte com a experiência do usuário.

Queremos que a nova métrica:

  1. Considere a capacidade de resposta de todas as entradas do usuário (não apenas a primeira)
  2. Capture a duração completa de cada evento (não apenas o atraso).
  3. Agrupe eventos que ocorrem como parte da mesma interação lógica do usuário e defina que a latência da interação como a duração máxima de todos os eventos.
  4. Criar uma pontuação agregada para todas as interações que ocorrem em uma página, ao longo no ciclo de vida de ML.

Para ter sucesso, devemos ser capazes de dizer com alta confiança que, se um site tiver uma pontuação baixa nesse nova métrica, ele não está respondendo rapidamente às interações do usuário.

Capturar toda a duração do evento

A primeira melhoria óbvia é tentar capturar a latência de ponta a ponta mais ampla de um evento. Conforme mencionado acima, a FID captura apenas a parte de atraso do evento de entrada. Ele não considera o tempo que o navegador leva para processar os manipuladores de eventos.

Há vários estágios no ciclo de vida de um evento, como ilustrado neste diagrama:

Cinco etapas no
ciclo de vida de um evento

Estas são as etapas que o Chrome segue para processar uma entrada:

  1. A entrada do usuário ocorre. O horário em que isso ocorre é o timeStamp do evento.
  2. O navegador realiza o teste de hits para decidir em qual frame HTML (frame principal ou algum iframe) um evento vai ocorrer. a que pertence. Em seguida, o navegador envia o evento ao processo do renderizador adequado responsável pelo desse frame HTML.
  3. O renderizador recebe o evento e o enfileira para que possa processá-lo quando ficar disponível para faça isso.
  4. O renderizador processa o evento executando seus manipuladores. Esses gerenciadores podem enfileirar trabalho assíncrono, como setTimeout e buscas, que fazem parte do processamento de entrada. Mas em agora, o trabalho síncrono está concluído.
  5. Um quadro é pintado na tela que reflete o resultado da execução dos manipuladores de eventos. Observe que quaisquer tarefas assíncronas enfileiradas pelos manipuladores de eventos ainda podem estar inacabadas.

O tempo entre as etapas (1) e (3) acima é o atraso de um evento, que é o que a FID mede.

O tempo entre as etapas (1) e (5) acima é a duração de um evento. É assim que nossa nova métrica medir.

A duração do evento inclui o atraso, mas também inclui o trabalho que ocorre nos manipuladores de eventos. e o trabalho que o navegador precisa fazer para pintar o próximo frame depois que esses manipuladores forem executados. A duração de um evento está disponível no momento na API Event Timing por meio do duração da entrada .

O ideal seria capturar também o trabalho assíncrono acionado pelo evento. Mas o problema é que, que é extremamente difícil de entender a definição de trabalho assíncrono acionado pelo evento. Conforme Por exemplo, um desenvolvedor pode optar por iniciar uma animação em manipuladores de eventos e usar um setTimeout para começar essa animação. Se capturássemos todas as tarefas postadas nos gerenciadores, a animação ficaria atrasada o tempo de conclusão enquanto a animação é executada. Acreditamos que vale a pena investigar opções sobre como usar heurística para capturar trabalhos assíncronos e que precisam ser concluídos o mais rápido possível. No entanto, queremos ter muito cuidado ao fazer isso, porque não queremos penalizar o trabalho. isso leva muito tempo para ser concluído. Portanto, nosso esforço inicial considerará a etapa 5 como até o ponto final: ele considera apenas o trabalho síncrono e a quantidade de tempo que leva para pintar após que esse trabalho seja concluído. Ou seja, não vamos aplicar heurística para adivinhar o trabalho que seria iniciado de forma assíncrona na etapa 4 em nosso esforço inicial.

Vale a pena ressaltar que, em muitos casos, o trabalho deve ser executado de forma síncrona. Na verdade, isso pode ser inevitável porque os eventos às vezes são distribuídos um após o outro, e os manipuladores de eventos precisam sejam executados em ordem. Dito isso, ainda vamos perder trabalhos importantes, como eventos que acionam busca ou que dependem de um trabalho importante a ser feito no próximo callback requestAnimationFrame, por exemplo.

Agrupar eventos em interações

Ampliar a medição da métrica de atraso para duração é uma boa primeira etapa, mas ainda deixa uma lacuna crítica na métrica: ela se concentra em eventos individuais e não na experiência do usuário interagindo com a página.

Vários eventos diferentes podem ser disparados como resultado de uma única interação do usuário e medir separadamente nem constroem uma imagem clara do que o usuário vivencia. Queremos ter certeza de que nossa métrica captura todo o tempo que um usuário tem que esperar por uma resposta ao tocar, pressionar teclas rolagem e arrastar com a maior precisão possível. Então, estamos introduzindo o conceito de interações para medir a latência de cada uma.

Tipos de interação

A tabela a seguir lista as quatro interações que queremos definir juntamente com os eventos DOM que às quais estão associados. Esse não é exatamente o mesmo conjunto de todos os eventos que são e enviado quando ocorre essa interação do usuário. Por exemplo, quando um usuário rola a tela, um evento de rolagem é enviado, mas acontece depois que a tela é atualizada para refletir a rolagem. consideram isso parte da latência da interação.

.
Interação Início / término Eventos no computador Eventos em dispositivos móveis
Teclado Tecla pressionada keydown keydown
keypress keypress
Chave liberada keyup keyup
Toque ou arraste Toque em "Iniciar" ou "Iniciar" pointerdown pointerdown
mousedown touchstart
Toque para cima ou arraste o final pointerup pointerup
mouseup touchend
click mousedown
mouseup
click
Rolagem N/A
Eventos DOM para cada tipo de interação.

No momento, as três primeiras interações listadas acima (teclado, toque e arrastar) são cobertas pela FID. Para nossa nova métrica de capacidade de resposta, queremos incluir também a rolagem, já que a rolagem é extremamente comum na Web e é um aspecto crítico da sensação de responsividade de uma página para os usuários.

Observe que cada uma dessas interações tem duas partes: quando o usuário pressiona o mouse, dedo ou tecla e quando o levantam. Precisamos garantir que nossa métrica não conte o tempo que o usuário passa manter o dedo pressionado entre essas duas ações como parte da latência da página.

Teclado

Uma interação de teclado tem duas partes: quando o usuário pressiona a tecla e quando ele a solta. Há três eventos associados a esta interação do usuário: keydown, keyup e keypress. O diagrama a seguir ilustra os atrasos e durações de keydown e keyup para um teclado interação:

Interação com o teclado
com durações de evento separadas

No diagrama acima, as durações estão separadas porque o frame das atualizações de keydown está apresentado antes da keyup ocorrer, mas esse não precisa ser sempre o caso. Além disso, observe que um frame possa ser apresentado no meio de uma tarefa no processo do renderizador desde as últimas etapas necessárias para produzir o frame são feitas fora do processo do renderizador.

keydown e keypress ocorrem quando o usuário pressiona a tecla, enquanto keyup ocorre quando o o usuário liberar a chave. Geralmente, a atualização de conteúdo principal ocorre quando a tecla é pressionada: texto aparece na tela ou o efeito modificador é aplicado. Dito isso, queremos capturar casos raros em que o keyup também apresenta atualizações interessantes na interface. Por isso, vamos analisar os o tempo total gasto.

Para capturar o tempo total da interação do teclado, podemos calcular o máximo da duração dos eventos keydown e keyup.

Há um caso extremo aqui que vale a pena mencionar: pode haver casos em que o usuário pressiona uma tecla demora um pouco para liberá-lo. Nesse caso, a sequência de eventos enviados pode variam. Em nesses casos, consideramos que há uma interação por keydown, que pode ou não ter um keyup correspondente.

Toque em

Outra interação importante do usuário é quando ele toca ou clica em um site. Semelhante a keypress, alguns eventos são disparados quando o usuário pressiona o botão para baixo, e outros conforme solta, conforme mostrado em no diagrama acima. Os eventos associados a um toque são um pouco diferentes no computador dispositivos móveis.

Para um toque ou clique, o soltar geralmente é a que desencadeia a maioria das reações, mas, assim como nas interações de teclado, queremos capturar a interação completa. Nesse caso, é mais é importante fazer isso, porque ter algumas atualizações de interface ao pressionar o toque não é tão incomum.

Gostaríamos de incluir as durações de todos esses eventos, mas muitos deles se sobrepõem completamente, precisamos medir apenas pointerdown, pointerup e click para cobrir interação.

Uma ideia inicial seria usar os eventos pointerdown e pointerup e presumir que eles abrangem todas as durações em que estamos interessados. Infelizmente, esse não é o caso, pois essa borda caso. Tente abrir este site em um dispositivo móvel e tocar em "Clique aqui". Este site aciona o toque no navegador atraso. Podemos observar que pointerdown, pointerup e touchend sejam enviados rapidamente, enquanto mousedown, mouseup e click aguardam o atraso antes de serem enviados. Isso significa que, se olharmos apenas em pointerdown e pointerup, perderíamos a duração dos eventos sintéticos, que é grandes devido ao atraso no toque do navegador e devem ser incluídos. Portanto, precisamos medir pointerdown, pointerup e click para abranger a interação completa.

Arrasto

Decidimos incluir a ação de arrastar também, pois ela tem eventos associados semelhantes e, como geralmente, causa atualizações importantes na interface do site. Mas para nossa métrica, pretendemos considerar apenas o início da ação de arrastar e o final da ação de arrastar, ou seja, as partes inicial e final dela. Isso é para tornar mais fácil pensar além de tornar as latências comparáveis às outras interações consideradas. Isso é de acordo com nossa decisão de excluir eventos contínuos, como mouseover.

Também não estamos considerando a implementação de arrastar e soltar usando o recurso API porque elas só funcionam no computador.

Rolagem

Uma das formas mais comuns de interagir com um site é a rolagem. Para nossa nova métrica, como medir a latência da interação inicial de rolagem do usuário. Especificamente, nós se preocupam com a reação inicial do navegador ao fato de que o usuário solicitou uma rolagem. Nós vamos não abrangem toda a experiência de rolagem. Ou seja, a rolagem produz muitos frames, e vamos focar nossa atenção para o frame inicial produzido como uma reação à rolagem.

Por que só o primeiro? Por um lado, os frames subsequentes podem ser capturados por uma suavidade separada. proposta. Ou seja, depois que o usuário vê o primeiro resultado da rolagem, o resto deve ser medido em à experiência de rolagem. Portanto, acreditamos que a suavidade poderia capturar isso melhor. Assim, assim como na FID, optamos por experiências do usuário distintas: experiências que tenham pontos claros de tempo associados a elas e para as quais podemos facilmente computar a latência. A rolagem como um todo é uma experiência contínua, então não pretendemos medir todos nessa métrica.

Então, por que medir rolagens? O desempenho de rolagem que coletamos no Chrome mostra que a rolagem é em geral, muito rápido. Dito isso, ainda queremos incluir latências de rolagem iniciais na nossa nova métrica por vários motivos. Primeiro, a rolagem é rápida somente porque foi muito otimizada, pois é muito importante. No entanto, ainda há maneiras de um site ignorar alguns dos ganhos de desempenho que o navegador oferece. O mais comum no Chrome é forçar a rolagem a acontecer na página principal fio Portanto, nossa métrica deve ser capaz de informar quando isso acontece e causa um baixo desempenho de rolagem. aos usuários. Em segundo lugar, a rolagem é muito importante para ser ignorada. Se excluirmos a rolagem teremos um grande ponto cego, e o desempenho de rolagem poderá diminuir com o tempo sem a os desenvolvedores perceberem.

Há vários eventos que são enviados quando o usuário rola a tela, como touchstart, touchmove e scroll. Exceto pelo evento de rolagem, isso depende em grande parte do dispositivo usado para Rolagem: eventos de toque são despachados ao rolar com o dedo em dispositivos móveis, enquanto o botão ocorrem ao rolar com a roda do mouse. Os eventos de rolagem são disparados após a rolagem inicial. foi concluída. E, em geral, nenhum evento DOM bloqueia a rolagem, a menos que o site use funções não passivas listeners de eventos. Portanto, pensamos na rolagem como desacoplada do DOM. Todos os eventos. O que queremos medir é o tempo a partir do qual o usuário se move o suficiente para produzir uma o gesto de rolagem até o primeiro frame que mostra que a rolagem aconteceu.

Como definir a latência de uma interação?

Como observamos acima, interações que têm uma "para baixo" e "para cima" componente precisam ser considerados separadamente para evitar atribuir o tempo que o usuário passou segurando o dedo para baixo.

Para esses tipos de interações, queremos que a latência envolva a duração de todos os eventos associados a elas. Como a duração dos eventos de cada "down" e "para cima" parte da interação pode se sobrepõem, a definição mais simples de latência de interação que o alcança é a de qualquer evento associado a ela. Voltando ao diagrama de teclado mostrado anteriormente, isso seria a duração de keydown, que é maior que o keyup:

Interação com o teclado
com duração máxima destacada

As durações de keydown e keyup também podem se sobrepor. Isso pode acontecer, por exemplo, quando o frame apresentadas para os dois eventos é o mesmo, como no diagrama a seguir:

Interação com o teclado
em que a ação de pressionar e soltar ocorrem no mesmo frame

Há prós e contras nessa abordagem de usar o máximo, e estamos interessados em ouvir seu feedback:

  • Pro: está alinhada com a forma como pretendemos medir a rolagem, já que mede apenas um duração do modelo.
  • Pro: o objetivo é reduzir o ruído para casos como interações do teclado, em que o keyup geralmente não faz nada e onde o usuário pode executar a tecla, pressionando e soltando rápida ou lentamente.
  • Con: não registra o tempo de espera total do usuário. Por exemplo, ele captura início ou fim de uma ação de arrastar, mas não ambos.

Para rolagem (que tem apenas um único evento associado), gostaríamos de definir a latência como o tempo o navegador leva para produzir o primeiro frame como resultado da rolagem. Ou seja, a latência é o delta entre o evento timeStamp do primeiro evento DOM (como touchmove, se você estiver usando uma dedo) que é grande o suficiente para acionar uma rolagem e a primeira pintura que reflete a rolagem o que está acontecendo.

Agregar todas as interações por página

Depois de definir o que é a latência de uma interação, precisaremos calcular um valor agregado para um carregamento de página, que pode ter muitas interações do usuário. Ter um valor agregado nos permite:

  • Formule correlações com as métricas de negócios.
  • Avalie correlações com outras métricas de desempenho. Idealmente, nossa nova métrica será suficiente independentemente de agregar valor às métricas atuais.
  • Exponha facilmente os valores nas ferramentas de uma forma que seja fácil de entender.

Para realizar essa agregação, precisamos resolver duas questões:

  1. Que números tentamos agregar?
  2. Como agregamos esses números?

Estamos analisando e avaliando várias opções. Sua opinião sobre essa agregação é muito bem-vinda.

Uma opção é definir um orçamento para a latência de uma interação, que pode depender do tipo (rolar, usar teclado, tocar ou arrastar). Por exemplo, se o orçamento para toques for de 100 ms e o de um toque for de 150 ms, o valor acima do orçamento dessa interação será 50 ms. Então, poderíamos calcular a quantidade máxima de latência que ultrapassa o orçamento para qualquer interação do usuário na página.

Outra opção é calcular a latência média ou mediana das interações ao longo da vida da página. Se tivéssemos latências de 80 ms, 90 ms e 100 ms, a média para a página seria de 90 ms. Também podemos considerar a média ou mediana "acima do orçamento" para levar em conta diferentes expectativas dependendo do tipo de interação.

Como isso funciona nas APIs de desempenho da Web?

O que está faltando na marcação de tempo do evento?

Infelizmente, nem todas as ideias apresentadas nesta postagem podem ser capturadas usando a marcação de tempo do evento. API. Em particular, não há uma maneira simples de conhecer os eventos associados a um determinado usuário com a API. Para fazer isso, propomos adicionar um interactionID ao API.

Outra falha da API Event Timing é que não há como medir a rolagem por isso estamos trabalhando para viabilizar essas medições (por meio da Event Timing ou de uma API separada).

O que você pode testar agora?

No momento, ainda é possível calcular a latência máxima para toques/arrastos e para o uso de e interações. O snippet de código a seguir produziria essas duas métricas.

let maxTapOrDragDuration = 0;
let maxKeyboardDuration
= 0;
const observer = new PerformanceObserver(list => {
  list
.getEntries().forEach(entry => {
   
switch(entry.name) {
     
case "keydown":
     
case "keyup":
        maxKeyboardDuration
= Math.max(maxKeyboardDuration,
            entry
.duration);
       
break;
     
case "pointerdown":
     
case "pointerup":
     
case "click":
        maxTapOrDragDuration
= Math.max(maxTapOrDragDuration,
            entry
.duration);
       
break;
   
}
 
});
});
observer
.observe({type: "event", durationThreshold: 16, buffered: true});
// We can report maxTapDragDuration and maxKeyboardDuration when sending
// metrics to analytics.

Feedback

Dê sua opinião sobre essas ideias enviando um e-mail para: web-vitals-feedback@googlegroups.com!