Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

RSS iMasters

[Resolvido] Desenvolvendo perfis CSS para diversão e lucro - nota

Recommended Posts

Esta é a primeira parte do meu artigo sobre desenvolvimento de perfis em CSS, composto de várias notas sobre a criação de perfis que utilizam o WebKit e as ferramentas do Opera.

?

Estive trabalhando recentemente com a otimização de desempenho de uma aplicação web página única. Ela foi altamente dinâmica, interativa e era fortemente recheada com novo CSS3. Não estou falando só de border-radius e gradientes. Era uma pilha cheia de sombras, gradientes, transformações, polvilhado com transições, cores lisas semitransparentes, truques pseudo-inteligentes baseados em elementos e recursos experimentais do CSS.

 

Além de olhar para gargalos no lado do Javascript/DOM, eu decidi entrar no terreno do CSS. Queria ver o tipo de impacto que esses agradáveis elementos UI têm no desempenho. A versão antiga do aplicativo - o sem frescuras - era muito mais dinâmica, embora a lógica JS por trás dela não tenha mudado drasticamente. Eu podia ver através de scrolling e animações que as coisas não são tão rápidas como deveriam ser.

 

Foi culpa do estilo?

 

Felizmente, apenas alguns dias antes, o pessoal do Opera saiu com um "style profiler" experimental (seguido, logo após, ticket + patch do WebKit). O profiler foi criado para revelar o desempenho do seletor correspondente do CSS, reflow de documento, repaint, e mesmo documento e tempos parsing de CSS.

 

Perfeito!

 

45672.pngEu não estava entusiasmado com a criação de perfis em um ambiente e com a otimização de acordo com um mecanismo (principalmente o mecanismo que é usado apenas em um navegador), mas decidi fazer uma tentativa. Afinal, ofender os estilos/regras provavelmente seria semelhantes em todos os mecanismos/navegadores. E essa era praticamente a única coisa existente lá fora.

 

A outra única ferramenta bastante semelhante foi a "timeline" do WebKit na guia em Ferramentas de Desenvolvimento. Porém, a timeline não era muito amigável para trabalhar. Ela não mostra o tempo total de reflow/repaint/matching seletor, e a única maneira de extrair essa informação foi por exportar dados como JSON e analisá-la manualmente (vou chegar aí mais tarde).

 

Abaixo estão algumas de minhas observações da criação de perfis que utilizam o WebKit e as ferramentas do Opera.

 

Antes de começarmos, gostaria de mencionar que a maioria (se não todas) destas notas se aplica melhor a apps grandes e complexas. Os documentos que possuem milhares de elementos e que são altamente interativos irão se beneficiar a maioria. No meu caso, reduzi sozinho o tempo de carregamento da página para ~ 650ms (~ 500ms (!) apenas no recálculo de estilo, ~~~V 100ms em repaint, e ~ 50ms em reflow). A aplicação tornou-se visivelmente mais dinâmica, especialmente em navegadores mais antigos como o IE7.

Para páginas/apps simples, há uma abundância de outras otimizações que devem ser analisadas primeiro.

 

Notas

1. A regra mais rápida é aquela que não existe. Há uma estratégia comum para combinar módulos de folhas de estilo em um arquivo para a produção. Isso faz uma grande coleção de regras, onde algumas (muitas) delas não são provavelmente usadas por determinada parte do site/aplicação. Se livrar de regras não utilizadas é uma das melhores coisas que se pode fazer para aperfeiçoar o desempenho do CSS, como há menor correspondência a ser feita em primeiro lugar. Há determinados benefícios de ter um grande arquivo, é claro, como o número reduzido de pedidos. Porém deve ser possível aperfeiçoar pelo menos as partes críticas do aplicativo, incluindo apenas estilos relevantes.

 

De qualquer forma, essa não é uma nova descoberta. Page Speed sempre alertou sobre isso. No entanto, fiquei realmente surpreso ao ver o quanto isso pode realmente afetar o tempo de renderização. No meu caso, eu aliminei ~ 200-300ms do selector matching - de acordo com o gerador de perfil Opera - apenas me livrando de regras de CSS não utilizadas. Tempos de Layout e paint também caíram bem.

 

2. Reduzindo reflow - outra otimização conhecida - desempenha um grande papel aqui também. Estilos dispendiosos não são tão caros quando menos reflows/rebuilts precisam ser executados pelo browser. E até mesmo estilos simples poderiam retardar as coisas, se forem muito usados. Reduzir refllows e reduzir da complexidade do CSS andam de mãos dadas.

 

3. Seletores mais dispendiosos e aqueles com múltiplas classes ("foo.bar.", "Foo. Bar.baz qux" etc.) tendem a ser mais universais ("*"). Já sabíamos disso, mas é bom ter a confirmação de profilers.

 

4. Cuidado com os seletores universais ("*") que são usados para ?nenhuma razão". Encontrei seletores como "button> *", embora ao longo dos botões site/app só tinha <span> 's neles. A substituição de "button> *" com "span> button" é feita para algumas melhorias surpreendentes no desempenho seletor. O navegador não precisa associar cada elemento (devido à associação direita-esquerda). Ele só precisa passar por cima de <span> 's - cujo número poderia ser significativamente menor - e verificar se o elemento pai é <button>. Você, obviamente, precisa ter cuidado substituindo "*" com tags específicas, já que é frequentemente difícil de encontrar todos os locais onde esse seletor poderia ser usado.

 

