Tableless

Busca Menu

Medindo performance e latência com a Navigation Timing API

Seja o primeiro a comentar por

Performance e latência são alguns dos requisitos de qualidade e experiência do usuário mais desafiadores em desenvolvimento web, especialmente quanto à performance client-side.Sabemos como aplicar técnicas que melhoram muito a performance da página, mas medir o desempenho adequadamente já não é tão trivial à nossa rotina de desenvolvimento. Pensando nisso, o W3C tem uma nova recomendação chamada Navigation Timing API. Com isso, é possível obter métricas e estatísticas detalhadas de modo nativo sobre tempo de carregamento, navegação entre páginas e carregamento de eventos.

A vantagem desta API sobre ferramentas externas e outras técnicas de aferição de latência via JavaScript é a quantidade de informações que podem ser obtidas sobre o tempo de carregamento da página em diferentes fases, proporcionando a medição em um escopo maior (end-to-end). Ferramentas como o PageSpeed e o WebPageTest já têm utilizado dados da Navigation Timing API na análise de carregamento de páginas.

Suporte

Até o momento da escrita deste artigo, a Navigation Timing é suportada pelo Chrome 24.0+, Firefox 18.0+ e IE 9+. A especificação já é recomendação do W3C desde dezembro de 2012 e a versão 2 da API já está em desenvolvimento.

Utilizando o objeto window.performance

Os parâmetros de carregamento da página são acessados através das propriedades navigation e timing do objeto [window.]performance. A propriedade navigation contém informações sobre como o usuário chegou à página e a propriedade timing apresenta as informações sobre carregamento da página.

É possível testar o window.performance diretamente no console do navegador. Supondo que estamos utilizando o Chrome, basta abrir a Developer Tools > Console e digitar performance no prompt. Abaixo, um exemplo do que você poderá obter. Note que o Chrome adiciona mais uma propriedade chamada memory, que pode ser acessada pelo performance.memory, apresentando informações sobre a utilização de memória pelo JavaScript.

Detalhes das propriedades do Navigation Timing API

Detalhes das propriedades do Navigation Timing API

Cada uma destas propriedades do timing expressa o tempo de um determinado evento em milisegundos a partir das 00:00 do dia 1º de Janeiro de 1970 (UTC). Quando o valor de algum dos atributos é zero, significa que este evento não ocorreu.

Os tipos de navegação ou “como cheguei até esta página?”

A window.performance.navigation armazena dois atributos que pode ser utilizados para detectar como o usuário chegou à página atual, por exemplo, via um redirecionamento, botões de navegação do histórico do navegador ou entrada normal por URL na barra de endereço. Os atributos são:

  • redirectCount: o número de redirecionamentos que ocorreram até que a página final fosse carregada;
  • type: a forma como o usuário chegou à página.

O atributo type é uma constante do tipo enumerada e pode apresentar os seguintes valores:

Constante Valor Descrição
TYPE_NAVIGATENEXT 0 Navegação iniciada por click em um link, entrada de URL na barra de endereço do navegador, submissão de formulário ou por uma operação de script.
TYPE_RELOAD 1 Recarregamento de página (por botão de refresh ou location.reload()).
TYPE_BACK_FORWARD 2 Navegação através dos botões de avançar/voltar do navegador ou por operações de navegação no histórico através de script (ex.: history.back()).
TYPE_UNDEFINED 255 Qualquer tipo de navegação que não se enquadre nos valores acima.

Os atributos de tempo de carregamento

A propriedade window.performance.timing armazena os dados relevantes sobre o tempo de carregamento desde o momento em que o navegador dispara a requisição para obter a página até o momento em que o carregamento de todo o documento é finalizado. A tabela abaixo mostra uma breve descrição destes eventos na ordem em que eles ocorrem:

Estágio Atributo Descrição

Rede

navigationStart Tempo depois de o documento anterior ter iniciado o evento de unload.
unloadEventStart Tempo imediatamente antes do evento de unload ser disparado.
unloadEventEnd Tempo após o documento anterior ter completado o unload, ou seja, ter sido descarregado para que o próximo documento seja carregado.
redirectStart Tempo da busca que iniciou o redirecionamento.
redirectEnd Tempo após a ocorrência do último redirecionamento.
fetchStart Tempo em que o recurso começa a ser buscado.
domainLookupStart Tempo imediatamente antes de iniciar a resolução de nome do domínio.
domainLookupEnd Tempo após finalizar a resolução de nome do domínio.
connectStart Tempo imediatamente antes de iniciar a conexão com o servidor para solicitar o recurso.
connectEnd Tempo em que a conexão com o servidor é finalizada.
secureConnectionStart Para os browsers onde este atributo existe (o IE não o possui no momento), ele retorna o tempo em que foi iniciada uma conexão HTTPS.

Servidor

requestStart Tempo imediatamente antes da requisição do documento ao servidor.
responseStart Tempo imediatamente após o recebimento do primeiro byte de resposta do servidor.
responseEnd Tempo após a finalização da resposta (recebimento do último byte) ou conexão com o servidor.

