Uma abordagem sistemática da velocidade: medições on-line no front-end

O comando Yandex speed otimiza manualmente os resultados da pesquisa. Fazê-lo às cegas é difícil e muitas vezes simplesmente inútil. Portanto, a empresa construiu uma infraestrutura para coletar métricas, testar a velocidade e analisar os dados.

Sobre quais métricas devem ser usadas e como otimizar tudo, o desenvolvedor do Yandex interfaces Andrei Prokopyuk ( Andre_487 ).



O material é baseado no discurso de Andrey na conferência do HolyJS . Sob o corte - e vídeo, e uma versão em texto do relatório.


Além deste relatório sobre medições on-line, há um relatório de Alexei Kalmakov (também da Yandex) sobre medições off-line; nesse caso, não há versão em texto, mas um vídeo está disponível.


Os resultados da pesquisa Yandex consistem em muitos blocos diferentes, classes de respostas para consultas de usuários. Mais de 50 pessoas trabalham neles na empresa e, para que a taxa de emissão não caia, cuidamos constantemente do desenvolvimento.



Ninguém argumentará que os usuários gostam mais da interface rápida do que da lenta. Porém, antes de começar a otimizar, é importante entender como isso afetará seus negócios. Os desenvolvedores precisam gastar tempo acelerando a interface se isso não afetar as métricas de negócios?

Para responder a essa pergunta, vou contar duas histórias.

Histórico da introdução de uma fonte da web específica na emissão


Após estabelecer um experimento com fontes, descobrimos que o tempo médio para renderização do conteúdo se deteriorou em 3%, em 62 milissegundos. Não tanto se você tomar um delta no vácuo. O atraso perceptível a olho nu começa com apenas 100 milissegundos - e, no entanto, o tempo até o primeiro clique aumentou imediatamente um por cento e meio.



Os usuários começaram a interagir mais tarde com a página. O número de páginas clicadas diminuiu quase meio por cento. O tempo de presença no serviço foi reduzido e o tempo de ausência foi aumentado.



Não começamos a implementar o recurso com fontes. Afinal, esses números parecem pequenos até você lembrar a escala do serviço. Na realidade, um por cento e meio - centenas de milhares de pessoas.

Além disso, a velocidade tem um efeito cumulativo. Para uma atualização com uma parcela de não reclamados - 0,4% seguirá cada vez mais. No Yandex, esses recursos são lançados em dezenas por dia e, se você não lutar por cada compartilhamento, ele não durará muito e atingirá 10%.

Histórico de armazenamento em cache do LS


Essa história está relacionada ao fato de incorporarmos muito conteúdo estático na página.



Devido à sua alta variabilidade, não podemos compilá-lo em um único pacote ou entregá-lo com recursos externos. A prática demonstrou que, com a entrega em linha, a renderização e a inicialização do JavaScript são as mais rápidas.

Uma vez que decidimos que usar um repositório de navegador seria uma boa ideia. Coloque tudo no localStorage e, nas entradas subsequentes da página, carregue-o a partir daí e não o transmita pela rede.

Depois, focamos principalmente nas métricas "tamanho HTML" e "tempo de entrega HTML" e obtivemos bons resultados. Com o passar do tempo, inventamos novos métodos de medir velocidade, adquirimos experiência e decidimos verificar novamente, realizar um experimento reverso, desativando a otimização.



O tempo médio de entrega de HTML (a principal métrica no momento do desenvolvimento da otimização) aumentou 12%, o que é muito. Mas, ao mesmo tempo, o tempo até o cabeçalho ser desenhado, antes da análise do conteúdo começar e antes da inicialização do JavaScript. Também reduziu o tempo para o primeiro clique. A porcentagem é pequena - 0,6, mas se você se lembrar da escala ...



Ao desativar a otimização, obtivemos uma piora na métrica, perceptível apenas para especialistas e, ao mesmo tempo, uma melhoria perceptível para o usuário.

As seguintes conclusões podem ser tiradas disso:

Primeiro, a velocidade afeta realmente os negócios e as métricas de negócios.

Em segundo lugar, as otimizações devem ser precedidas de medições. Se você implementar algo, depois de fazer medições ruins, é provável que você não faça nada útil. A composição do público, a frota de dispositivos, os cenários de interação e as redes são diferentes em todos os lugares, e você precisa verificar o que exatamente funcionará para você.



Certa vez, Ash nos ensinou desde os mortos sinistros primeiro a atirar, depois a pensar ou não pensar. Em velocidade, você não precisa fazer isso.

