medium entre ecmascript diferencias diferencia and javascript performance const v8 let

entre - v8 Implicaciones de rendimiento de JavaScript de const, let y var?



let var y const (4)

Independientemente de las diferencias funcionales, ¿el uso de las nuevas palabras clave ''let'' y ''const'' tiene algún impacto generalizado o específico en el rendimiento en relación con ''var''?

Después de ejecutar el programa:

function timeit(f, N, S) { var start, timeTaken; var stats = {min: 1e50, max: 0, N: 0, sum: 0, sqsum: 0}; var i; for (i = 0; i < S; ++i) { start = Date.now(); f(N); timeTaken = Date.now() - start; stats.min = Math.min(timeTaken, stats.min); stats.max = Math.max(timeTaken, stats.max); stats.sum += timeTaken; stats.sqsum += timeTaken * timeTaken; stats.N++ } var mean = stats.sum / stats.N; var sqmean = stats.sqsum / stats.N; return {min: stats.min, max: stats.max, mean: mean, spread: Math.sqrt(sqmean - mean * mean)}; } var variable1 = 10; var variable2 = 10; var variable3 = 10; var variable4 = 10; var variable5 = 10; var variable6 = 10; var variable7 = 10; var variable8 = 10; var variable9 = 10; var variable10 = 10; function varAccess(N) { var i, sum; for (i = 0; i < N; ++i) { sum += variable1; sum += variable2; sum += variable3; sum += variable4; sum += variable5; sum += variable6; sum += variable7; sum += variable8; sum += variable9; sum += variable10; } return sum; } const constant1 = 10; const constant2 = 10; const constant3 = 10; const constant4 = 10; const constant5 = 10; const constant6 = 10; const constant7 = 10; const constant8 = 10; const constant9 = 10; const constant10 = 10; function constAccess(N) { var i, sum; for (i = 0; i < N; ++i) { sum += constant1; sum += constant2; sum += constant3; sum += constant4; sum += constant5; sum += constant6; sum += constant7; sum += constant8; sum += constant9; sum += constant10; } return sum; } function control(N) { var i, sum; for (i = 0; i < N; ++i) { sum += 10; sum += 10; sum += 10; sum += 10; sum += 10; sum += 10; sum += 10; sum += 10; sum += 10; sum += 10; } return sum; } console.log("ctl = " + JSON.stringify(timeit(control, 10000000, 50))); console.log("con = " + JSON.stringify(timeit(constAccess, 10000000, 50))); console.log("var = " + JSON.stringify(timeit(varAccess, 10000000, 50)));

.. Mis resultados fueron los siguientes:

ctl = {"min":101,"max":117,"mean":108.34,"spread":4.145407097016924} con = {"min":107,"max":572,"mean":435.7,"spread":169.4998820058587} var = {"min":103,"max":608,"mean":439.82,"spread":176.44417700791374}

Sin embargo, la discusión como se indica aquí parece indicar un potencial real para las diferencias de rendimiento en ciertos escenarios: https://esdiscuss.org/topic/performance-concern-with-let-const


TL; DR

En teoría , una versión no optimizada de este ciclo:

for (let i = 0; i < 500; ++i) { doSomethingWith(i); }

sería más lento que una versión no optimizada del mismo bucle con var :

for (var i = 0; i < 500; ++i) { doSomethingWith(i); }

porque se crea una variable i diferente para cada iteración de bucle con let , mientras que solo hay una i con var .

En la práctica , aquí en 2018, V8 realiza suficiente introspección del bucle para saber cuándo puede optimizar esa diferencia. (Incluso antes de eso, lo más probable es que tu circuito esté haciendo suficiente trabajo para que la sobrecarga adicional relacionada con el let elimine de todos modos. Pero ahora ni siquiera tienes que preocuparte por eso).

Detalles

La diferencia importante entre var y let en un bucle for es que se crea una i diferente para cada iteración; aborda el clásico problema de "cierres en bucle":

function usingVar() { for (var i = 0; i < 3; ++i) { setTimeout(function() { console.log("var''s i: " + i); }, 0); } } function usingLet() { for (let i = 0; i < 3; ++i) { setTimeout(function() { console.log("let''s i: " + i); }, 0); } } usingVar(); setTimeout(usingLet, 20);

Crear el nuevo EnvironmentRecord para cada cuerpo de bucle ( enlace de especificación ) es trabajo, y el trabajo lleva tiempo, razón por la cual, en teoría, la versión let es más lenta que la versión var .

