3 Dicas de performance de CSS

O primeiro passo para se discutir a performance da renderização das páginas no navegador é entender como o navegador funciona.

Antes de continuar você deve entender os conceitos de browser reflow e browser repaint, pois nosso objetivo para ter uma página renderizada mais rapidamente é a redução dos reflows e repaints da página.

Como o navegador interpreta o CSS?

O navegador começa a leitura do CSS da direita para a esquerda, do nosso último elemento para o primeiro. Ele pega o seletor bem da direita, percorre todos os elementos do DOM que casem com este seletor e passar para o próximo seletor a esquerda, verificando os parents do seletor que ele verificou anteriormente (o bem da direita na sua linha de seletores).

Parece confuso mas na prática é simples. Para o código abaixo, por exemplo:

#content #menu ul li a

O navegador vai varrer todos os elementos "a" da sua página, depois ele vai verificar quais destes elementos estão dentro de um elemento li e assim por diante até encontrar o elemento #content.

Agora que você já sabe como o navegador trabalha vamos as dicas de CSS para páginas rápidas!

 

1. Escreva seletores curtos

Agora que você já sabe como o navegador percorre o seu seletor, já sabe quanto mais curto ele for menos será o caminho percorrido e consequentemente mais rápida a renderização da sua página.

Evite

#content nav#menu ul li a

 

Melhor performance CSS

.menu-item

 

Outro exemplo, em uma página com bastante conteúdo tabular:

Evite

table thead tr td

 

Melhor performance CSS

.header-table

 

2. Prefira classes e ids do que seletor por elemento

Quanto mais preciso seu seletor for menos elementos do DOM serão percorridos pelo browser, o seletor de tag tende a ser mais abrangente do que seletor de classe.

Evite 

h2.product-title

Melhor performance CSS

.product-title

 

Evite

nav#menu

Melhor performance

#menu

O navegador não precisa fazer 2 verificações para estilizar os elementos casados com a classe.

 

3. Evite seletor universal, por atributo e pseudo-selectors

Principalmente no IE evite os pseudo seletores como :hover, :nth-child e outros. O seletor universal percorre todos os elementos do DOM (por isso a baixa performance) e os pseudo seletores tem uma performance bem inferior do que qualquer seletor por classe ou id, então sempre que for possível evite seu uso.

Evite:

input[type="text"]

Não tão ruim:

input.texto

Melhor performance CSS:

.input-texto

 

Dica bônus: não enlouqueça

Não seja um paranóico, não deixe que as preocupações com performance de CSS prejudiquem (muito) a organização e leitura do seu código.

Se você trabalha em projetos com uma equipe grande em que todos estão acostumados a escrever seletores descritivos (e compridos) para facilitar o entendimento do código pode ser um pouco complicado fazer esta mudança, uma boa dica é estimular comentários no CSS – qualquer processo de minify arrancará os comentários e manterá o código enxuto.

 

Para saber mais sobre performance no front-end veja este post sobre performance de javascript e o recente post do Chris sobre manipulação do DOM de forma mais performática.

Se está na dúvida (ou não acredita no que escrevi), utiliza esta ferramenta para testar a performance de seletores CSS.

 

Referências:

Melhorando a performance do CSS

Escrevendo CSS eficiente

Google best pratices rendering

Mozilla – Writting effective CSS

Simplifying CSS selectors

Criar elementos no DOM com DocumentFragment

O uso do DocumentFragment para criação de nós no DOM é muito importante no que diz respeito a performance do seu javascript, quando é necessário fazer a inserção de vários elementos de uma vez só.

DocumentFragment é um container para nós DOM, que  pode receber elementos e depois ser adicionado (através do método appendChild) a um nó. O benefício se dá tanto na performance do script (como veremos logo mais, e também pode ser visto nesse post do John Resig) como na renderização da página (reflow e repaint) no browser, uma vez que ao invés de ter que adicionar n elementos, um a um, eles são adicionados de uma vez só.

Abaixo tem um trecho de código usando o DocumentFragment, exemplificando o uso:

var div = document.getElementById("minha_div"); //passo 1
var
fragment = document.createDocumentFragment();
for(var i=0; i<100; i++) {
 var d = document.createElement("p");
 fragment.appendChild(d); //passo 2
}
div.appendChild(fragment); //passo 3

