Tempos de exibição de CSS e peso de renderização da página

Introdução

Se você é do tipo de pessoa que acompanha coisas como como os navegadores funcionam, já sabe que há alguns artigos incríveis detalhando a operação de renderização/composição acelerada por GPU do Chrome. Em primeiro lugar, Renderização acelerada no Chrome: o modelo de camadas é uma ótima introdução sobre como o Chrome usa o conceito de camadas para desenhar a página. Para uma análise mais detalhada, Composição acelerada por GPU no Chrome discute como o Chrome usa essas camadas, junto com a GPU para renderizar sua página.

A pergunta filosófica

Depois de passar muito tempo escrevendo rasterizadores de software para fins 3D, ficou claro para mim que algumas propriedades do CSS precisam ter uma performance variada ao desenhar a página. Por exemplo, rasterizar uma imagem pequena na tela é uma operação algorítmica completamente diferente que desenha uma sombra projetada em uma forma arbitrária. A pergunta passou a ser: Como as diferentes propriedades do CSS afetam o peso de renderização da sua página?

Meu objetivo era categorizar um grande conjunto de propriedades/valores CSS pelos tempos de pintura, para que possamos entender quais tipos de propriedades CSS têm mais desempenho do que outros. Para fazer isso, criei uma automação com fita adesiva e chiclete para tentar adicionar visibilidade numérica aos tempos de pintura do CSS, que funcionou assim:

  • Gerar um conjunto de páginas HTML individuais, cada uma com um único elemento DOM e algumas permutações de propriedades CSS anexadas a ele.
  • Execute um script de automação que, para cada página, vai:
    • Abrir o Chrome
    • Carregar uma página
    • Produza uma imagem Skia para a página.
    • Execute cada imagem do Skia tirada pelo Skia Benchmark para receber os tempos.
  • Descarte todos os tempos e se surpreenda com os números. (Esta parte é importante…)

Com essa configuração, geramos um conjunto de páginas HTML, em que cada página contém uma permutação exclusiva de propriedades e valores CSS. Por exemplo, confira estes dois arquivos HTML:

<style>
#example1 {
    background: url(foo.png) top left / 50% 60%;
    padding: 20px; 
    margin-top: 10px;
    margin-right: 20px; 
    text-align: center;
}
</style>
<div id="example1">WOAH</div>

E outra, mais complexa

<style>
#example1 {
    background-color:#eee;
    box-shadow: 1px 2px 3px 4px black;
    border-radius: 50%;
    background: radial-gradient(circle closest-corner, white, black);
    padding: 20px; 
    margin-top: 10px;
    margin-right: 20px; 
    text-align: center;
}
</style>
<div id="example1">WOAH</div>

Confira abaixo uma variante do último exemplo, em que mudamos apenas o valor de radial-gradient:

<style>
#example1 
{
    background-color:#eee;
    box-shadow: 1px 2px 3px 4px black;
    border-radius: 50%;
    background: radial-gradient(farthest-side, white, black);
    padding: 20px; 
    margin-top: 10px;
    margin-right: 20px; 
    text-align: center;
}
</style>
<div id="example1" style="padding: 20px; margin-top: 10px;margin-right: 20px; text-align: center;">WOAH</div>

Cada página é carregada em uma instância nova do Chrome para garantir que os tempos não sejam enviesados por estados desatualizados em recarregamentos de página. Além disso, uma imagem Skia (*.SKP) é usada para avaliar quais comandos Skia são usados para pintar a página. Depois que os arquivos SKP forem gerados para cada arquivo HTML, executamos outro lote para enviar os arquivos *.SKP pelo aplicativo Skia Benchmark (criado com o código-fonte do Skia), que descarta o tempo médio necessário para renderizar essa página.

Como avaliar os dados

Com isso, agora temos a capacidade aproximada de registrar o tempo que um conjunto de propriedades CSS leva para ser renderizado. Ou seja, podemos começar a classificar as propriedades do CSS de acordo com a performance de pintura. Este é um gráfico grande feito com o Chrome 27 Beta mostrando todos os dados de tempo desse processo. Todos os dados estão sujeitos a mudanças à medida que o Chrome fica mais rápido com o tempo.

Tempos de todas as permutações no teste

Cada barra vertical representa o tempo de pintura de uma página com uma única combinação de propriedades CSS (ampliada em 100x; o valor real da escala deste gráfico é 0,1.56ms). Muitas linhas bonitas, mas, nesse formato, são inúteis. Precisamos fazer mineração de dados para encontrar tendências úteis.

Primeiro, encontramos provas de que algumas propriedades do CSS são mais caras para renderizar do que outras. Por exemplo, desenhar uma sombra projetada em um elemento DOM envolve uma operação de várias passagens com splines e outros tipos de coisas desagradáveis, em vez de opacidade, que é mais fácil de renderizar.

Tempo gasto para pintar um elemento que tem apenas uma propriedade CSS

Em segundo lugar, e mais interessante, combinações de propriedades CSS podem ter um tempo de pintura maior do que a soma das partes. Do ponto de vista de um observador, isso é um pouco estranho.Esperaríamos que A+B = C, não 2, 2C. Por exemplo, adicionar box-shadow e border-radius-stroke :

Tempos de todas as permutações no teste

O que é realmente interessante é que não é apenas a propriedade box-shadow, mas sim essa permutação de valor específica. Por exemplo, abaixo mostra um agrupamento de box-shadow : 50% e border-radius com variações de valor.

Tempos de todas as permutações no teste

Analisando os dados, isso continua por um tempo. Há muitas combinações estranhas, e meu conjunto de testes mal as toca. Ainda há muitos testes e combinações que podem gerar resultados interessantes.

Como encontrar o peso de renderização da página

Com a capacidade de rastrear os tempos de renderização de cada elemento na página, os desenvolvedores podem começar a avaliar o peso de renderização da página e como ele afeta a capacidade de resposta do site. Confira algumas dicas para começar.

  1. Use o modo de pintura contínua do Chrome nas Ferramentas para desenvolvedores do Chrome para entender quais propriedades CSS estão custando.
  2. Incorpore as revisões do CSS ao seu processo de revisão de código para detectar problemas de desempenho. Procure no CSS lugares em que você está usando recursos que são conhecidos por serem mais caros, como gradientes e sombras. Pergunte a si mesmo: "Eu realmente preciso disso aqui?"
  3. Em caso de dúvida, sempre opte pela melhor performance. Talvez os usuários não se lembrem da largura do padding nas colunas, mas vão se lembrar de como é visitar seu site.

Considerações finais

Uma das coisas mais interessantes sobre esse experimento é que os tempos vão continuar mudando com cada versão do Chrome (espero que se tornem mais rápidos ;). O software do navegador é uma área de superfície em constante mudança. O que é lento hoje pode ser rápido amanhã. Você pode evitar colocar box-shadow: 1px 2px 3px 4px em um elemento que já tem border-radius:5. No entanto, a conclusão mais valiosa é que as propriedades CSS afetam diretamente os tempos de pintura da página.

Referências