I have created four different functions, like this:
var normal = function() {
return;
};
var control = function() {
return;
alert("Hello, world!");
};
var withArguments = function() {
return;
arguments;
};
var withEval = function() {
return;
eval("");
};
Since they all just do nothing and immediately return, I would expect all of them to have the same speed. But, after testing it on jsPerf, I find that normal
and control
execute about the same, but withArguments
and withEval
execute much more slowly.
Why would these unexecuted statements have any performance impact? Since they're never executed, how is it possible for them to have any effect?
In short, calling eval
inside of a function and being able to access the arguments
array both use extra set-up during function invocation. If it is known that neither arguments
nor eval
will be executed, this extra set-up can be skipped.
The compiler does not attempt to predict whether or not the arguments
array will actually be accessed or whether eval
will actually be called, it only checks whether or not they exist in the function.
arguments
It is more expensive during runtime to invoke a variadic function that uses the arguments
object than a "normal" function that doesn't use the arguments
object.
The extra steps required to bind the execution environment when the arguments
object is declared are specified in §10.6 of the ECMA-262 standard. Creating the arguments
object is a somewhat expensive 15-step process. Basically, arguments
has to be populated with the passed-in arguments, and the .caller
and .callee
properties have to be created.
The standard says that the arguments
object should be created when a function enters its execution context, unless there is already a parameter, variable, or function declared inside the function named arguments
.
For purposes of optimization, most browsers do not actually create the arguments object unless the function actually uses it somewhere (even after a return
). This is why you see a performance hit when arguments
is referenced, even when lines containing it are never executed.
eval
Entering eval
code, as specified in §10.4.2 of the ECMA-262 standard, requires creating a special execution context. Basically, it has to bind all the properties of the calling function's execution context to the eval
context.
If there are multiple eval
s called in one function, they will basically both be doing the same process twice. For optimization, if browsers detect that there is an eval
in the function (even after a return
), it pre-populates this new execution context that every eval
can use, so that it doesn't need to be recreated multiple times.
Note that these optimizations are browser dependent and not required by the standard, so some browsers might not actually perform the optimizations described, or they might do things differently.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With