Dan*_*iel 50 javascript performance
我创建了四个不同的函数,如下所示:
var normal = function() {
return;
};
var control = function() {
return;
alert("Hello, world!");
};
var withArguments = function() {
return;
arguments;
};
var withEval = function() {
return;
eval("");
};
Run Code Online (Sandbox Code Playgroud)
由于他们都什么都不做并立即返回,我希望他们所有人都能拥有相同的速度.但是,经过测试它jsPerf,我发现normal和control执行大致相同,但withArguments和withEval执行速度要慢得多.
为什么这些未执行的声明会对性能产生任何影响?由于他们从未被执行过,他们怎么可能有任何影响?
Pet*_*son 64
简而言之,调用eval函数内部并能够访问arguments数组都在函数调用期间使用额外的设置.如果已知既不执行arguments也不eval执行,则可以跳过此额外设置.
编译器不会尝试预测arguments数组是否实际被访问或是否eval实际被调用,它只会检查它们是否存在于函数中.
arguments在运行时调用使用该arguments对象的可变参数函数比不使用该arguments对象的"普通"函数更昂贵.
在arguments声明对象时绑定执行环境所需的额外步骤在ECMA-262标准的第10.6节中指定.创建arguments对象是一个有点昂贵的15步过程.基本上,arguments必须使用传入的参数填充,并且必须创建.caller和.callee属性.
标准表示arguments当函数进入其执行上下文时应该创建对象,除非已经在名为的函数内声明了参数,变量或函数arguments.
出于优化的目的,大多数浏览器实际上并不创建参数对象,除非函数实际在某处使用它(即使在a之后return).这就是为什么在arguments引用时会看到性能损失的原因,即使从不执行包含它的行也是如此.
eval输入eval代码(如ECMA-262标准的第10.4.2节所述)需要创建特殊的执行上下文.基本上,它必须将调用函数的执行上下文的所有属性绑定到eval上下文.
如果eval在一个函数中调用了多个s,它们基本上都会执行两次相同的过程.为了优化,如果浏览器检测到eval函数中有一个(即使在a之后return),它会预先填充每个eval可以使用的新执行上下文,这样就不需要多次重新创建它.
请注意,这些优化是依赖于浏览器的,并且不是标准所要求的,因此某些浏览器可能实际上不会执行所描述的优化,或者它们可能以不同的方式执行操作.
| 归档时间: |
|
| 查看次数: |
1731 次 |
| 最近记录: |