O uso é bem simples: deve-se criar um DocumentFragment, atribuindo a uma variável (passo 1), então para cada elemento criado esse elemento é adicionado ao documentFragment (passo 2) e, por final, se adiciona o DocumentFragment ao element que será o container desses nós no DOM.

Aqui http://jsfiddle.net/chrisbenseler/RQ28C/ tem um teste comparando a criação com e sem DocumentFragment; para criar 5000 elementos

e adicionar a uma div, com DocumentFragment o browser (Firefox 14.0.1 do Ubuntu) leva em média 230 milisegundos; já sem, 330 milisegundos.

Dicas: jQuery performance

Duas coisas que todo o bom desenvolvedor deve se preocupar: segurança e performance.

Comecei a me preocupar e estudar mais a fundo performance em PHP quando passei a ter problemas com o crescimento do And After, para isso desenvolvi um sistema de cache inteligente utilizando o cache do Code Igniter, que aumentou muito a performance de entrega das páginas – e mesmo assim tem muito que pode melhorar.

Performance no front-end

Com a reduação dos custos computacionais (cloud, balance e servidores mais acessíveis) os problemas de processamento do backend muitas vezes são resolvidos com o "liga mais máquina", mas os problemas de performance no front-end são sentidos pelo usuário – e não temos controle sobre o computador do usuário.

A redução do custo do acesso a internet banda larga (internet 1Mb a R$35,00) permite que carreguemos mais código e imagens com mais qualidade sem prejudicar muito a entrega, mas ainda temos dois pontos principais de otimização de sites front-end que independem de banda ou do servidor:

  1. Renderização do código
  2. Performance do javascript

A forma e ordenação de como o HTML é escrito definem como ele será renderizado – e cada browser fará isso de uma forma, por isso é muito importante seguir as boas práticas e recomendações da W3C para estar preparado para o futuro, e não preso aos navegadores do passado.

Assim como o html, cada navegador tem a sua forma (ou engine) para lidar com javascript, o que diferencia muito a performance de algumas funções em um navegador ou outro – achar a forma que atende melhor seus usuários (sem ficar preso a navegadores velhacos) é o que eu vejo como melhor opção.

Se você quer entender um pouco mais sobre javascript recomendo a leitura dos slides sobre performance em javascript que postei anteriormente, os slides deste post tratam exclusivamente da biblioteca jQuery.

jQuery performance

Os slides abaixo apresentam diversos testes de performance com a biblioteca jQuery, em diversos navegadores. 

 

Uma boa forma de mensurar e testar seu código é criando uma rotina de testes de performance, que pode ser usando alguma biblioteca (ainda não usei para teste de performance) e o "modo macho", criando um cronômetro em javascript e marcando o tempo de execução de loops com cada função que você quer testar.

Performance – preciso me preocupar tanto?

Este post surgiu quando eu ia publicar aqui a apresentação Extreme Javascript Performance, do autor do script.aculo.us, Thomas Fuchs. O post é mais amplo, não trata de javascript e nem do código em si, mas sim da importância (ou não) de levar em consideração possíveis problemas de performance que poderão causar problemas no futuro.

Quando comecei a "programar"¹ eu não ligava muito para performance. Ok, eu não ligava nem um pouco. 

Motivos que levam um desenvolvedor (noob) não ligar para performance:

  • Ele não sabe bem o que está fazendo
  • A aplicação terá poucos usuários (sobra de recursos)
  • Eventuais problemas de performance não vão causar prejuízo financeiro
  • Pensamento POG: funcionou, deixa assim

Pois bem, guri novo que era, tinha os 4 elementos que precisava para fazer cagada. E obviamente fazia. Fiz meu primeiro blog em PHP, funcionava, postava, subia imagem… o código era uma porcaria, mas funcionava.

 Fazer bem feito...

Fazer bem feito para fazer só uma vez, né?

 

Performance – porque se preocupar?

Com o tempo cresci (apenas no modo de pensar e programar, na altura quem me conhece sabe: nada.), aprendi coisas novas e coisas que eu já deveria saber, brinquei fazendo "mini-serviços", desenvolvi o And After e testei e produzi uma ferramenta que inicialmente era só para o And After mas acabei abrindo e foi utilizada por centenas de publishers – a Vitrine Fácil.

