Bjorn Tipling, publicó ayer un artículo con algunos consejos con los que mejorar el rendimiento de las aplicaciones javascript que interactuan con DOM, pero he estado haciendo pruebas de rendimiento y creo que es necesario comentarlas aqui para que veamos que es más optimo y que no lo és.
Escenario
El escenario en donde he realizado las pruebas es el siguiente:
- Windows XP
- Firefox 2.0.7
- Firebug 1.0.5
- Clase Timer en Javascript
1. No usar operaciones DOM para crear nodos.
Bjorn, comenta que la mejor opción para la creación de nodos es usar parentNode.innerHTML, pero … los resultados son diferentes.
Código
var rep = 10000; //10.000
var parentNode = $('res');
var func = function() {
parentNode.innerHTML = "<div>Stuff</div>"
};
var func2 = function() {
var d = document.createElement("div");
d.nodeValue = "Stuff";
parentNode.childNodes[0] = d;
};
timer.start();
for (var x=0; x<rep; x++) func();
console.log("[NO_DOM]: " + timer.since());
timer.start();
for (var x=0; x<rep; x++) func2();
console.log("[DOM]: " + timer.since());
Resultados
[NO_DOM]: 2491
[DOM]: 705
2. Como excepción a la anterior, en los casos de insercción a continuación de lo que ya había, si que se recomienda usar DOM.
El comando parentNode.innerHTML +=, consume una cantidad insana de tiempo, esto es una realidad y la prueba lo ha demostrado. He reducido el numero de repeticiones a 1.000 para evitar que se colgara el navegador.
Código
var rep = 1000; //1.000
var parentNode = $('res');
var func = function() {
parentNode.innerHTML += "<div>Stuff</div>"
};
var func2 = function() {
node = document.createElement("div");
node.innerHTML = "<div>More Stuff</div>";
parentNode.appendChild(node.childNodes[0]);
};
timer.start();
for (var x=0; x<rep; x++) func();
console.log("[NO_DOM]: " + timer.since());
timer.start();
for (var x=0; x<rep; x++) func2();
console.log("[DOM]: " + timer.since());
Resultados
[NO_DOM]: 40210
[DOM]: 344
3. No concatenes cadenas con +=
Bjorn publica unos ejemplos de como concatenar cadenas, pero las pruebas indican que los resultados no son muy diferentes.
Código
var rep = 10000; //10.000
var parentNode = $('res');
var func = function() {
html = "";
html += "<div>"
html += "Content"
html += "</div>"
parentNode.innerHTML = html;
};
var func2 = function() {
html2 = [];
html2.push("<div>")
html2.push("Content")
html2.push("</div>")
parentNode.innerHTML = html2.join("");
};
timer.start();
for (var x=0; x<rep; x++) func();
console.log("[NO_DOM]: " + timer.since());
timer.start();
for (var x=0; x<rep; x++) func2();
console.log("[DOM]: " + timer.since());
Resultados
[NO_DOM]: 2804
[DOM]: 2850
4. Dale un respiro a tu navegador despues de una buena tanda de insercciones DOM.
Parece obvio pensar que deberíamos darle un descanso a nuestro navegador despues de un intenso trabajo con DOM.
Código
var rep = 1000; //10.000
var parentNode = $('res');
function animation() {
console.log("Descanso");
};
var func = function() {
parentNode.innerHTML = "<div>Stuff</div>"
setTimeout(function(){animation();},0);
};
var func2 = function() {
var d = document.createElement("div");
d.nodeValue = "Stuff";
parentNode.childNodes[0] = d;
setTimeout(function(){animation();},0);
};
timer.start();
for (var x=0; x<rep; x++) func();
console.log("[NO_DOM]: " + timer.since());
timer.start();
for (var x=0; x<rep; x++) func2();
console.log("[DOM]: " + timer.since());
Resultados
[NO_DOM]: 485
[DOM]: 204
5. Ten cuidado con el tamaño de tu javascript.
El tamaño del nuestro javascript, no solo debe ser pequeño para evitar que la carga del usuario sea larga o pesada. Tambien hemos de pensar que el fichero es procesado por el navegador y a mayor tamaño, mayor procesamiento requiere.
6. Cargar javascript cuando lo necesitemos
Una solución para evitar que todo el javascript sea cargado al inicio, es la de segmentarlo e ir cargandolo cuando necesitemos.
7. Comprime tu javascript, 8. Gzip te ayuda
Evidentemente si comprimimos el JS, el tamaño del mismo será menor y por lo tanto ahorraremos tiempo de carga.
Código
var rep = 1000; //10.000
var parentNode = $('res');
var func = function() {
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
};
var func2 = function() {
eval(function(p,a,c,k,e,d){e=function(c){return c};if(!''.replace(/^/,String)){while(c--){d[c]=k[c]||c}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";2.1="0";',3,3,'HOLA|innerHTML|parentNode'.split('|'),0,{}))
};
timer.start();
for (var x=0; x<rep; x++) func();
console.log("[NO_DOM]: " + timer.since());
timer.start();
for (var x=0; x<rep; x++) func2();
console.log("[DOM]: " + timer.since());
Resultado
[NORMAL]: 4731
[COMPRESS]: 7347
En este ejemplo pretendo mostrar la diferencia de tiempo que tarda el PC en responder a la descompresión de código, en func2(), tenemos la versión comprimida con Javascript Compressor (Packer de Dean Edwars) de func(). Para complementar esta prueba, he realizado la prueba con la compresión plana, osea eliminando los carácteres especiales y en blanco, dejando una línea de texto.
Código
var rep = 1000; //10.000
var parentNode = $('res');
var func = function() {
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
parentNode.innerHTML = "HOLA";
};
var func2 = function() {
parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";parentNode.innerHTML="HOLA";
};
timer.start();
for (var x=0; x<rep; x++) func();
console.log("[NO_DOM]: " + timer.since());
timer.start();
for (var x=0; x<rep; x++) func2();
console.log("[DOM]: " + timer.since());
Resultados
[NORMAL]: 4782
[COMPRESS]: 4594




4 comentarios, 0 referencias
+
#