Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript JS:在闭包的父范围中分配变量会降低性能。为什么?_Javascript_Performance_Scope_Closures - Fatal编程技术网

Javascript JS:在闭包的父范围中分配变量会降低性能。为什么?

Javascript JS:在闭包的父范围中分配变量会降低性能。为什么?,javascript,performance,scope,closures,Javascript,Performance,Scope,Closures,在研究javascript中的闭包时,我提出了下面的一个小例子,但我并不真正理解到底发生了什么 我希望使用垃圾收集器,假设在紧循环中的函数内声明带有var的变量会导致大量的分配和释放。我试图通过将我的var声明放在闭包的父范围中来避免这种情况,并期望closured函数会更快。不管这个想法多么糟糕,我一开始就偶然发现了这个小问题 var withClosure = function() { var a, b, c, d, e, f, g; return function () {

在研究javascript中的闭包时,我提出了下面的一个小例子,但我并不真正理解到底发生了什么

我希望使用垃圾收集器,假设在紧循环中的函数内声明带有
var
的变量会导致大量的分配和释放。我试图通过将我的
var
声明放在闭包的父范围中来避免这种情况,并期望closured函数会更快。不管这个想法多么糟糕,我一开始就偶然发现了这个小问题

var withClosure = function() {
    var a, b, c, d, e, f, g;
    return function () {
        a = 1;
        b = 2;
        c = 3;
        d = 4;
        e = 5;
        f = 6;
        g = 7;
    };
}();

var withoutClosure = function () {
    var a = 1;
    var b = 2;
    var c = 3;
    var d = 4;
    var e = 5;
    var f = 6;
    var g = 7;
};

console.time("without");
for (var i = 0; i < 1000000000; i++) {
    withoutClosure();
}
console.timeEnd("without");


console.time("withcsr");
for (var i = 0; i < 1000000000; i++) {
    withClosure();
}
console.timeEnd("withcsr");


/*
Output on my machine:
    without: 1098.329ms
    withcsr: 8878.812ms

Tested with node v.6.0.0 and Chrome 50.0.2661.102 (64-bit)
*/
var withClosure=function(){
变量a、b、c、d、e、f、g;
返回函数(){
a=1;
b=2;
c=3;
d=4;
e=5;
f=6;
g=7;
};
}();
var withoutClosure=函数(){
var a=1;
var b=2;
var c=3;
var d=4;
变量e=5;
var f=6;
var g=7;
};
时间(“无”);
对于(变量i=0;i<100000000;i++){
无闭包();
}
控制台。时间结束(“无”);
控制台。时间(“带CSR”);
对于(变量i=0;i<100000000;i++){
with closure();
}
控制台。时间结束(“带CSR”);
/*
我的机器上的输出:
无:1098.329ms
带CSR:8878.812ms
使用节点v.6.0.0和Chrome 50.0.2661.102(64位)进行测试
*/
我分配给父范围中的变量的事实使得闭包的运行速度比我机器上的正常版本慢8倍。使用更多的变量会使情况变得更糟。如果我只是读取变量而不是分配给它们,问题就不存在了


这是什么原因?有人能解释一下吗?

在没有闭包的示例中,任何体面的Javascript引擎都会意识到函数中的变量是初始化的,但在超出范围之前从未读取过,因此可以在不影响函数输出的情况下删除

在闭包示例中,变量仍在范围内,因此无法优化


本讲座深入解释了JIT Javascript编译器所做的一些优化:

它与符号表的工作方式有关。符号表将符号(例如变量名)映射到其值,就像关联数组一样。符号表与其他类型的关联数组(如哈希表)的不同之处在于,为了简单和高效,它们是分层的(每个符号表可能有一个父表)。符号解析从当前作用域的符号表开始,一直到根作用域,使用第一个匹配符号的值,如果没有符号匹配到根,则使用未定义的值

在当前范围中声明和引用变量时,只会命中一个符号表:当前范围的符号表。但是,当在父范围中声明变量并在当前范围中引用时,需要对符号表进行两次点击:一次点击未命中的当前范围,另一次点击成功的父范围。因此,从父范围引用变量的速度大约是从当前范围引用变量的速度的两倍


这篇文章在解释符号表方面做得很好:

也许JS引擎以不同的方式优化了函数-如果没有读取任何变量,则可以将非闭包函数优化为空函数。在每个函数末尾返回变量的总和(从而读取值)循环内的闭包需要引用循环外的i。内部函数的变量是调用内部函数时的值,我认为它不会像您期望的那样跟随每次迭代。请您重新表述您的观点。我无法理解这个注释。如果它是汇编,可能更有意义,您可以使用cpu为特定函数提供的许多寄存器,如果您像其他函数一样使用外部,push、pop堆栈变量可能会使程序绑定到内存速度。这已在注释中提出。我还尝试了另一个例子,在那里我读取、求和并返回值。问题仍然存在。返回值没有任何区别,因为它将被优化为“返回28”。事实上,因为您不使用返回值,它可能根本不会执行函数。我提出了另一个示例,以避免未使用和可预测的变量,问题仍然存在。我仍然不确定根本原因。然而,您的回答和视频清楚地表明,我的基准测试尝试非常幼稚,而且毫无用处,因为我可能无法隔离问题,JIT将干扰我的结果和我为形成前提而进行的测试。事实上,编写一个能够产生有效结果的微基准非常困难。