trabajo tiempo reducir para optimize optimizar minimiza herramientas ejecución compilación análisis javascript performance optimization loops for-loop

reducir - reduce el tiempo de ejecución de javascript wordpress



¿Es realmente necesario optimizar JavaScript para bucles? (8)

2017 Respuesta actualizada

Debe utilizar la forma optimizada / mejor práctica.

En su ejemplo exacto: es tan trivial, que no importa. Incluso con una diferencia de rendimiento del 50%, como lo indica @ jfriend00, no significa mucho. Las CPU (para incluir los teléfonos inteligentes actuales) pueden hacer millones de cálculos por segundo. Lo que significa que la fracción de milisegundo ni siquiera se registrará para el usuario, lo que está en línea con lo publicado por @Ned Batchelder.

Sin embargo, la codificación no debe ser sobre lo que puede salirse con la suya. Dicho esto, como dijo @DwB, el "... valor de parada ... solo es valioso si es un valor calculado". Teniendo esto en cuenta, el siguiente código proporciona un ejemplo de una función de pérdida de tiempo para devolver un valor de parada. Aquí se hace evidente cuán diferente es la velocidad. Multiplique las posibles deficiencias en un servidor, el código complejo del lado del cliente y otros cálculos intensivos, y mejorará la experiencia del usuario utilizando las mejores prácticas.

