javascript - tag - ¿Son los bucles realmente más rápidos al revés?
title of page html (30)
He escuchado esto unas cuantas veces. ¿Son los bucles de JavaScript realmente más rápidos cuando se cuenta hacia atrás? Si es así, ¿por qué? He visto algunos ejemplos de pruebas que muestran que los bucles invertidos son más rápidos, ¡pero no puedo encontrar ninguna explicación de por qué!
Supongo que se debe a que el bucle ya no tiene que evaluar una propiedad cada vez que comprueba si está terminado y solo compara con el valor numérico final.
Es decir
for (var i = count - 1; i >= 0; i--)
{
// count is only evaluated once and then the comparison is always on 0.
}
Respuesta corta
Para el código normal, especialmente en un lenguaje de alto nivel como JavaScript , no hay diferencia de rendimiento en i++
e i--
.
El criterio de rendimiento es el uso en el bucle for
y la instrucción de comparación .
Esto se aplica a todos los lenguajes de alto nivel y es en su mayoría independiente del uso de JavaScript. La explicación es el código del ensamblador resultante en la línea inferior.
Explicación detallada
Una diferencia de rendimiento puede ocurrir en un bucle. El fondo es que en el nivel del código del ensamblador puede ver que una compare with 0
es solo una declaración que no necesita un registro adicional.
Esta comparación se emite en cada paso del bucle y puede resultar en una mejora de rendimiento medible.
for(var i = array.length; i--; )
Se evaluará a un pseudo código como este:
i=array.length
:LOOP_START
decrement i
if [ i = 0 ] goto :LOOP_END
... BODY_CODE
:LOOP_END
Tenga en cuenta que 0 es un literal, o en otras palabras, un valor constante.
for(var i = 0 ; i < array.length; i++ )
será evaluado a un pseudo código como este (supuesta optimización de intérprete normal):
end=array.length
i=0
:LOOP_START
if [ i < end ] goto :LOOP_END
increment i
... BODY_CODE
:LOOP_END
Tenga en cuenta que end es una variable que necesita un registro de CPU . Esto puede invocar un intercambio de registro adicional en el código y necesita una declaración de comparación más costosa en la instrucción if
.
Solo mis 5 centavos
Para un lenguaje de alto nivel, la legibilidad, que facilita el mantenimiento, es más importante como una mejora menor del rendimiento.
Normalmente, la iteración clásica de matriz de principio a fin es mejor.
La iteración más rápida desde el final de la matriz hasta el inicio da como resultado la secuencia inversa posiblemente no deseada.
Post scriptum
Como se preguntó en un comentario: La diferencia de --i
i--
está en la evaluación de i
antes o después de la disminución.
La mejor explicación es probarlo ;-) Aquí hay un ejemplo de Bash .
% i=10; echo "$((--i)) --> $i"
9 --> 9
% i=10; echo "$((i--)) --> $i"
10 --> 9
Depende de la ubicación de su matriz en la memoria y la proporción de aciertos de las páginas de memoria mientras accede a esa matriz.
En algunos casos, acceder a los miembros de la matriz en el orden de las columnas es más rápido que el orden de las filas debido al aumento en la proporción de aciertos.
Esto no depende del signo --
o ++
, pero depende de las condiciones que aplique en el bucle.
Por ejemplo: su bucle es más rápido si la variable tiene un valor estático que si su bucle comprueba las condiciones cada vez, como la longitud de una matriz u otras condiciones.
Pero no se preocupe por esta optimización, porque esta vez su efecto se mide en nanosegundos.
He visto la misma recomendación en Sublime Text 2.
Como ya se dijo, la mejora principal no es evaluar la longitud de la matriz en cada iteración en el bucle for. Esta es una técnica de optimización bien conocida y particularmente eficiente en JavaScript cuando la matriz es parte del documento HTML (haciendo un for
para todos los elementos li
).
Por ejemplo,
for (var i = 0; i < document.getElementsByTagName(''li'').length; i++)
es mucho más lento que
for (var i = 0, len = document.getElementsByTagName(''li'').length; i < len; i++)
Desde donde estoy, la principal mejora en la forma de su pregunta es el hecho de que no declara una variable adicional ( len
en mi ejemplo)
Pero si me pregunta, el punto principal no es sobre la optimización i++
vs i--
, sino sobre no tener que evaluar la longitud de la matriz en cada iteración (puede ver una prueba de referencia en jsperf ).
Intento dar una imagen amplia con esta respuesta.
Mi opinión entre paréntesis era mi creencia hasta que acabo de probar el problema recientemente:
[[En términos de lenguajes de bajo nivel como C / C++ , el código se compila de manera que el procesador tenga un comando de salto condicional especial cuando una variable es cero (o no es cero).
Además, si te interesa esta optimización, puedes usar ++i
lugar de i++
, porque ++i
es un comando de un solo procesador, mientras que i++
significa j=i+1, i=j
.]]
Se pueden hacer bucles realmente rápidos al desenrollarlos:
for(i=800000;i>0;--i)
do_it(i);
Puede ser mucho 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 pueden ser bastante complicadas (solo para mencionar, existen los problemas de preprocesamiento de comandos del procesador y manejo de caché en el juego).
En términos de lenguajes de alto nivel , como JavaScript según lo que solicitó, puede optimizar las cosas si confía en bibliotecas, funciones integradas para bucles. Déjalos decidir cómo se hace mejor.
En consecuencia, en JavaScript, sugeriría usar algo como
array.forEach(function(i) {
do_it(i);
});
También es menos propenso a errores y los navegadores tienen la oportunidad de optimizar su código.
[OBSERVACIÓN: no solo los navegadores, sino que también tiene un espacio para optimizar fácilmente, simplemente redefina la función forEach
(el navegador depende) para que use el mejor truco más reciente. :) @AMK dice que en casos especiales vale la pena usar array.pop
o array.shift
. Si haces eso, ponlo detrás de la cortina. La máxima exageración es agregar opciones a forEach
para seleccionar el algoritmo de bucle.]
Además, también para los lenguajes de bajo nivel, la mejor práctica es utilizar alguna función de biblioteca inteligente para operaciones complejas y en bucle, si es posible.
Esas bibliotecas también pueden poner cosas (subprocesos múltiples) detrás de su espalda y también programadores especializados los mantienen actualizados.
Hice un poco más de escrutinio y resulta que en C / C ++, incluso para operaciones 5e9 = (50,000x100,000), no hay diferencia entre subir y bajar si la prueba se realiza contra una constante como la que dice @alestanis. (Los resultados de JsPerf a veces son inconsistentes, pero en general dicen lo mismo: no se puede hacer una gran diferencia).
Entonces, resulta que es más bien una cosa "elegante". Solo te hace parecer un mejor programador. :)
Por otro lado, para desenrollar en esta situación 5e9, me ha bajado de 12 segundos a 2,5 segundos cuando pasé por 10s, y a 2,1 segundos cuando pasé 20s. Fue sin optimización, y la optimización ha reducido las cosas a poco tiempo indiscutible. :) (El desenrollado se puede hacer en mi forma anterior o usando i++
, pero eso no trae las cosas adelante en JavaScript).
En definitiva: mantenga las i--
/ i++
y ++i
/ i++
en las entrevistas de trabajo, array.forEach
a array.forEach
u otras funciones de biblioteca complejas cuando estén disponibles. ;)
La última vez que me molesté fue cuando escribí el ensamblaje 6502 (8 bits, ¡sí!). La gran ganancia es que la mayoría de las operaciones aritméticas (especialmente los decrementos) actualizaron un conjunto de indicadores, uno de ellos era Z
, el indicador ''llegó a cero''.
Entonces, al final del bucle, simplemente hiciste dos instrucciones: DEC
(decrementar) y JNZ
(saltar si no es cero), ¡no se necesita comparación!
No creo que tenga sentido decir que i--
es más rápido que i++
en JavaScript.
En primer lugar , depende totalmente de la implementación del motor JavaScript.
En segundo lugar , siempre que las construcciones JIT''ed más sencillas y se traduzcan a instrucciones nativas, entonces i++
vs i--
dependerá totalmente de la CPU que lo ejecute. Es decir, en ARM (teléfonos móviles) es más rápido bajar a 0 desde que la disminución y la comparación a cero se ejecutan en una sola instrucción.
Probablemente, pensaste que una era más desperdiciada que la otra porque la forma sugerida es
for(var i = array.length; i--; )
pero la forma sugerida no es porque una más rápida que la otra, sino simplemente porque si escribes
for(var i = 0; i < array.length; i++)
luego, en cada iteración array.length
tuvo que evaluar (un motor de JavaScript más inteligente tal vez podría descubrir que el bucle no cambiará la longitud del array). Aunque parece una declaración simple, en realidad es una función que el motor de JavaScript llama bajo el capó.
La otra razón por la que i--
podría considerarse "más rápido" es porque el motor de JavaScript necesita asignar solo una variable interna para controlar el bucle (variable a la var i
). Si se comparó con array.length o con alguna otra variable, tenía que haber más de una variable interna para controlar el bucle, y el número de variables internas es un activo limitado de un motor de JavaScript. Cuantas menos variables se usen en un bucle, mayor será la posibilidad de que JIT tenga optimización. Es por eso que i--
podría ser considerado más rápido ...
No es el --
o ++
, es la operación de comparación. Con --
puedes usar una comparación con 0, mientras que con ++
necesitas compararla con la longitud. En el procesador, la comparación con cero normalmente está disponible, mientras que la comparación con un entero finito requiere una resta.
a++ < length
en realidad se compila como
a++
test (a-length)
Por lo tanto, toma más tiempo en el procesador cuando se compila.
No es que i--
sea más rápido que i++
. En realidad, ambos son igualmente rápidos.
Lo que lleva tiempo en los bucles ascendentes es evaluar, para cada i
, el tamaño de su matriz. En este bucle:
for(var i = array.length; i--;)
Usted evalúa .length
solo una vez, cuando declara i
, mientras que para este bucle
for(var i = 1; i <= array.length; i++)
evalúa .length
cada vez que incrementas i
, cuando verificas si i <= array.length
.
En la mayoría de los casos, no debería preocuparse por este tipo de optimización .
Para abreviar: No hay absolutamente ninguna diferencia al hacer esto en JavaScript.
En primer lugar, puedes probarlo tú mismo:
No solo puede probar y ejecutar cualquier secuencia de comandos en cualquier biblioteca de JavaScript, sino que también tiene acceso a toda la serie de secuencias de comandos escritas anteriormente, así como a la posibilidad de ver las diferencias entre el tiempo de ejecución en diferentes navegadores en diferentes plataformas.
Por lo que puedes ver, no hay diferencia entre el rendimiento en cualquier entorno.
Si desea mejorar el rendimiento de su script, puede intentar hacer lo siguiente:
- Tener una
var a = array.length;
declaración para que no esté calculando su valor cada vez en el bucle - Hacer bucle desenrollado http://en.wikipedia.org/wiki/Loop_unwinding
Pero tienes que entender que la mejora que puedes obtener será tan insignificante, que en su mayoría no deberías preocuparte por ello.
Mi propia opinión de por qué surgió tal error (Dec vs Inc)
Hace mucho, mucho tiempo hubo una instrucción de máquina común, DSZ (Decrement and Skip on Zero). Las personas que programaron en lenguaje ensamblador utilizaron esta instrucción para implementar bucles con el fin de guardar un registro. Ahora estos datos antiguos están obsoletos, y estoy bastante seguro de que no obtendrás ninguna mejora en el rendimiento en ningún idioma con esta pseudo mejora.
Creo que la única forma en que ese conocimiento puede propagarse en nuestro tiempo es cuando lees el código personal de otra persona. Vea tal construcción y pregunte por qué se implementó y aquí está la respuesta: "mejora el rendimiento porque se compara con cero". Te desconcertó el mayor conocimiento de tu colega y piensas usarlo para ser mucho más inteligente :-)
Puede explicarse mediante JavaScript (y todos los idiomas) que finalmente se convierten en códigos de operación para ejecutarse en la CPU. Las CPU siempre tienen una sola instrucción para comparar contra cero, lo que es muy rápido.
Además, si puede garantizar que el count
sea siempre >= 0
, podría simplificar:
for (var i = count; i--;)
{
// whatever
}
Ya que está interesado en el tema, eche un vistazo a la publicación del blog de Greg Reimer sobre un punto de referencia de bucle de JavaScript, ¿Cuál es la forma más rápida de codificar un bucle en JavaScript? :
Construí un conjunto de pruebas de comparación de bucles para diferentes formas de codificación de bucles en JavaScript. Ya hay algunos de estos por ahí, pero no encontré ninguno que reconociera la diferencia entre matrices nativas y colecciones HTML.
También puede hacer una prueba de rendimiento en un bucle abriendo https://blogs.oracle.com/greimer/resource/loop-test.html
(no funciona si JavaScript está bloqueado en el navegador, por ejemplo, NoScript ).
EDITAR:
Se puede realizar un punto de referencia más reciente creado por Milan Adamovsky en tiempo de ejecución here para diferentes navegadores.
Para una prueba en Firefox 17.0 en Mac OS X 10.6 obtuve 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;
}
Ya que ninguna de las otras respuestas parece responder a su pregunta específica (más de la mitad de ellas muestra ejemplos de C y discute idiomas de nivel inferior, su pregunta es para JavaScript) Decidí escribir la mía.
Entonces, aquí tienes:
Respuesta simple: i--
generalmente es más rápido porque no tiene que ejecutar una comparación a 0 cada vez que se ejecuta, los resultados de las pruebas en varios métodos se encuentran a continuación:
Resultados de la prueba: según lo "probado" por this jsPerf, arr.pop()
es en realidad el bucle más rápido por el momento. Pero, enfocándose en --i
, i--
, i++
y ++i
como hizo en su pregunta, aquí están los jsPerf (son de múltiples jsPerf, consulte las fuentes a continuación) los resultados resumidos:
--i
y i--
son lo mismo en Firefox mientras que i--
es más rápido en Chrome.
En Chrome, un básico para bucle ( for (var i = 0; i < arr.length; i++)
) es más rápido que i--
y --i
mientras que en Firefox es más lento.
Tanto en Chrome como en Firefox, un arr.length
almacenado en caché es significativamente más rápido con Chrome por delante en aproximadamente 170,000 ops / seg.
Sin una diferencia significativa, ++i
es más rápido que i++
en la mayoría de los navegadores, AFAIK, nunca es al revés en ningún navegador.
Un resumen más corto: arr.pop()
es el bucle más rápido con diferencia; para los bucles específicamente mencionados, i--
es el bucle más rápido.
Fuentes: this , http://jsperf.com/ipp-vs-ppi-2
Espero que esto responda tu pregunta.
Este tipo comparó muchos bucles en javascript, en muchos navegadores. También tiene una suite de pruebas para que puedas ejecutarlas tú mismo.
En todos los casos (a menos que perdí uno en mi lectura) el bucle más rápido fue:
var i = arr.length; //or 10
while(i--)
{
//...
}
++
vs. --
no importa porque JavaScript es un lenguaje interpretado, no un lenguaje compilado. Cada instrucción se traduce a más de un lenguaje de máquina y no debe preocuparse por los detalles sangrientos.
Las personas que hablan de usar --
(o ++
) para hacer un uso eficiente de las instrucciones de montaje están equivocadas. Estas instrucciones se aplican a la aritmética de enteros y no hay enteros en JavaScript, solo números .
Debe escribir código legible.
for(var i = array.length; i--; )
no es mucho más rápido. Pero cuando reemplaza array.length
con super_puper_function()
, eso puede ser significativamente más rápido (ya que se llama en cada iteración). Esa es la diferencia.
Si va a cambiarlo en 2014, no necesita pensar en la optimización. Si va a cambiarlo con "Buscar y reemplazar", no necesita pensar en la optimización. Si no tiene tiempo, no necesita pensar en la optimización. Pero ahora, tienes tiempo para pensar en ello.
PS: i--
no es más rápido que i++
.
i--
es tan rápido como i++
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 de la matriz cada vez. Para matrices grandes se puede ver la degradación del rendimiento.
AYUDE A OTROS A EVITAR UN DOLOR DE CABEZA --- ¡VOTE ESTO PARA ARRIBA!
La respuesta más popular en esta página no funciona para Firefox 14 y no pasa el jsLinter. "while" los bucles necesitan un operador de comparación, no una asignación. Funciona en chrome, safari, e incluso es decir. Pero muere en firefox.
¡ESTO ESTÁ DESCOMPUESTO!
var i = arr.length; //or 10
while(i--)
{
//...
}
Esto funcionará (Funciona en firefox, pasa el jsLinter)
var i = arr.length; //or 10
while(i>-1)
{
//...
i = i - 1;
}
Bueno, no sé sobre JavaScript, debería ser solo una cuestión de reevaluación de la matriz y tal vez algo que ver con las matrices asociativas (si solo disminuye, es poco probable que se deban asignar nuevas entradas, si la matriz es densa, es decir, alguien puede optimizar para eso).
En el ensamblaje de bajo nivel, hay una instrucción de bucle, llamada DJNZ (decrementar y saltar si no es cero). Por lo tanto, la disminución y el salto son todos en una sola instrucción, lo que posiblemente sea un poco más rápido que INC y JL / JB (incrementar, saltar si es menor que / saltar si está debajo). Además, comparar con cero es más simple que comparar con otro número. Pero todo eso es realmente marginal y también depende de la arquitectura de destino (podría marcar la diferencia, por ejemplo, en Arm en un teléfono inteligente).
No esperaría que estas diferencias de bajo nivel tuvieran un gran impacto en los idiomas interpretados, simplemente no he visto DJNZ entre las respuestas, así que pensé que compartiría un pensamiento interesante.
En muchos casos, esto esencialmente no tiene nada que ver con el hecho de que los procesadores pueden compararse a cero más rápido que otras comparaciones.
Esto se debe a que solo unos pocos motores de Javascript (los que están en la lista JIT) generan código de lenguaje de máquina.
La mayoría de los motores de Javascript crean una representación interna del código fuente que luego interpretan (para tener una idea de cómo es esto, eche un vistazo al final de esta página en SpiderMonkey de Firefox ). Generalmente, si un fragmento de código hace prácticamente lo mismo pero conduce a una representación interna más simple, se ejecutará más rápido.
Tenga en cuenta que con tareas simples como sumar / restar una de una variable, o comparar una variable con algo, la sobrecarga del intérprete de una "instrucción" interna a la siguiente es bastante alta, por lo que las "instrucciones" menos utilizado internamente por el motor JS, mejor.
En palabras muy simples
"i-- y i ++. En realidad, ambos toman el mismo tiempo".
pero en este caso, cuando tenga una operación incremental ... el procesador evalúa .length cada vez que la variable se incrementa en 1 y en caso de disminución ... particularmente en este caso, evaluará .length solo una vez hasta que obtengamos 0.
Esto es solo una conjetura, pero quizás sea porque es más fácil para el procesador comparar algo con 0 (i> = 0) en lugar de con otro valor (i <Things.length).
Me encanta, muchas marcas, pero no hay respuesta: D
Simplemente poner una comparación contra cero es siempre la comparación más rápida
Entonces (a == 0) en realidad es más rápido en devolver True que (a == 5)
Es pequeño e insignificante y con 100 millones de filas en una colección es medible.
es decir, en un bucle arriba podría estar diciendo dónde i <= array.length y estar incrementando i
en un bucle descendente, podría estar diciendo dónde i> = 0 y estar decrementando i en su lugar.
La comparación es más rápida. No es la ''dirección'' del bucle.
A veces, hacer algunos cambios menores en la forma en que escribimos nuestro código puede hacer una gran diferencia en la rapidez con la que nuestro código se ejecuta realmente. Un área donde un cambio de código menor puede hacer una gran diferencia en los tiempos de ejecución es donde tenemos un bucle for que está procesando una matriz. Cuando la matriz es de elementos en la página web (como los botones de opción), el cambio tiene el mayor efecto, pero todavía vale la pena aplicar este cambio incluso cuando la matriz es interna al código de Javascript.
La forma convencional de codificar un bucle for para procesar una matriz es la siguiente:
for (var i = 0; i < myArray.length; i++) {...
El problema con esto es que la evaluación de la longitud de la matriz usando myArray.length toma tiempo y la forma en que hemos codificado el bucle significa que esta evaluación debe realizarse cada vez que se realiza el bucle. Si la matriz contiene 1000 elementos, la longitud de la matriz se evaluará 1001 veces. Si estuviéramos viendo los botones de radio y tuviéramos myForm.myButtons.length, entonces nos llevará más tiempo evaluarlos, ya que el grupo apropiado de botones dentro de la forma especificada debe ubicarse antes de poder evaluar la longitud cada vez alrededor del bucle.
Obviamente, no esperamos que la longitud de la matriz cambie mientras la procesamos, por lo que todos estos recálculos de la longitud se agregan innecesariamente al tiempo de procesamiento. (Por supuesto, si tiene un código dentro del bucle que agrega o elimina las entradas de la matriz, entonces el tamaño de la matriz puede cambiar entre iteraciones y, por lo tanto, no podemos cambiar el código que lo prueba)
Lo que podemos hacer para corregir esto para un bucle donde el tamaño es fijo es evaluar la longitud una vez al inicio del bucle y guardarlo en una variable. Luego podemos probar la variable para decidir cuándo terminar el ciclo. Esto es mucho más rápido que evaluar la longitud de la matriz cada vez, especialmente cuando la matriz contiene más que unas pocas entradas o es parte de la página web.
El código para hacer esto es:
for (var i = 0, var j = myArray.length; i < j; i++) {...
Así que ahora solo evaluamos el tamaño de la matriz una vez y probamos nuestro contador de bucles contra la variable que mantiene ese valor cada vez alrededor del bucle. Se puede acceder a esta variable adicional mucho más rápido que evaluar el tamaño de la matriz, por lo que nuestro código se ejecutará mucho más rápido que antes. Solo tenemos una variable extra en nuestro script.
A menudo, no importa en qué orden procesamos la matriz siempre que se procesen todas las entradas de la matriz. En este caso, podemos hacer que nuestro código sea un poco más rápido eliminando la variable adicional que acabamos de agregar y procesando la matriz en orden inverso.
El código final que procesa nuestra matriz de la manera más eficiente posible es:
for (var i = myArray.length-1; i > -1; i--) {...
Este código aún solo evalúa el tamaño de la matriz una vez al inicio, pero en lugar de comparar el contador de bucle con una variable, lo comparamos con una constante. Dado que una constante es incluso más efectiva para acceder que una variable y ya que tenemos una declaración de asignación menos que antes, nuestra tercera versión del código ahora es ligeramente más eficiente que la segunda versión y mucho más eficiente que la primera.
El mejor enfoque para responder a este tipo de pregunta es realmente intentarlo. Configure un bucle que cuente con un millón de iteraciones o lo que sea, y hágalo de ambas maneras. Tiempo de ambos bucles, y comparar los resultados.
La respuesta probablemente dependerá de qué navegador está utilizando. Algunos tendrán resultados diferentes que otros.
Hice una comparación en jsbench .
Como señaló alestani, una cosa que lleva tiempo en los bucles ascendentes, es evaluar, para cada iteración, el tamaño de su matriz. En este bucle:
for ( var i = 1; i <= array.length; i++ )
Evalúas .length
cada vez que incrementas i
. En este:
for ( var i = 1, l = array.length; i <= l; i++ )
Evalúas .length
solo una vez, cuando declaras i
. En este:
for ( var i = array.length; i--; )
la comparación es implícita, ocurre justo antes de disminuir i
y el código es muy legible. Sin embargo, lo que puede hacer una gran diferencia, es lo que pones dentro del bucle.
Bucle con llamada a función (definido en otra parte):
for (i = values.length; i-- ;) {
add( values[i] );
}
Bucle con código en línea:
var sum = 0;
for ( i = values.length; i-- ;) {
sum += values[i];
}
Si puede insertar su código en línea, en lugar de llamar a una función, sin sacrificar la legibilidad, ¡puede hacer un bucle un orden de magnitud más rápido!
Nota : como el navegador se está volviendo bueno para incorporar funciones simples, realmente depende de qué tan complejo sea su código. Entonces, perfil antes de optimizar, porque
- El cuello de botella puede estar en otro lugar (ajax, reflow, ...)
- Puedes elegir un mejor algoritmo
- Puedes elegir una mejor estructura de datos
Pero recuerda:
El código está escrito para que la gente lo lea, y solo de forma incidental para que las máquinas lo ejecuten.
La forma en que lo estás haciendo ahora no es más rápida (aparte de que es un bucle indefinido, supongo que querías hacerlo) i--
.
Si quieres hacerlo más rápido haz:
for (i = 10; i--;) {
//super fast loop
}
por supuesto que no lo notarías en un bucle tan pequeño. La razón por la que es más rápido es porque estás disminuyendo i al mismo tiempo que verificas que es "verdadero" (se evalúa como "falso" cuando llega a 0)
No se consume mucho tiempo por i-- o i ++. Si uno se adentra en el interior de la arquitectura de la CPU del ++
es más rápido que el --
, ya que la --
operación va a hacer el complemento a 2, pero sucedió dentro del hardware, así que esto hará que sea rápido y hay gran diferencia entre el ++
y --
también estas operaciones se consideran de la Menos tiempo consumido en la CPU.
El bucle for se ejecuta así:
- Inicializa la variable una vez al inicio.
- Compruebe la restricción en el segundo operando del circuito,
<
,>
,<=
, etc. - A continuación, aplicar el bucle.
- Incrementa el loop y vuelve a lanzar estos procesos nuevamente.
Asi que,
for (var i = Things.length - 1; i >= 0; i--) {
Things[i]
};
calculará la longitud del arreglo solo una vez al inicio y esto no es mucho tiempo, pero
for(var i = array.length; i--; )
calculará la longitud en cada bucle, por lo que consumirá mucho tiempo.
Primero, i++
y i--
tome exactamente el mismo tiempo en cualquier lenguaje de programación, incluido JavaScript.
El siguiente código toma mucho tiempo diferente.
Rápido:
for (var i = 0, len = Things.length - 1; i <= len; i++) { Things[i] };
Lento:
for (var i = 0; i <= Things.length - 1; i++) { Things[i] };
Por lo tanto, el siguiente código toma un tiempo diferente también.
Rápido:
for (var i = Things.length - 1; i >= 0; i--) { Things[i] };
Lento:
for (var i = 0; i <= Things.length - 1; i++) { Things[i] };
PS Slow es lento solo para unos pocos idiomas (motores de JavaScript) debido a la optimización del compilador. La mejor manera es usar ''<'' en lugar de ''<='' (o ''='') y ''--i'' en lugar de ''i--'' .
Se solía decir que --i era más rápido (en C ++) porque solo hay un resultado, el valor decrementado. i-- necesita almacenar el valor decrementado de nuevo en i y también retener el valor original como el resultado (j = i--;). En la mayoría de los compiladores, esto usaba dos registros en lugar de uno, lo que podría hacer que otra variable tuviera que escribirse en la memoria en lugar de conservarse como una variable de registro.
Estoy de acuerdo con los otros que han dicho que no hay diferencia en estos días.