A grande desvantagem dessa otimização é que você perde a flexibilidade, já que alterar a marcação também exigirá mudar o CSS também. Você não será capaz de apenas substituir uma implementação de botão por outra no futuro. Fiquei em dúvida sobre fazer essa substituição, já que, essencialmente, se livrar de abstração útil melhora o desempenho. Como sempre, encontre o compromisso certo para o seu caso, até que os mecanismos comecem a aperfeiçoar esses seletores e não tivermos que nos preocupar com eles.

 

5. Eu usei este trecho de código para localizar rapidamente quais os elementos substituir com "*".

 

$(selector).pluck('tagName').uniq(); // ["SPAN"]

Isso conta com as extensões Array#pluck e Array#uniq do Prototype.js. Uma versão simples (com confiança no ES5 e nos seletores de API) talvez seja algo assim:

Object.keys([].slice.call(

document.querySelectorAll('button > *'))

.reduce(function(memo, el){ memo[el.tagName] = 1; return memo; }, {}));

6. Em ambos Opera e WebKit, seletores [type = "..."] parecem ser mais dispendiosos do que input [type = "..."]. Provavelmente, devido a atributos limitadores de navegadores verificarem elementos de tag especificada (afinal, [type = "..."] é um seletor universal).

 

7. No Opera, pseudos ":: selection" e ": ativa" também estão entre os seletores mais dispendiosos - de acordo com o profiler. Sou capaz de compreender que ?: active" seja dispendioso, mas não sei por que "::selection" é. Talvez o "bug" no profiler/matcher do Opera . Ou apenas a forma como o mecanismo funciona.

 

8. Em ambos Opera e WebKit, o "border-radius" está entre as propriedades mais caras do CSS para afetar o tempo de renderização. Ainda mais do que sombras e gradientes. Observe que isso não afeta o tempo de layout - como se poderia pensar - mas, principalmente, de repaint (recarregar a página já carregada).

 

Como você pode notar a partir desta página de teste, eu criei um documento com 400 botões.

45673.pngComecei verificando como os vários estilos afetam o desempenho de renderização ("repaint time" no profiler do Opera). A versão básica do botão só tinha estes estilos:

background: #F6F6F6;

border: 1px solid rgba(0, 0, 0, 0.3);

font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;

font-size: 14px;

height: 32px;

vertical-align: middle;

padding: 7px 10px;

float: left;

margin: 5px;

45674.png

 

O total do tempo de repaint de 400 botões com esses estilos básico levou apenas 6ms (no Opera). Então, eu gradativamente adicionei mais estilos e gravei mudança no tempo de repaint. A versão final tinha esses estilos adicionais, e estava levando 177 para fazer o repaint - uma melhoria de 30x.

text-shadow: rgba(255, 255, 255, 0.796875) 0px 1px 0px;

box-shadow: rgb(255, 255, 255) 0px 1px 1px 0px inset, rgba(0, 0, 0, 0.0976563) 0px 2px 3px 0px;

border-radius: 13px;

background: -o-linear-gradient(bottom, #E0E0E0 50%, #FAFAFA 100%);

opacity: 0.9;

color: rgba(0,0,0,0.5);

45675.pngO breakdown exato de cada uma dessas propriedades era a seguinte:

45683.png

 

O text-shadow e linear-gradient estavam entre as menos caras. Opacidade e transparent rgba () color estavam um pouco mais caras. Em seguida, estava box-shadow, com uma inserção (0 1px 1px 0) pouco mais rápido do que um normal (0 2px 3px 0). Finalmente, a inesperada elevada border-radius.

 

Também tentei transformar com rotação de parâmetro (apenas 1 grau) e obtive números realmente altos. Rolando a página - com ligeiros 400 botões de rotação - era, ainda, visivelmente irregular. Tenho certeza de que não é fácil transformar arbitrariamente um elemento em uma página. Ou talvez esse seja o caso de falta de otimização? Por curiosidade, verifiquei diferentes graus de rotação e consegui o seguinte:

45681.png

 

Note como mesmo o elemento rotativo de 0,01 graus é muito dispendioso. E à medida que o ângulo aumenta, o desempenho parece cair, embora não de forma linear, mas, aparentemente, de uma forma ondulada (chegando a 45 graus, em seguida caindo a 90 graus).

 

Há espaço para muitos testes aqui - eu estaria curioso para ver as características de desempenho de diferentes opções de transformação (translação, escala, inclinação etc.) em vários navegadores.

 

 

No próximo artigo, as notas finais sobre a criação de perfis que utilizam o WebKit e as ferramentas do Opera.

?

Texto original disponível em http://perfectionkills.com/profiling-css-for-fun-and-profit-optimization-notes/

 

 

 

 

 

http://imasters.com.br/artigo/23955/css/desenvolvendo-perfis-css-para-diversao-e-lucro-notas-de-otimizacao-parte-01

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.