var eCount = document.getElementById("loopCount"); var waitDiv = document.getElementById("waitDiv"); var runButton = document.getElementById("runButton"); var interCount = eCount.value.replace(//D/g,''''); var names = [''George'',''Ringo'',''Paul'',''John'']; eCount.addEventListener("input", function(){ var value = parseInt(this.value.replace(//D/g,'''')).toLocaleString(); this.value = value.toLocaleString(); }); function runLoop(){ interCount = eCount.value.replace(//D/g,''''); waitImg(true); setTimeout(function(){ var cachedTime = loopTest("cached"); var inlineTime = loopTest("inline"); document.getElementById( "cached" ).innerText = cachedTime+" Cached"; document.getElementById( "inline" ).innerText = inlineTime+" Not Cached"; waitImg(false); }, 100); // delay to allow update of DOM with waitimg gif } function loopTest(meth){ var worthlessVariable = 0; var t0 = performance.now(); if( meth == "cached" ){ for( var i = 0, len = busyCalulations(); i < len; i++) { worthlessVariable = i; } }else{ for( var i = 0; i < busyCalulations(); i++) { worthlessVariable = i; } } var t1 = performance.now(); return (t1 - t0); } function busyCalulations(){ // garbage math to simulate doing something // it returns interCount after some pointless math var limit = Math.floor(Math.random() * 20) + 20; return interCount*(limit*names.length)/(limit*names.length); } function waitImg(txt){ // display wait timer if (txt === true){ waitDiv.style.visibility = "visible"; runButton.style.visibility = "hidden"; }else{ waitDiv.style.visibility = "hidden"; runButton.style.visibility = "visible"; } }

<h1>Loop Tester</h1> <form onSubmit="return false;"> Loop Length <input id="loopCount" type="text" value="100,000"><br> <br><br> <button id="runButton" onClick="runLoop();">Run Test</button> <div id="waitDiv" style="visibility: hidden"><img src="https://i.stack.imgur.com/5qXc3.gif"></div> <br><br> </form> <div><p>Times are in milliseconds</p> <div id="cached"></div> <div id="inline"></div> </div>

Leí que se recomienda optimizar los bucles en JavaScript al no leer el atributo de longitud de una matriz en cada iteración en el encabezado del bucle .

Por lo tanto, deberíamos hacer esto:

var names = [''George'',''Ringo'',''Paul'',''John'']; for(var i=0,j=names.length;i<j;i++){// Read array length once and assign it to a variable doSomeThingWith(names[i]); }

en lugar de esto:

var names = [''George'',''Ringo'',''Paul'',''John'']; for(var i=0;i<names.length;i++){ doSomeThingWith(names[i]); }

Sin embargo, creé un pequeño testcase para comparar las dos técnicas, pero a veces el primer caso fue más rápido y, a veces, el segundo.

¿Qué versión recomendarías?


Como regla general, el almacenamiento en caché del "valor de parada" de un bucle (en su caso names.length) solo es valioso si es un valor calculado. Para la matriz en cuestión, es solo una búsqueda, por lo que ganará poco almacenándola en caché.


Definir "really necessary" .
Si recorres una matriz de 4 elementos, no creo que ni siquiera a IE le importe, pero ten en cuenta que quizás debas recorrer algunos elementos de dom; diga que tiene una lista ( ul ) con 1.000.000 (o más) entradas ( li ). Creo que declarar una variable adicional le ahorraría verificar la propiedad de la longitud de ese mismo mil millones de veces.
Tal vez exageré un poco con la parte del millón, pero eche un vistazo a los resultados de las pruebas en solo 10000 li ''s.
El bucle optimizado era casi cien veces más rápido que el "normal".

Mi conclusión: optimiza tus bucles ... no te puede dañar (ni a tu código ni a tu navegador).


Este consejo siempre fue, en el mejor de los casos, una microoptimización, y con todo el trabajo realizado en la velocidad de los motores de Javascript, es poco probable que ya sea una diferencia mensurable. Tal vez en algún lugar de un bucle muy largo y estrecho pueda hacer una diferencia, pero lo dudo.

Por alguna razón, los programadores tienden a concentrarse en la velocidad por encima de todo, incluso cuando no está justificado. Piense en la corrección, luego legibilidad.


Por favor, consulte this publicación, que habla sobre la optimización de los bucles JS.

Así que una solución simple para tu problema sería:

let arr = ["a", "b", "c", "d", "e"] let i = arr.length while(i--) { callFn(); }

El código anterior se ejecutaría más rápido en comparación con otras técnicas de bucle convencionales como

for(let i = 0; i < arr.length; i++) {}

Porque el código anterior tendría que buscar arr.length en cada iteración.


Primero, debo decir que esta respuesta está escrita en 2011 y estas cosas cambian con el tiempo (a medida que los intérpretes de los navegadores optimizan más y más cosas), por lo tanto, si realmente desea conocer el estado actual del mundo, debe realizar pruebas en los navegadores actuales. .

Ejecute su propia prueba jsperf en cualquier versión de IE. Allí verá una diferencia consistente entre los dos métodos o muchos otros navegadores antiguos. Aparentemente solo lo ejecutó en Chrome, que es tan rápido y tan optimizado que hay una diferencia insignificante entre los dos métodos. En IE9 (que es probablemente mucho mejor que IE7 e IE8), el método que precede en caché la longitud es 31% más rápido.

Una prueba jsperf diseñada para esta pregunta da resultados cuantitativos en esta pregunta. En preguntas como esta, uno solo debe ir a jsperf para ver cuál es la diferencia real en lugar de tanta especulación.

Muestra una diferencia en los navegadores que probé, que varía desde casi ninguna diferencia hasta una diferencia bastante considerable según el navegador. En Chrome, casi no hay diferencia. En IE9, almacenar la longitud primero es casi un 50% más rápido.

Ahora, si esta diferencia de velocidad es importante para sus scripts depende del código específico. Si tuvieras una gran variedad de bucles con frecuencia, podría hacer una diferencia significativa en algunos navegadores para usar este formulario:

for (var i = 0, len = list.length; i < len; i++) { // do code here }

En un caso de prueba ligeramente diferente al usar pseudo matrices en vivo devueltas por algunas funciones de DOM, todavía había una diferencia en la velocidad, pero no tan ampliada (esperaba que la diferencia fuera mayor en las matrices en vivo de pseudo-DOM, pero no lo fue).

En la práctica, tiendo a usar la versión corta (menos escritura) cuando no creo que mi sección de código sea crítica a la velocidad y / o la matriz no sea grande y yo usaría la versión más larga que precede en caché la longitud si Estoy pensando conscientemente en la velocidad o la matriz es enorme o estoy haciendo muchas iteraciones sobre la misma matriz.

Hay un par de otras razones de programación para pre-cachear la longitud. Si va a agregar elementos al final de la matriz durante el bucle y no desea que el bucle itere sobre los elementos recién agregados, entonces NECESITA cargar previamente la longitud y solo iterar sobre los elementos inicialmente presentes .

for (var i = 0, len = list.length; i < len; i++) { if (list[i] == "whatever") { list.push("something"); } }

Tenga en cuenta que los navegadores evolucionan continuamente y agregan cada vez más optimizaciones, por lo que una optimización que muestre un gran beneficio en 2011 puede incorporarse esencialmente en un navegador más moderno en el futuro, por lo que ya no es necesaria la optimización codificada a mano. Entonces, si está tratando de optimizar algo para el rendimiento de hoy, tiene que probar en los navegadores de hoy, no puede simplemente confiar en las cosas que lee que pueden tener algunos años.


Yo lo recomiendo

var names = [''George'',''Ringo'',''Paul'',''John'']; var length = names.length; for(var i=0;i<length;i++){ doSomeThingWith(names[i]); }


Yo recomendaría el segundo:

var names = [''George'',''Ringo'',''Paul'',''John'']; for (var i = 0; i < names.length; i++) { doSomeThingWith(names[i]); }

Porque es más conciso y más idiomático. Nunca necesitarás usar el primero a menos que estés realizando una microoptimización absurda.