E o terceiro ponto: as medições devem refletir a experiência do usuário. Por exemplo, o tamanho do HTML e o tempo de entrega são métricas de velocidade ruins, porque o usuário não se senta no devTools e não seleciona um serviço com menos atraso. Mas quais métricas são boas e corretas - contaremos mais adiante.

O que e como medir?


As medições devem começar com algumas métricas importantes que, diferentemente do tamanho do HTML, estão próximas da experiência do usuário.



Se TTFCP (tempo para a primeira pintura completa do conteúdo) e TTFMP (tempo para a primeira pintura significativa) indicam o tempo até a primeira renderização do conteúdo e o tempo antes da renderização do conteúdo significativo, então o terceiro é o tempo antes da inicialização da estrutura, vale a pena explicar.

Este é o momento em que a estrutura já passou pela página, coletou todos os dados necessários e travou os manipuladores. Se o usuário clicar em algum lugar naquele momento, ele receberá uma resposta dinâmica.

E a última, quarta métrica, o tempo até a primeira interatividade, geralmente é chamada de tempo para interatividade (TTI).

Essas métricas, diferentemente do tamanho html ou do tempo de entrega, estão próximas da experiência do usuário.

Hora de pintar primeiro o conteúdo completo


Para medir o tempo em que o usuário viu o primeiro conteúdo na página, existe uma API de tempo de pintura, disponível até agora apenas no cromo. Os dados dele podem ser obtidos da seguinte maneira.



Com essa chamada, obtemos um conjunto de eventos de renderização. Até agora, dois tipos de eventos são suportados: primeira pintura - qualquer renderização e primeira pintura com conteúdo completo - qualquer renderização de conteúdo que não seja o fundo branco da guia vazia e o conteúdo de fundo da página.

Portanto, obtemos uma série de eventos, filtramos a tinta primeiro e o conteúdo completo e enviamos com um determinado ID.

Hora da primeira pintura significativa


Não há nenhum evento na API de sincronização do Paint sinalizando que um conteúdo significativo foi renderizado na página. Isso se deve ao fato de que esse conteúdo em cada página é diferente. Se estamos falando de serviço de vídeo, o principal é o player, nos resultados da pesquisa - o primeiro resultado que não é de publicidade. Existem muitos serviços e uma API universal ainda não foi desenvolvida. Mas aqui muletas boas e comprovadas entram em jogo.

Existem duas escolas de muletas no Yandex para medir essa métrica: usando RequestAnimationFrame e medindo com InterceptionObserver.

No RequestAnimationFrame, a renderização é medida usando um intervalo.



Suponha que haja algum conteúdo significativo. Aqui está uma div com o conteúdo principal da classe. Um script é colocado na frente dele, em que RequestAnimationFrame é chamado duas vezes.

No retorno de chamada da primeira chamada, escreva o limite inferior do intervalo. No retorno de chamada do segundo - o topo. Isso ocorre devido à estrutura de quadros que o navegador renderiza.



O primeiro é a execução do JavaScript, a análise dos estilos e o cálculo do layout, renderização e composição.

O retorno de chamada, chamando RequestAnimationFrame, é ativado no mesmo estágio do JavaScript e o conteúdo é renderizado na última seção do quadro durante a composição. Portanto, na primeira chamada, obtemos apenas o limite inferior, visivelmente removido no tempo da saída de pixels na tela.



Coloque dois quadros lado a lado. Pode-se ver que no final do primeiro deles o conteúdo foi renderizado. Anotamos a borda inferior de RequestAnimationFrame, chamada dentro do primeiro retorno de chamada e o retorno de chamada no segundo quadro. Assim, obtemos o intervalo do JavaScript chamado no quadro em que o conteúdo foi renderizado para JavaScript no segundo quadro.

InterceptionObserver


Nossa segunda muleta com o mesmo conteúdo funciona de maneira diferente. Desta vez, o script é colocado abaixo. Nele, criamos InterceptionObserver e assinamos o domNode.



Como não passamos parâmetros adicionais, medimos sua interseção com a viewport. Esse tempo é registrado como o tempo exato da renderização.



Isso funciona porque a interseção do conteúdo principal e da janela de visualização é a interseção exata que o usuário vê. Essa API foi projetada para saber exatamente quando um usuário viu um anúncio, mas nossa pesquisa mostrou que isso também funciona em blocos que não são de anúncios.

Desses dois métodos, ainda é melhor usar o RequestAnimationFrame: seu suporte é mais amplo e é testado por nós na prática.

Js inited


Imagine uma estrutura que tenha algum tipo de evento “init” no qual você possa se inscrever, mas lembre-se de que, na prática, o JS Inited é uma métrica simples e complexa.