Nesta época eu já dava importância para performance, código bem escrito, mas ainda faltava experiência de gerenciar de "cabo a rabo" uma aplicação que fosse utilizada por diversos usuários, e eu tinha uma tremenda inexperiência com uma coisa importantíssima quando se fala de performance: cache.

Mas mais do que aprender como melhorar performance (isso a gente aprende programando e lendo, mas as vezes "esquece") eu aprendi os motivos para se preocupar com performance dos nosso códigos. E segue uma listinha:

  • Downtime custa CARO quando a ferramenta é lucrativa
  • Downtime suja o nome do serviço (lembram do No Donut for you?)
  • Se o sistema/aplicativo for bom ele terá usuários
  • Você não pode freiar o crescimento do sistema (é o mesmo que freiar os lucros)
  • Muitas vezes é impossível prever o crescimento

 

Como melhorar a performance do código?

Já que optei neste post por não tratar de nenhuma linguagem específica, para alguns leitores as dicas podem ficar uma coisa superficial, mas espero que de alguma forma ajudem na forma de um guia inicial para começar a se preocupar com performance…

  • Cache é importante
  • Estude e domine a linguagem que está utilizando (siga as boas práticas recomendadas)
  • Acompanhe o crescimento do seu serviço / site
  • Realize testes de stress no servidor
  • Monitore "de perto" como está o seu servidor (consumo)
  • Lembre-se denovo: cache é importante
  • Verifique: é necessário otimizar? Não vai prejudicar a manutenção do código ou o desenvolvimento de novas features?

 

Cada caso é um caso, otimizar é importante e pode fazer você economizar com servidor porém não deve lhe causar muita dor de cabeça na hora de fazer uma alteração ou aumentar as funcionalidades do sistema… 😉

Recomendo um posto do meu xará, Guilherme Chapiewski: A falácia da otimização prematura, que aborda a célebre frase “A otimização prematura é a raiz de todo o mal” – e muitas vezes não é bem assim.

 

E você, se preocupa com performance? Discorda do que foi dito acima? Concorda?

Comente, gostaria de saber opiniões dos leitores também 😀

 


¹ As aspas são para indicar um fato simples e que não precisa de maiores explicações: comecei a programar sozinho, like a noob.

Extreme JavaScript performance

Faz algum tempo que comecei a escrever sobre performance no javascript, como introdução a uma apresentação de slides deste neste post, mas achei que o assunto era bastante pano pra manda e resolvi repartir as coisas.

Comecei a escrever tanto sobre a importância de alguns cuidados com perfomance que o post deixou de ser direcionado a Javascript e se tornou um relato da minha curta experiência com cuidados com performance – backend e frontend. Meu post inicial virou um rascunho para um post que sairá em breve: Performance – preciso me preocupar *tanto*? –  linko-o aqui quando publicar.

Voltando ao Javascript, nunca me preocupei tanto com questões de performance no Javascript – pois não fazia coisas muito complexas até um tempo atrás, e sempre me preocupei mais com questões de performance no backend.

Porém quando a aplicação é maior e você precisa manipular bastante interface, informações e tem interação direta com o usuário acaba percebendo que você já tem diversas classes e todas elas precisam funcionar perfeitamente para não comprometer o funcionamento de nada. Não se preocupar com performance neste caso é perigoso, errado, chato bobo e feio.

Thomas Fuchs (o ninja autor do script.aculo.us) realizou uma série de testes comparando métodos de executar uma mesma ação no JavaScript, e fez isso em quatro navegadores: Firefox, Internet Explorer, Ópera e Chrome.

Javascript ninja

Javascript ninja

A apresentação respondeu algumas curiosidades e dúvidas, mostrando qual a forma mais performática de executar um loop, um contador, criar arrays e objetos, declarar variáveis, etc…

 

 

Achei a apresentação e testes realizados bem legais, dá para entender melhor e – na medida do possível – alterar o método de desenvolver para uma forma mais performnática.

Compreendo e concordo que performance não é tudo, pois alguns dos métodos mais performáticos não são os mais produtivos – como por exemplo evitar chamar funções dentro de funções.

Mas de qualquer forma, pensar em performance – e endender um pouco melhor como nossos precioso script vai ser interpretado sempre é interessante!