Buscando por "ahí" he visto varias perlas que pese a ser buenas de por sí, están desperdigadas entre mucha paja. Voy a intentar recopilarlas todas en estos posts.
Partiendo de la premisa de que el código más óptimo es el que no se ejecuta, vemos que en algoritmos de orden 1 optimizar código puede ser un poco tonto, pero cuando subimos de orden como n o incluso n^2 y no digamos n^3 (o superiores, so bestias! qué estáis haciendo?!?!?) cada ciclo de reloj cuenta. Al turrón!
Reducción del ámbito de ejecución
Dentro de cada bloque se ven tanto las variables definidas dentro de ese bloque como las de todos sus padres, de modo que mientras más saltos de nivel de profundidad en el acceso a variables dentro del ámbito, más se tarda en ejecutar el código. Para reducir los saltos podemos echar mano de estas técnicas:
- Almacenar en variables locales las variables que se encuentren fuera del ámbito actual. Especialmente con variables globales.
- Evitar el uso de WITH ya que incrementa en uno el nivel de profundidad del ámbito. Usar variables locales en vez de WITH.
- Cuidado con TRY-CATCH. CATCH incrementa en uno el nivel de profundidad del ámbito.
- Usar las closures con moderación. Si no sabes qué es una closure, ahora es el momento. Si aun así te has quedado igual, piensa en que son funciones auto-ejecutadas. En jQuery se usan continuamente y son las típicas que van dentro de las llamadas: blahblahblah( function() { ...algo...} )
- No olvidar usar VAR al definir las variables. Si no usas VAR para definir variables estás cometiendo un epic-fail porque todas tus variables serán globales!. Al próximo que se le olvide usar VAR, le corto las manos.
Se puede accceder a la información de 4 maneras:
- Literal. var nombre = “pepe”;
- Variable. var nombre2 = nombre;
- Propiedad de objeto. var nombre3 = objeto.nombre;
- Elemento de un array. var nombre4 = items[0];
- El método más rápido es el 1.
- La diferencia en tiempo entre el 1 y el 2 es despreciable (si la variable es local, ojo).
- Los métodos 3 y 4 son más costosos y depende del navegador en cuánto lo son (seguro que en IE6 es de orden n-factorial).
- Mientras mayor sea el nivel de profundidad, más costoso. coste de objeto.nombre.name >> objeto.nombre.
- No hay diferencia entre objeto.nombre y objeto[“name”] salvo en safari que la notación por punto es más rápida.
- Almacenar los casos 3 y 4 en variables locales si:
- La propiedad de un objeto se accede más de 1 vez.
- El elemento del array se accede más de 1 vez.
- Minimizar el nivel de profundidad para acceder a los datos en el objto/array.
Quedaría como:
function procesa(datos) {
if(datos.count > 0) {
for(var i=0; i<datos.length; i++) {
procesaDatos(elemento[i]);
}
}
}
function procesa(datos) {
var cuenta = datos.length,
elemento = datos.element;
if(cuenta > 0) {
for(var i=0; i<cuenta; i++) {
procesaDatos(elemento[i]);
}
}
}
Sorprendentemente, la segunda función se ejecuta hasta un 33% más rápido.
Bucles
Aquí es donde se nos escapa el mojo, así que dependiendo de la versión de javascript con la que estemos trabajando (espero por vuestro bien que sea la última y tengáis un navegador decente... sí, Internet Explorer no está en la lista de admitidos, lo sentimos). Ya sabéis, si solo se ejecuta el código una vez (o pocas iteraciones) y no nos pasamos de los 50ms, como que no importa demasiado, pero es bueno saber en qué afectan las distintas estructuras de bucles.
ECMA-357 javascript 2ª edición:
- FOR-EACH --> Evitar a toda costa!. Muy bonito y legible pero mata el rendimiento.
- FOR
- FOR-IN --> Evitar a toda costa!.
- DO-WHILE
- WHILE
- array.forEach --> Evitar a toda costa.
- jQuery.each(), Y.each(), $each, Enumerable.each() --> Evitar a toda costa. Tardan 8x veces más.
Soluciones sencillas:
- Almacenar la longitud en una variable local para que no se chequee cada iteración.
- Incrementar el contador a la vez que se accede (dato = datos[i++])
- Eliminar acceso a objetos/propiedades usando variables locales para almacenarlos.
- Usar bucles del tipo (50% más rápidos): for(i = 0, ii = Obj.length; ii--;){}
No hay comentarios:
Publicar un comentario