178 votos

¿JavaScript - son lazos muy rápido al revés...?

He escuchado esto unas cuantas veces. Son el JavaScript de bucles mucho más rápido al contar hacia atrás? Si es así, ¿por qué? Yo he visto un par de test suite ejemplos que muestran que invierte los bucles son más rápidos, pero no puedo encontrar ninguna explicación de por qué!

Estoy asumiendo que es debido a que el bucle no tiene para evaluar una propiedad cada vez que se comprueba si se acabó, y sólo comprueba en contra de la final valor numérico.

Es decir.

for (var i = count - 1; i >= 0; i--)
{
  // count is only evaluated once and then the comparison is always on 0.
}

Gracias de antemano a cualquiera que pueda satisfacer a mi profesional de la curiorisity!

748voto

alestanis Puntos 11214

No se que i-- es más rápido que i++. En realidad, ambos son igual de rápido.

Lo que lleva tiempo en ascender a los bucles, es evaluar, para cada i, el tamaño de la matriz. En este bucle:

for(var i = array.length; i--; )

Evaluar .length sólo una vez, cuando declara i, mientras que para este bucle

for(var i = 1; i <= array.length; i++ )

evaluar .length cada vez que el incremento i, cuando compruebe si i <= array.length.

En la mayoría de los casos, usted no debería preocuparse por este tipo de optimización.

167voto

Tom Ritter Puntos 44352

Este tipo en comparación a un montón de bucles en javascript, en muchos de los navegadores. También tiene una suite de prueba para que pueda ejecutarlos mismo.

En todos los casos (a menos que me faltaron uno en mi lectura) era el lazo más rápido:

var i = arr.length; //or 10
while(i--)
{
  //...
}

120voto

Barnabas Szabolcs Puntos 4109

Trato de dar un amplio panorama con esta respuesta.

Los siguientes pensamientos entre paréntesis fue mi creencia hasta que yo sólo he probado recientemente el tema:

[[En términos de bajo nivel de lenguajes como C/C++, el código se compila de manera que el procesador tiene una especial condicional de salto de comandos cuando una variable es cero (no-cero).
También, si te preocupa mucho esta optimización, se podría ir ++i en lugar de i++, porque ++i es un procesador de comandos, mientras que i++ medio j=i+1, i=j.]]

Muy rápido de bucles puede ser hecho por desenrollar ellos:

for(i=800000;i>0;--i)
    do_it(i);

Puede ser más lento que

for(i=800000;i>0;i-=8)
{
    do_it(i); do_it(i-1); do_it(i-2); ... do_it(i-7);
}

pero las razones para esto puede ser bastante complicado (por sólo mencionar, hay cuestiones de procesador de comandos de preprocesamiento y caché de manejo en el juego).

En términos de lenguajes de alto nivel, como JavaScript como has pedido, se pueden optimizar las cosas si se basan en las bibliotecas, las funciones integradas para el bucle. Deja que ellos decidan cómo se hace mejor.

En consecuencia, en JavaScript, sugiero el uso de algo como

array.forEach(function(i) {
    do_it(i);
});

También es menos propenso a errores y navegadores tienen una oportunidad para optimizar su código.

[COMENTARIO: no sólo la de los navegadores, pero también tienen un espacio para optimizar fácilmente, sólo tienes que redefinir la forEach función (navegador dependiente), de modo que se utiliza la última mejores trucos! :) @A.M.K. dice que, en casos especiales, vale la pena, más bien, usando array.pop o array.shift. Si haces eso, lo puso detrás de la cortina. La suma de overkill es añadir opciones a forEach para seleccionar el bucle del algoritmo.]

Por otra parte, también para el bajo nivel de idiomas, la mejor práctica es utilizar algunos inteligente de la función de la biblioteca para los complejos, las operaciones de bucle si es posible.

Las bibliotecas también pueden poner las cosas (multi-threaded) detrás de su espalda y también especializados, programadores de mantenerlos actualizados.

Hice un poco más de escrutinio y resulta que en C/C++, incluso para 5e9 = (50,000x100,000) operaciones, no hay ninguna diferencia entre la subida y bajada de si la prueba se realiza en contra de una constante como @alestanis dice. (JsPerf los resultados a veces son incoherentes, pero por lo general dicen lo mismo: no se puede hacer una gran diferencia.)
Así, --i pasa a ser más bien un "posh". Sólo te hace ver como un mejor programador. :)

Por otro lado, para desplegaba en este 5e9 situación, me ha traído abajo a partir de 12 segundos a 2,5 segundos de cuando fui por 10s, y a 2.1 seg cuando fui por 20 años. Fue sin optimización, optimización y ha llevado las cosas a unmeasureable poco tiempo. :) (Desenrollar puede ser hecho en mi camino de arriba o usando i++, pero que no se lleva las cosas por delante en JavaScript. )

En definitiva: mantener i--/i++ y ++i/i++ diferencias para las entrevistas de trabajo, se adhieren a array.forEach u otras complejas funciones de la biblioteca cuando esté disponible. ;)

34voto

RoManiac Puntos 1278

i--es tan rápido comoi++

Este código a continuación es tan rápido como el tuyo, pero utiliza una variable adicional:

var up = Things.length;
for (var i = 0; i < up; i++) {
    Things[i]
};

La recomendación es no evaluar el tamaño del array cada vez. Para matrices de grandes uno puede ver la degradación del rendimiento.

21voto

dreamcrash Puntos 8227

Ya, que están interesados en el tema, echa un vistazo a Greg Reimer weblog post acerca de un JavaScript bucle de referencia, Lo que la Manera más Rápida de Código de un Bucle en JavaScript?:

He construido un lazo de evaluación comparativa de la suite de prueba para diferentes formas de codificar los bucles en JavaScript. Hay un par de estos por ahí ya, pero yo no encuentro ninguna que reconoció la diferencia entre los nativos de las matrices y HTML colecciones.

Usted también puede hacer una prueba de rendimiento en un bucle mediante la apertura https://blogs.oracle.com/greimer/resource/loop-test.html (no funciona si JavaScript está bloqueado en el navegador, por ejemplo, NoScript).

EDICIÓN:

Una más reciente benchmark creado por Milán Adamovsky se puede realizar en tiempo de ejecución aquí para diferentes navegadores.

Para una de las Pruebas en Firefox 17.0 en Mac OS X 10.6 tengo el siguiente bucle:

var i, result = 0;
for (i = steps - 1; i; i--) {
  result += i;
}

como el más rápido precedido por:

var result = 0;
for (var i = steps - 1; i >= 0; i--) {
  result += i;
}

Benchmark example.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X