0

Lately I've been really digging into JS performance, and this other question of mine Javascript Array Performance lead me to this problem.

Problem: Looping using a global variable seems to be WAY faster than iterating using a local variable, can anyone explain to me, why is that ? --- This has just been my error in JSPerf understanding, but Problem 2 still remains, but I guess there is no real answer to it, the rest has been discussed with @Igor-Raush in chat --- Or so I thought, that test in JSPerf is still 100x faster, then the basic version ...

  • I am pretty sure it isn't local variable creation

You can see this behavior here: http://jsperf.com/fastest-array-loops-in-javascript/420 -- I added the last two tests, but the last one did not work, for some reason, so I removed its contents

Problem 2 (extra question, kind of related): Why is that when you run the tests on JSPerf individually ( for some of them ), their performance is consistently COMPLETELY different, than when they are all ran at once ? ( You can see this on While length-- test )


I am testing this, because ( If you went to my other question ), I do not believe that looping over my array should be as slow as it is, in the tests.

Community
  • 1
  • 1
user1494173
  • 169
  • 1
  • 4
  • 11

1 Answers1

1

Problem 1

The reason for the vast performance "improvement" in the global case is that you are initializing a global it = 0 in the preparation code. In JSPerf, each test case is run for multiple trials. The first time your test case is run, it increments the global it until it exceeds arr.length.

The next time (and all subsequent times) the test case is run, the condition it < arr.length evaluates to false, and the loop is not even entered. This is not the case in the "While loop, basic" test case where var i = 0 is initialized before every trial.

You can see in this Plunker that using a global iterator variable is approximately twice as slow as using a local one (open console to see results).

Problem 2

One possible reason for high variance in performance is that running all tests could cause the array to be cached closer to CPU by the time the later test cases are run. When you run a test case stand-alone, it may require memory access. For something as basic as for/while iteration, memory access is a real bottleneck. However, this is just one possible explanation.

Igor Raush
  • 15,080
  • 1
  • 34
  • 55
  • 1. Oh damn, you are absolutely right, that completely slipped my mind, for some reason I thought jsperf would "restart" all used variables between each iteration, dumb of me, sorry. ( And I just checked, teardown does not work between iterations ) 2. I see, that could explain it, but a ~300x speedup ? Guess I need to try to find another explanation for that super slow search in the other question, it really bothers me, that running the .get function yields exteremly promising results, but running the same function in a test function within a loop ( even with a single iteration ) is slow. – user1494173 Oct 14 '15 at 19:27
  • I was seeing about a 20-25% slowdown when running the "While length--" case stand-alone vs. when running all tests. – Igor Raush Oct 14 '15 at 19:32
  • Also don't underestimate the slowdown due to cache misses. A well-known example demonstrating effects of caching and spatial locality is in-order vs. reverse iteration. See this [Plunker](http://plnkr.co/edit/DBicYo1CAu4xpxVXA6M0?p=preview). In-order iteration is much more cache friendly on a good optimizing compiler, since it will pre-load blocks of the array into cache. The speedup I see in Chrome is about ~30k times! – Igor Raush Oct 14 '15 at 19:58
  • That is the most bizarre thing, because, and I will copy the results here all tests - 309,169,504 ops/sec stand-alone - 490,824 ops/sec Yeeeah, I see something like 600x slow down, pretty weird, don't you think ? – user1494173 Oct 14 '15 at 20:00
  • Exactly, I know, but Firefox in this situation is doing some super funky stuff, I don't understand any of it. I have no idea why would a cache unfriendly decrementing loop be faster, than a normal loop. – user1494173 Oct 14 '15 at 20:01
  • Yes, that's very strange. I guess I am trying to say that JSPerf benchmarks of things like iteration are tricky to set up to be consistent and reliable. The Plunker I posted in the comment above shows more or less consistent results in latest FF, Chrome, and Safari. Sometimes I prefer to benchmark things this way because I can see and control exactly what's going on. – Igor Raush Oct 14 '15 at 20:16
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/92320/discussion-between-user1494173-and-igor-raush). – user1494173 Oct 14 '15 at 21:30