Introdução
Se você é o tipo de pessoa que acompanha coisas como o funcionamento dos navegadores, já sabe que recentemente foram publicados alguns artigos incríveis detalhando a operação de renderização/composição acelerada por GPU do Chrome. Primeiro, Accelerated Rendering in Chrome: The Layer Model (em inglês) é uma ótima introdução sobre como o Chrome usa o conceito de camadas para desenhar a página. Para uma investigação mais detalhada, GPU Accelerated Compositing in Chrome (em inglês) discute como o Chrome usa essas camadas, além da GPU, para renderizar a 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 CSS deveriam ter um desempenho variado ao renderizar sua página. Por exemplo, rasterizar uma imagem pequena na tela é uma operação algorítmica completamente diferente de desenhar uma sombra projetada em uma forma arbitrária. Então, a pergunta é: como as diferentes propriedades de CSS afetam o peso de renderização da sua página?
Meu objetivo era categorizar um grande conjunto de propriedades/valores de CSS pelos tempos de pintura, para que possamos entender quais tipos de propriedades de CSS têm melhor desempenho do que outras. Para fazer isso, escrevi uma automação com fita adesiva e chiclete para tentar adicionar visibilidade numérica aos tempos de pintura do CSS, que funcionou assim:
- Gere um conjunto de páginas HTML individuais, cada uma com um único elemento DOM e alguma permutação 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
- Produzir uma imagem Skia para a página
- Execute cada imagem do Skia tirada pelo Skia Benchmark para conferir os tempos.
- Despeje todos os tempos e se maravilhe 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, aqui estão 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 outro, mais complexo,
<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>
Abaixo, como uma variante do último exemplo, em que mudamos apenas o valor do gradiente radial:
<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 influenciados por estados desatualizados em recarregamentos de página), e uma Skia Picture (*.SKP) é tirada para avaliar quais comandos do Skia são usados para pintar a página. Depois que os arquivos SKP são gerados para cada arquivo HTML, executamos outro lote para enviar os arquivos *.SKP pelo aplicativo Skia Benchmark (criado com base no código-fonte do Skia), que mostra o tempo médio de renderização da página.
Como avaliar os dados
Com isso, agora temos uma capacidade aproximada de traçar quanto tempo um conjunto de propriedades CSS leva para ser renderizado. Ou melhor, podemos começar a classificar as propriedades CSS pelo desempenho de pintura. Veja um gráfico grande feito com o Chrome 27 Beta que mostra todo o conjunto de dados de tempo desse processo. Todos os dados estão sujeitos a mudanças, já que o Chrome fica cada vez mais rápido com o tempo.
Cada barra vertical representa o tempo de pintura de uma página com uma única combinação de propriedades CSS (ampliada em 100 vezes; o valor de escala real desse gráfico é de 0 a 1,56 ms). Muitas linhas bonitas, mas, dessa forma, é um pouco inútil. Precisamos fazer uma mineração de dados para encontrar tendências úteis.
Primeiro, encontramos provas de que algumas propriedades CSS são simplesmente 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, ao contrário da opacidade, que é mais fácil de renderizar.
Em segundo lugar, e mais interessante, as 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.Esperamos que A+B = C, não 2, 2C. Por exemplo, adicionando box-shadow e border-radius-stroke :
O mais interessante é que não é apenas a propriedade box-shadow em si, mas sim aquela permutação de valor específica. Por exemplo, abaixo mostramos um agrupamento de box-shadow : 50% e border-radius com variações de valor.
Analisando os dados, isso continua por um tempo. Há muitas combinações estranhas, e meu pacote de testes mal toca em todas elas. 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 acompanhar os tempos de renderização de cada elemento na página, os desenvolvedores podem começar a avaliar o peso da renderização da página e como isso afeta a responsividade do site. Confira algumas dicas para começar:
- Use o modo de pintura contínua nas Ferramentas para desenvolvedores do Chrome para entender quais propriedades CSS estão custando mais.
- Incorpore revisões de CSS ao seu processo de revisão de código para detectar problemas de desempenho. Procure lugares no CSS em que você está usando elementos que são conhecidos por serem mais caros, como gradientes e sombras. Pergunte-se: eu realmente preciso disso aqui?
- Em caso de dúvida, sempre priorize o melhor desempenho. Seus usuários podem não se lembrar da largura do padding nas colunas, mas vão se lembrar da experiência de 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 (esperamos que fiquem 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 usar este artigo para evitar colocar box-shadow: 1px 2px 3px 4px em um elemento que já tem border-radius:5. No entanto, o mais importante é que as propriedades CSS afetam diretamente os tempos de pintura da página.