Simples - porque você só precisa encontrar o momento em que a estrutura terminou a organização dos eventos. Complexo - porque você precisa procurar esse ponto por conta própria para cada estrutura.

Tempo para interativo


O TTI costuma ser confundido com a métrica anterior, mas, na verdade, é um indicador do momento em que o fluxo principal do navegador é lançado. Durante o carregamento da página, muitas tarefas são executadas: da renderização de vários elementos à inicialização da estrutura. Somente quando é descarregado é que chega a primeira interatividade.

O conceito de tarefas longas e a API de tarefas longas ajudam a medir isso.

Primeiro sobre as longas tarefas.



Entre as breves tarefas indicadas pelas setas, o navegador pode empacotar facilmente o processamento de um evento do usuário, por exemplo, entrada, porque possui uma alta prioridade. Mas com as longas tarefas indicadas pelas setas vermelhas, isso não funcionará.

O usuário terá que esperar até que se esgote e somente depois que o navegador iniciar o processamento de sua entrada. Ao mesmo tempo, a estrutura já pode ser inicializada e os botões funcionarão, mas lentamente. Uma resposta tão adiada é uma experiência do usuário bastante desagradável. No momento em que a última Tarefa Longa é concluída e o encadeamento fica vazio por um longo tempo, a ilustração aparece em 7 segundos e 300 milissegundos.

Como medir esse intervalo dentro do JavaScript?



A primeira etapa é designada condicionalmente como a etiqueta do corpo de abertura, após o que vem o script. Isso cria um PerformanceObserver que assina o evento Long Task. Dentro do retorno de chamada PerformanceObserver, as informações do evento são coletadas em uma matriz.



Depois de coletar os dados, chega a hora do segundo passo. Ele é designado condicionalmente como uma etiqueta de corpo de fechamento. Pegamos o último elemento da matriz, a última tarefa longa, examinamos o momento de sua conclusão e verificamos se já passou tempo suficiente.

No trabalho original dessa métrica, 5 segundos foram tomados como constantes, mas a escolha não foi substanciada de forma alguma. Acabou sendo suficiente por 3 segundos. Se passarem 3 segundos, contamos o tempo até a primeira interatividade; caso contrário, definimos Timeout e verificamos essa constante novamente.

Como processar os dados?


Os dados precisam ser recebidos dos clientes, processados ​​e apresentados de maneira conveniente. Nosso conceito de envio de dados é bastante simples. É chamado de contador.



Transferimos os dados de uma determinada métrica para uma caneta especial no back-end e os coletamos no repositório.



Aqui, a agregação de dados é designada convencionalmente como uma consulta SQL. Aqui estão as principais agregações que geralmente consideramos de acordo com as métricas de velocidade: média aritmética e grupo de percentis (50, 75, 95, 99).



A média aritmética em nossa série numérica é quase 1900. É visivelmente maior que a maioria dos elementos do conjunto, porque essa agregação é muito sensível aos valores extremos. Essa propriedade ainda é útil para nós.



Para calcular percentis para o mesmo conjunto, classifique-o e coloque o ponteiro no índice de percentil. Digamos que o 50, que também é chamado de mediana. Nós caímos entre os elementos. Nesse caso, você pode sair da situação de maneiras diferentes, calculamos a média entre elas. Temos 150. Quando comparado com a média aritmética, é claramente visto que os percentis são insensíveis aos valores extremos.

Levamos em conta e usamos esses recursos de agregações. A sensibilidade aritmética das emissões é uma desvantagem se você tentar avaliar a experiência do usuário. De fato, um usuário sempre pode conectar-se à rede, por exemplo, de um trem e estragar a seleção.

Mas a mesma sensibilidade é uma vantagem quando se trata de monitoramento. Para não perder um problema importante, usamos a média aritmética. Ele muda facilmente, mas o risco de um falso positivo nesse caso não é um problema tão grande. Melhor ignorar do que ignorar.



Além disso, consideramos a mediana (se anexarmos às métricas de tempo, a mediana é um indicador do tempo em que 50% das solicitações se encaixam) e o 75º percentil. No momento, 75% das solicitações se encaixam. Consideramos a estimativa da velocidade geral. Os percentis 95 e 99 são considerados para medir a cauda longa e lenta. Estes são números muito grandes. 95 é considerado o pedido mais lento. O percentil 99 é anormal.

Não faz sentido contar o máximo. Este é o caminho da loucura. Depois de calcular o máximo, pode acontecer que o usuário aguarde o carregamento da página há 20 anos.

Tendo considerado as agregações, resta apenas aplicar esses números, e a coisa mais óbvia que se pode fazer com eles é apresentá-los em gráficos.



