javascript V8优化和"泄漏的参数"

时间:2015-05-14 10:23:33

标签: javascript v8

我在various places中读到,谨慎对待arguments对象,这是可行的......

    var i = arguments.length, args = new Array(i);
    while (i--) args[i] = arguments[i];

但是,这样可以吗?...

function makeArray (l) {
    var i = l.length, array = new Array(i);
    while (i--) array[i] = l[i];
    return array;
};
//...
//EDIT: put the function on an object to better represent the actual case
var o = {};
o.f = function (callback) {
    var args = makeArray (arguments);
    callback.apply(args[0] = this, args);
};

"泄漏的论点是什么意思"以及它如何影响优化?

我专注于V8,但我认为它也适用于其他编译器?

证明它有效......



function makeArray (l) {
    var i = l.length, array = new Array(i);
    while (i--) array[i] = l[i];
    return array;
};
//...
//EDIT: put the function on an object to better represent the actual case
var o = {};
o.f = function (callback) {
    var args = makeArray (arguments);
    callback.apply(args[0] = this, args);
};
o.m = "Hello, ";
function test(f, n) {
    alert(this.m + " " + n)
}
o.f(test, "it works...")




2 个答案:

答案 0 :(得分:8)

arguments的问题与本地evalwith的问题相同:它们会导致别名。 Aliasing defeats all sorts of optimizations因此,即使您启用了这些函数的优化,您最终也可能只是浪费时间而这是JIT的一个问题,因为在编译器中花费的时间不是花费时间来运行代码(尽管优化中的一些步骤)管道可以并行运行。

由于arguments泄漏导致的别名:

function bar(array) {    
    array[0] = 2;
}

function foo(a) {
    a = 1;
    bar(arguments);
    // logs 2 even though a is local variable assigned to 1
    console.log(a);
}
foo(1);

请注意,严格模式消除了这一点:

function bar(array) {    
    array[0] = 2;
}

function foo(a) {
    "use strict";
    a = 1;
    bar(arguments);
    // logs 1 as it should
    console.log(a);
}
foo(1);

然而,严格模式也没有得到优化,我不知道任何合理的解释,除非基准测试不使用严格模式,很少使用严格模式。这可能会改变,因为许多es6功能需要严格模式,es6中不需要arguments所以...

答案 1 :(得分:1)

这是一个双重问题:

  1. 您将失去所有可能的优化和分支预测 arguments对象无法预测。
  2. 你泄漏了记忆。真糟糕!
  3. 请考虑以下代码(运行风险自负!):

    
    
    function a(){return arguments;}
    
    x=a(document.getElementsByTagName('*'));
    
    window._interval=setInterval(function(){
    
        for(var i=0;i<1e6;i++)
        {
            x=a(x);
        }
    },5000);
    &#13;
    *{font-family:sans-serif;}
    &#13;
    <p>Warning! This may overheat your cpu and crash your browser really badly!</p>
    
    <p>I'm not responsible for any software and hardware damages!</p>
    
    <p><b>Run at your own risk!!!</b></p>
    
    <p>If you ran this code, press F5 to stop or close the browser.</p>
    
    <p>If you want, you can try to <button onclick="window.clearInterval(window._interval);window.x='';">stop it</button>. (the RAM may remain unchanged)</p>
    &#13;
    &#13;
    &#13;

    现在看着你的RAM上升,当你运行时(它每5秒钟以大约300-500MB的速度上升)。
    简单地传递参数的简单实现可能会导致这些问题。

    更不用说你的代码(通常)会慢一些。

    请注意:

    &#13;
    &#13;
    function a(){return arguments;}
    function b(arg){return arg;}
    
    x=a(document.getElementsByTagName('*'));
    
    window._interval=setInterval(function(){
    
        for(var i=0;i<1e6;i++)
        {
            x=b(x);
        }
    },5000);
    &#13;
    *{font-family:sans-serif;}
    &#13;
    <p>This may be safe, but be careful!</p>
    
    <p>I'm not responsible for any software and hardware damages!</p>
    
    <p><b>Run at your own risk!!!</b></p>
    
    <p>If you ran this code, press F5 to stop or close the browser.</p>
    
    <p>If you want, you can try to <button onclick="window.clearInterval(window._interval);window.x='';">stop it</button>.</p>
    &#13;
    &#13;
    &#13;

    不会产生与以前的代码相同的效果 这是因为b()返回相同的变量,而不是对新arguments对象的新引用 这是非常重要的区别。