Browser

domLoading Tempo em que o status do documento passa a ser “loading”.
domInteractive Tempo em que o status do documento passa a ser “interactive” (DOM completamente interpretado pelo parser do user agent).
domContentLoadedEventStart Tempo em que o evento DOMContentLoaded é disparado no documento.
domContentLoadedEventEnd Tempo após finalizar o evento DOMContentLoaded.
domComplete Tempo em que o status do documento passa a ser “complete”. O status “complete” difere do “interactive” pois engloba a execução de scripts.
loadEventStart Tempo em que inicia a execução do evento de load da página.
loadEventEnd Tempo em que finaliza a execução do evento de load da página.

Conforme a developer Kasia explica em um artigo de seu blog, os eventos de Rede envolvem tudo que acontecem antes do browser enviar a requisição do documento e pode ajudar a medir latência de rede; os eventos de Servidor são referentes aos tempos de requisição e resposta do documento, ajudando a medir quanto tempo o servidor leva para processar a página; por fim, os eventos do Browser ocorrem a partir do momento que o documento é criado até o momento em que o evento de onload é disparado, auxiliando a medir de fato a performance client-side.

Na timeline abaixo, retirada da documentação da API, é possível ver o fluxo de execução destes eventos.

 

Modelo de Processo da Navigation Timing API

Modelo de Processo da Navigation Timing API

Como utilizar todos estes dados para extrair as informações que nos interessam?

Depois de toda esta fundamentação teórica, chegamos de fato no ponto que nos interessa, o pulo do gato: como utilizar estes dados para obter as métricas de performance. Geralmente, a forma de obter estas informações se dá pelo cálculo da diferença entre alguns atributos.

Compilando alguns exemplos apresentados pelo Sam Dutton do HTML5Rocks, Colin Ihrig do SitePoint e a documentação de JS da Mozilla, temos as seguintes combinações (mas é possível obter muito mais):

Informação Cálculo
Tempo total de latência de rede responseEnd – fetchStart
Tempo de carregamento da página a partir do momento que a página é retornada do servidor loadEventEnd – responseEnd
Tempo total de carregamento da página loadEventEnd – navigationStart
Tempo de resposta a uma requisição feita ao servidor responseEnd – requestStart
Tempo de redirecionamento redirectEnd – redirectStart
Tempo de resolução do DNS domainLookupEnd – domainLookupStart
Tempo de conexão com o servidor connectEnd – connectStart

Acrescento também alguns testes que fiz com outros cálculos:

Informação Cálculo
Tempo para renderizar o DOM (realizar a interpretação – parser – de todo o HTML) domInteractive – domLoading
Tempo total para carregar a página, incluindo a requisição de todos os arquivos externos, principalmente scripts domComplete – domLoading
Tempo de carregamento de scripts no evento onload loadEventEnd – loadEventStart

Exemplos

No site Web Timing Demo é possível ter uma prévia de como estes dados podem ser visualizados graficamente. Além disso, a aplicação mostra o valor de todas as propriedades da window.performance para aquela página.

Outra aplicação mais completa é o bookmarket desenvolvido pela Kasia, citada anteriormente neste artigo. Basta arrastá-lo para a barra de favoritos do browser e clicar nele em qualquer página que deseja analisar.

Referências e mais recursos

Can I Use… Navigation Timing API. Disponível em: http://caniuse.com/#feat=nav-timing

Colin Ihrig. Profiling Page Loads with the Navigation Timing API. Disponível em: http://www.sitepoint.com/profiling-page-loads-with-the-navigation-timing-api/

Internet Explorer Developer Center. Navigation timing (Windows). Disponível em: http://msdn.microsoft.com/en-us/library/ie/hh673552(v=vs.85).aspx

Kasia Drzyzga. Breaking Down OnLoad Event – Performance Bookmarklet. Disponível em: http://66.7percentangel.com/2011/12/breaking-down-onload-event-performance-bookmarklet/

Leigh Shevchik. It’s All in the Timing: How to Use the Navigation Timing Specification to Improve Web Performance. Disponível em: http://blog.newrelic.com/2012/05/16/its-all-in-the-timing-how-to-use-the-navigation-timing-specification-to-improve-web-performance/

Microsoft MSDN. performanceTiming object. Disponível em: http://msdn.microsoft.com/en-us/library/ff975075

Mozilla Developer Network. Navigation Timing. Disponível em: https://developer.mozilla.org/en-US/docs/Navigation_timing

Sam Dutton. Measuring Page Load Speed with Navigation Timing. Disponível em: http://www.html5rocks.com/en/tutorials/webperformance/basics/

W3C. HTML5: A vocabulary and associated APIs for HTML and XHTML. Disponível em: http://www.w3.org/TR/html5/syntax.html

W3C. Navigation Timing. Disponível em: http://www.w3.org/TR/navigation-timing/

 

Publicado no dia