No gráfico, nosso tempo real até o primeiro conteúdo contém métricas completas de tinta para pesquisa. A linha azul reflete a dinâmica dos desktops, a vermelha - para dispositivos móveis.

Temos que monitorar constantemente os gráficos de velocidade e confiamos essa tarefa ao robô.

Monitoramento


Como as métricas de velocidade são voláteis e constantemente flutuam com diferentes períodos, o monitoramento precisa ser ajustado. Para isso, usamos o conceito de frustrações.

Depuração é o momento em que um processo aleatório altera suas características, como variação ou expectativa matemática. No nosso caso, esta é a amostra média. Como mencionado, a média é sensível às emissões e adequada para o monitoramento.



Aqui está um exemplo de um gráfico em que o alinhamento ocorreu e o robô registrou o incidente. Como ele isolou esse momento de várias outras hesitações? Para entender isso, impomos dados adicionais.



O gráfico amarelo é um indicador métrico e o gráfico azul é uma média móvel com um período suficientemente grande. Vermelho é a média mais três desvios padrão. Verde é o mesmo, apenas com um sinal de menos.



Indicadores vermelhos e verdes formam um corredor seguro. Enquanto a métrica e a média móvel flutuam entre elas - tudo é normal, essas são flutuações comuns. Mas se eles saírem da zona segura, o monitoramento é acionado.



Verificando a velocidade dos recursos


Tudo o que foi discutido foi trabalhar com os dados de velocidade de um projeto já lançado, mas quero medir a velocidade de recursos individuais antes de enviá-los para grandes produções. Para fazer isso, usamos o teste A / B - uma comparação de métricas para os grupos controle e experimental.



Dividimos os usuários em grupos experimentais e de controle. As leituras de cada slot são coletadas separadamente, agregadas e tabuladas.



Nos testes A / B, como regra, a média aritmética também é usada. Aqui vemos um delta e, para determinar com precisão se é um acidente ou um resultado significativo, um teste estatístico é aplicado.



É designado como "MW" porque o teste de Mann-Whitney é usado no cálculo. Com sua ajuda, a chamada "porcentagem de correção" é calculada. Este indicador tem um limite, após o qual tomamos o delta como verdadeiro. Aqui é fixado em 99,9%.

Quando o teste atinge esse valor, o delta é destacado na interface. Nós chamamos isso de coloração. Aqui vemos o verde, ou seja, uma boa coloração na hora da primeira tinta cheia de conteúdo. O tempo para a primeira pintura significativa não atingir esse valor, ou seja, o delta também é bom, mas não 99,9%. É completamente impossível confiar nela. Após a inicialização da estrutura e o tempo de interatividade, é observada uma coloração vermelha com confiança ruim. A partir disso, podemos tirar a mesma conclusão que no caso de fontes.



Como fazer você mesmo?


Você pode implementar medições de velocidade de duas maneiras. O primeiro é fazer tudo o que é seu.



Um identificador para receber dados de clientes, um back-end, que coloca tudo isso em um banco de dados, MongoDB, PostgreSQL, MySQL, qualquer DBMS (eles possuem agregações prontas para uso), além de uma das muitas soluções de código aberto - para desenhar gráficos e organizar o monitoramento.

A segunda solução é usar os sistemas de análise Yandex Metric ou Google Analytics. No exemplo das métricas Yandex, é assim.



Aqui estão as métricas que a métrica fornece ao usuário imediatamente. Claro, isso não é tudo o que foi exposto acima, mas já é algo. O restante pode ser adicionado manualmente através das configurações do usuário. Testes e monitoramento A / B também estão disponíveis.

Conclusão


O conceito de medição de velocidade on-line sobre o qual falamos é conhecido como RUM - Real User Monitoring. Nós a amamos tanto que até desenhamos um logotipo com um trema legal de rock and roll.



Essa abordagem é boa porque se baseia em números do mundo real, nos indicadores que o público do seu serviço possui. Usando métricas, você parece receber feedback de cada usuário. Então comece a otimizar e não pare.
O anúncio no final. Se você gostou desta conversa com o HolyJS 2018 Piter , provavelmente estará interessado no próximo HolyJS 2018 Moscow , que será realizado de 24 a 25 de novembro .Lá, você pode não apenas ver muitos outros relatórios JS, mas também perguntar a qualquer orador na área de discussão após o relatório. E amanhã, a partir de 1º de novembro, os preços dos ingressos subirão para a final, então hoje é a última oportunidade de comprá-los com desconto!

Source: https://habr.com/ru/post/pt426571/


All Articles