Back when JavaScript interpreters were still slow, avoiding a function call inside a performance-critical code was very much recommended. With the recent improvements to the modern JavaScript engines, this practice becomes less relevant. One important feature which reduces the need to worry about function call overhead is automatic function inlining.
Consider the following code:
function square(x) {
return x * x;
}
function f(x) {
var sum = ;
for (var i = ; i < x; i++) {
sum += square(i);
}
return sum;
}
If x
is a large number, invoking f(x)
will cause a lot of function call to square
. Even if the overhead is small, it can become significant when accumulated over a bazillion calls. This promotes the best practice of avoiding function calls within such a loop.
Fortunately, a modern JavaScript engine may sense that this part of the code is pretty hot (due to the extensive loop) and decide to optimize it. Among many others optimization, a simple thing to do is not to invoke square
for every iteration. Since the implementation of that function is rather simple and it does not have any side effects, it is rather easy to inline it automatically. In other words, your code would be executed as if you would have written it this way:
function f(x) {
var sum = ;
for (var i = ; i < x; i++) {
sum += i * i;
}
return sum;
}
How can we verify this? Here is one possible approach: by using V8 debugger shell (as described by Florian Loitsch). First, let add some more lines to the original code for the purpose of stressing the execution:
for (var x = ; x < 10000; ++x) f(1e4);
Now, if you have built V8 and get its debugging shell d8
, it’s a matter of running:
d8 --trace-inlining sum.js
which will give (among other informational messages):
Inlined square called from f.
indicating that V8 finally decides not to invoke the function too many times and to just inline it.
If you always worry about manual function inlining, this is a good time to revisit that thought. Simply write the code to be readable even if it means breaking the code into multiple small functions! In many cases, we can trust the modern JavaScript engines to automatically inline those functions.