Pero la diferencia solo importa si crea una función (cierre) dentro del ciclo que usa i , como hice en el ejemplo de fragmento ejecutable anterior. De lo contrario, la distinción no se puede observar y se puede optimizar.

Aquí en 2018, parece que V8 (y SpiderMonkey en Firefox) está haciendo una introspección suficiente para que no haya un costo de rendimiento en un bucle que no utiliza la semántica variable por iteración. Ver esta prueba jsPerf .

En algunos casos, const puede brindar una oportunidad de optimización que var no haría, especialmente para las variables globales.

El problema con una variable global es que es, bueno, global; cualquier código en cualquier lugar podría acceder a él. Entonces, si declara una variable con var que nunca tiene la intención de cambiar (y nunca cambia en su código), el motor no puede asumir que nunca cambiará como resultado del código cargado más tarde o similar.

Con const , sin embargo, le está diciendo explícitamente al motor que el valor no puede cambiar¹. Por lo tanto, es libre de hacer cualquier optimización que desee, incluida la emisión de un literal en lugar de una referencia variable al código que lo usa, sabiendo que los valores no se pueden cambiar.

¹ Recuerde que con los objetos, el valor es una referencia al objeto, no el objeto en sí. Entonces, con const o = {} , puede cambiar el estado del objeto ( o.answer = 42 ), pero no puede hacer que o señale a un nuevo objeto (porque eso requeriría cambiar la referencia del objeto que contiene).

Cuando se usa let o const en otras situaciones similares a var , no es probable que tengan un rendimiento diferente. Esta función debe tener exactamente el mismo rendimiento si usa var o let , por ejemplo:

function foo() { var i = 0; while (Math.random() < 0.5) { ++i; } return i; }

Es, por supuesto, poco probable que importe y algo de lo que preocuparse solo si hay un problema real que resolver.


La respuesta de TJ Crowder es muy buena pero:

  1. ''let'' está hecho para hacer que el código sea más legible, no más poderoso
  2. por teoría vamos a ser más lento que var
  3. por práctica, el compilador no puede resolver completamente (análisis estático) un programa incompleto, por lo que en algún momento perderá la optimización
  4. en cualquier caso, usar ''let'' requerirá más CPU para la introspección, el banco debe iniciarse cuando google v8 comience a analizar
  5. Si la introspección falla, ''let'' presionará fuertemente al recolector de basura V8, requerirá más iteración para liberar / reutilizar. También consumirá más RAM. el banco debe tener en cuenta estos puntos
  6. Google Closure transformará let en var ...

El efecto de la brecha de rendimiento entre var y let se puede ver en el programa completo de la vida real y no en un solo ciclo básico.

De todos modos, usar let donde no es necesario, hace que su código sea menos legible.


"DEJAR" ES MEJOR EN LAS DECLARACIONES DE LAZO

Con una prueba simple (5 veces) en el navegador así:

// WITH VAR console.time("var-time") for(var i = 0; i < 500000; i++){} console.timeEnd("var-time")

El tiempo medio de ejecución es más de 2.5 ms

// WITH LET console.time("let-time") for(let i = 0; i < 500000; i++){} console.timeEnd("let-time")

El tiempo medio de ejecución es más de 1.5ms.

Encontré que el tiempo de bucle con let es mejor.


La respuesta de TJ Crowder es tan excelente.

Aquí hay una adición de: "¿Cuándo obtendría el máximo provecho de mi dinero en la edición de declaraciones de var existentes para const?"

Descubrí que la mayor mejora del rendimiento tenía que ver con las funciones "exportadas".

Entonces, si el archivo A, B, R y Z están llamando a una función de "utilidad" en el archivo U que se usa comúnmente a través de su aplicación, entonces cambiar esa función de utilidad a "const" y la referencia del archivo principal a un const puede eak fuera un poco de rendimiento mejorado. Me pareció que no era mensurablemente más rápido, pero el consumo general de memoria se redujo en aproximadamente un 1-3% para mi aplicación Frankenstein-ed groseramente monolítica. Lo cual, si está gastando bolsas de efectivo en la nube o en su servidor de metal desnudo, podría ser una buena razón para pasar 30 minutos para revisar y actualizar algunas de esas declaraciones var para const.

Me doy cuenta de que si lees cómo const, var y dejas trabajar debajo de las sábanas, probablemente ya hayas concluido lo anterior ... pero en caso de que "lo hayas mirado": D.

Por lo que recuerdo de la evaluación comparativa en el nodo v8.12.0 cuando estaba haciendo la actualización, mi aplicación pasó del consumo inactivo de ~ 240 MB de RAM a ~ 233 MB de RAM.