6

I am looking at improving some of our for each loops and created a test benchmark to compare different ways we are using them. The test can be found here.

I was surprised to find out that this code:

function add(val) {
   sum += val;
}
values.forEach(add);

performs better than this one.

 values.forEach(function(val) {
   sum += val;
  });

Aren't these exactly the same? What makes the first code snippet faster than the second one?

GETah
  • 20,922
  • 7
  • 61
  • 103

1 Answers1

6

It's a problem with your test. Your tests are:

values.forEach(add);

and

values.forEach(function(val) {
  sum += val;
});

In the second test, you're timing the creation of the function as well as the execution of the forEach. In the first test, you're not timing the creation of the function; that's done during the setup phase of the test, which isn't timed.

Davin Tryon created a test that creates the functions in both cases:

function add(val) {
 sum += val;
}
values.forEach(add);

vs.

values.forEach(function(val) {
  sum += val;
});

...in which the difference in performance disappears on some engines, and goes the other way (declaration being slower) on some. (The latter is probably that the engine figures out during the test that it can inline the function, or at least skip some of the steps that it can't skip with a declaration.)

enter image description here

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Still, it's good to note that declaring your functions beforehand is faster! – Jonathan Jan 22 '15 at 09:27
  • 1
    @Jonathan: What makes you think that? Provided you create the functions just once rather than repeatedly, declaration vs. expression doesn't matter modulo inlining (see the results from Davin's update I added to the answer). – T.J. Crowder Jan 22 '15 at 09:39
  • Thank you! However, the code where the function is created every time is called multiple times for multiple arrays making the performance even worse. The test I created reflects my production environment and the way it is setup :) – GETah Jan 22 '15 at 09:46
  • @GETah: Well yeah. Creating functions takes non-zero time. If you can create the function *once* and reuse it, of course that's going to be faster. – T.J. Crowder Jan 22 '15 at 09:53
  • @T.J.Crowder: I forked the test and created another where I named the anonymous function passed to `forEach`. It is performing faster than anonymous one. I can't understand the reason behind it. Here's the link to test: http://jsperf.com/for-vs-foreach/272 – Anurag Peshne Jan 22 '15 at 09:55
  • @AnuragPeshne: See the note at the end of the answer about inlining, although a difference as small as in the one data set on that test could just be within the range of measurement error. Where I saw inlining was primarily with Firefox's SpiderMonkey. – T.J. Crowder Jan 22 '15 at 10:06
  • That's what I meant: declaring them beforehand instead of declaring them several times in the loop. – Jonathan Jan 22 '15 at 10:08
  • @Jonathan: Ah, gotcha. Yeah: Don't recreate the same function if you don't have to. :-) – T.J. Crowder Jan 22 '15 at 11:54