Problema de optimización / desaceleración de Javascript var vs let (de) optimización en v8 y SpiderMonkey
Durante la refactorización del código JavaScript en mi proyecto, descubrí que algunos de mis bucles se ralentizaron drásticamente. Buscando la causa raíz que he encontradoesta pregunta SO indicando que la desaceleración es causada porlet
declaración dentrofor
creación de bucle y cierre. Para mi sorpresa moviéndoselet
y cierre de lafor
loop no ayudó, e incluso usandovar
en lugar delet
for loop loop tampoco ayuda porque la ralentización es causada porlet
metidodespués elfor
lazo. Al eliminar detalles adicionales, obtuve este fragmento de código:
"use strict"
console.log("=========================");
(function(){
var itr = 0;
function f(){++itr;}
console.time('without_let');
for(var i = 0; i < 50000000; ++i){
f();
}
var totals = 0;
console.timeEnd('without_let'); //chrome: 122ms, FF:102ms
})();
(function(){
var itr = 0;
function f(){++itr;}
console.time('let_below');
for(var i = 0; i < 50000000; ++i){
f();
}
let totals = 0; // <--- notice let instead of var
console.timeEnd('let_below'); //chrome: 411ms, FF:99ms
})();
(function(){
let itr = 0;
function f(){++itr;}
console.time('let_above_and_in_loop');
for(let i = 0; i < 50000000; ++i){
f();
}
var totals = 0;
console.timeEnd('let_above_and_in_loop'); //chrome: 153ms, FF:899ms
})();
(function(){
var itr = 0;
function f(){++itr;}
console.time('let_in_loop');
for(let i = 0; i < 50000000; ++i){
f();
}
var totals = 0;
console.timeEnd('let_in_loop'); //chrome: 137ms, FF:102ms
})();
(también enJS Fiddle Nota: el uso de JS Fiddle muestra resultados un poco diferentes, pero una desaceleración similar todavía está presente en los mismos lugares)
Ejecutar esto en Chrome produce lo siguiente
without_let: 122ms
let_below: 411ms <----------- Slowdown for v8
let_above_and_in_loop: 153ms
let_in_loop: 137ms
Google me trajo ael artículo declarando quelet
causó desoptimización antes de Chrome 56 / V8 5.6! pero mi Chrome es 57.0.2987.133 (64 bits) y v8 ver 5.7.492.71. Más sorpresas al intentar ejecutar esto en Firefox 52.0.2 (32 bits). Aquí tenemos desaceleración en otro lugar, cuando la variable creada conlet
se usa dentro del cierre:
without_let: 101.9ms
let_below: 99ms
let_above_and_in_loop: 899ms <----- Slowdown for SpiderMonkey
let_in_loop: 102ms
Como veo, el problema está relacionado de alguna manera con la característica llamada "Zona muerta temporal", pero aún no está claro:
¿Por qué dos navegadores principales (motores JavaScript principales) aún no pueden optimizar esas partes (diferentes) del fragmento?
¿Hay alguna solución alternativa para seguir usandolet
(excepto usando Babel para convertir let en var)? Supongamos que puedo pasar opciones a Chrome o incluso directamente a v8 a través dev8::V8::SetFlagsFromCommandLine(&argc, argv, true);
UPD: En Chrome ver 58.0.3029.96, correspondeng v8 versión 5.8.283.37 (correspondiente ahttps://omahaproxy.appspot.com/) después de habilitar chrome: // flags / # enable-v8-future como jmrk sugiere a continuación, todavía hay desaceleración para el tercer caso (ahora 2 veces en lugar de 8 veces)
without_let: 157.000ms
let_below: 155.000ms
let_above_and_in_loop: 304.000ms
let_in_loop: 201.000ms
Firefox 53.0 (32 bits)
without_let: 278.650ms
let_below: 310.290ms
let_above_and_in_loop: 848.325ms
let_in_loop: 275.495ms