Uma parte importante do ciclo de desenvolvimento da Microsoft é ajustar o desempenho do produto. O ajuste de desempenho também é uma das principais áreas às quais os desenvolvedores devem prestar atenção. Após anos de desenvolvimento, a indústria aprendeu muito sobre como otimizar o desempenho dos programas Win32.
Um dos problemas que os desenvolvedores enfrentam hoje é que eles não entendem muito bem o que faz com que as páginas DTHML e HTML sejam executadas de forma rápida ou lenta. Claro, existem algumas soluções simples – como não usar imagens de 2 MB. Usamos algumas outras técnicas interessantes para melhorar o desempenho de páginas DHTML. Esperamos que elas possam ajudá-lo a melhorar o desempenho de suas próprias páginas.
Aqui utilizo um exemplo de programa para criar uma tabela. Os métodos document.createElement() e element.insertBefore() são usados para criar uma tabela com 1000 linhas (Row). Cada linha possui uma coluna (Célula). O conteúdo contido na Célula é denominado “Texto”. Quão ruim esse código poderia ser? Quanto espaço para ajustes um programa tão pequeno tem? Por favor, veja a introdução.
No início, escrevi um programa que achei que seria rápido. Tentei evitar alguns problemas de baixo nível, como não definir variáveis explicitamente ou usar VBScript e JavaScript ao mesmo tempo em uma página. O programa é o seguinte:
<html>
<corpo>
<roteiro>
var tbl, tbody, tr, td, texto, i, max;
máx = 1000
tbl = document.createElement("TABELA");
tbl.border = "1";
tbody = document.createElement("TBODY");
tbl.insertBefore(tbody, null);
document.body.insertBefore(tbl, null);
para (i=0; i<máx; i++) {
tr = document.createElement("TR");
td = document.createElement("TD");
texto = document.createTextNode("Texto");
td.insertBefore (texto, nulo);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
</script>
</body>
</html>
Execute este programa em uma máquina PII233/64MB de memória/NT4.0/IE5.0. A página é carregada desta máquina. O tempo desde o início do carregamento da página até o silêncio completo da página (todos os eventos foram executados e a exibição da tela foi concluída) é de 2.328 milissegundos, que também é a linha de base deste teste (eu o chamo de Teste1).
Nesta página, uma operação muito demorada é fazer referência frequente a objetos globais, como "documento", "corpo", "janela", etc. Fazer referência a todas essas variáveis globais semelhantes é muito mais caro do que fazer referência a uma variável local.
Então fiz a primeira tentativa de melhoria: cache (Cache) document.body na variável local "theBody":
adicionei o seguinte código:
var theBody = document.body;
Em seguida, modifique esta linha:
document.body.insertBefore(tbl, null);
Mude para:
theBody.insertBefore(tbl, null);
Veja a segunda amostra.
Esta modificação não afetou muito o tempo geral, apenas encurtou 3 ms. Mas foi demonstrado que se também houver um objeto document.body no loop e sua referência for modificada, os benefícios serão consideráveis.
Posteriormente, armazenei em cache o objeto de documento - em nosso teste, o objeto de documento foi referenciado um total de 3.002 vezes. O código modificado é o seguinte:
<html>
<corpo>
<roteiro>
var tbl, tbody, tr, td, texto, i, max;
máximo = 1000;
var theDoc = documento;
var theBody = theDoc.body
tbl = theDoc.createElement("TABELA");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
para (i=0; i<máx; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
texto = theDoc.createTextNode("Texto");
td.insertBefore (texto, nulo);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
</script>
</body>
</html>
Veja a terceira amostra.
Esse tempo de execução é de apenas 2.100 ms, economizando cerca de 10% do tempo. Usar variáveis locais em vez de fazer referência direta ao objeto do documento economizou em média 0,4 milissegundos de cada vez.
Uma maneira comum de otimizar o desempenho é definir o atributo "defer" na tag <SCRIPT> quando o script não precisar ser executado imediatamente. (O script imediato não está contido em um bloco de função, portanto será executado durante o processo de carregamento.) Depois de definir o atributo "defer", o IE não precisa esperar que o script seja carregado e executado. Dessa forma a página carregará mais rápido. De modo geral, isso também significa que os scripts imediatos são melhor colocados em blocos de função e manipulam a função no manipulador onload do documento ou objeto de corpo. Esta propriedade é útil quando existem alguns scripts que precisam ser executados com base nas ações do usuário - como clicar em um botão ou mover o mouse para uma determinada área. Mas quando há alguns scripts que precisam ser executados durante ou após o carregamento da página, os benefícios de usar o atributo defer não são grandes.
A seguir está a versão modificada do código usando o atributo defer:
<html>
<body onload="init()">
<adiamento de script>
função inicialização() {
var tbl, tbody, tr, td, texto, i, max;
máximo = 1000;
var theDoc = documento;
var theBody = theDoc.body
tbl = theDoc.createElement("TABELA");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
para (i=0; i<máx; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
texto = theDoc.createTextNode("Texto");
td.insertBefore (texto, nulo);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
}
</script>
</body>
</html>
Veja a quarta amostra.
O tempo deste teste é 2.043 ms. Isto representa um aumento de 12% em relação ao teste de base e 2,5% superior ao teste anterior.
Um método de melhoria do qual falaremos abaixo é muito útil, é claro, mas um pouco mais problemático. Quando você precisa criar um elemento e depois inseri-lo em uma estrutura semelhante a uma árvore, é mais eficiente inseri-lo diretamente no tronco - em vez de inseri-lo primeiro em uma subárvore grande e depois inserir a subárvore grande no tronco. Por exemplo, se você criar uma tabela com uma coluna em cada linha e algum texto na coluna, poderá fazer o seguinte:
1. Criar <TR>
2. Criar <TD>
3. Criar nó TextNode
4. Inserir TextNode em <TD >
5 Insira <TD> em <TR>
6. Insira <TR> em TBODY
Quando for mais lento que o seguinte método:
1. Crie <TR>
2. Crie <TD>
3. Crie TextNode
4. Insira <TR > Inserir em TBODY
5. Inserir <TD> em <TR>
6. Inserir TextNode em <TD>
Todos os quatro testes acima usam o método anterior. Usamos o último método para o quinto teste. O código é o seguinte:
<html>
<body onload="init()">
<adiamento de script>
função inicialização() {
var tbl, tbody, tr, td, texto, i, max;
máximo = 1000;
var theDoc = documento;
var theBody = theDoc.body
tbl = theDoc.createElement("TABELA");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
para (i=0; i<máx; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
texto = theDoc.createTextNode("Texto");
tbody.insertBefore(tr, null);
tr.insertBefore(td, null);
td.insertBefore (texto, nulo);
}
}
</script>
</body>
</html>
Veja a quinta amostra.
Test5 leva apenas 1.649 ms. Esta é uma melhoria de 25% em relação ao último teste e quase 30% mais rápida que a linha de base.
Modificações subsequentes foram feitas usando folhas de estilo pré-fabricadas. A largura da coluna de uma tabela que usa uma folha de estilo predefinida ou é definida por meio da tag <COL>. Quando não há tag <COL>, a largura de cada coluna é distribuída uniformemente. Como não há necessidade de recalcular o tamanho de cada coluna, etc., usar uma folha de estilos realmente melhora o desempenho, especialmente quando o número de colunas na tabela é grande.
O código para adicionar uma folha de estilo (CSS) é muito simples, como segue:
tbl.style.tableLayout = "fixed";
Veja a sexta amostra
Como a tabela em nosso teste tinha apenas uma coluna, essa alteração melhorou o desempenho da página apenas em 1,6%. Se houver mais colunas, o aumento de desempenho será ainda maior.
Os dois últimos testes mudaram a forma como o texto é inserido na tabela. Nos testes anteriores, primeiro criamos um TextNode e depois o inserimos no TD. Em Test7, em vez disso, especificamos o texto incluído via innerText. O código modificado é:
td.innerText = "Text";
Veja a sétima amostra.
Surpreendentemente, a diferença que esta modificação fez foi enorme – uma melhoria de desempenho de 9% em relação à última vez e um total de melhoria de desempenho de 36% em relação ao original. O tempo varia dos primeiros 2.323 ms aos últimos 1.473 ms.
Agora, quase todo mundo sabe que usar element.innerHTML é muito lento. Para ver o quão lento é, fiz um último teste: inserir texto usando innerHTML em vez de innerText. Isso reduz muito o desempenho. O tempo atingiu 3375ms, 80% mais lento que o último teste e 45% mais lento que o teste de linha de base. Obviamente, innerHTML consome muito tempo.
Ajustar o desempenho da página HTML é semelhante ao ajustar o desempenho do aplicativo Win32; você precisa saber o que é lento e o que é rápido; Espero que esses métodos possam ajudá-lo a melhorar o desempenho da página.