Skip to main content

News

Topic: Javascript array size and performance (Read 226 times) previous topic - next topic

  • Rhuan
  • [*][*][*][*]
Javascript array size and performance
Every Javascript tutorial on arrays says make your arrays with var array_name = []; unless you have all the values at the start and can do it explicitly.

Additionally if you read up on fast loop performance you're told to do:
Code: [Select]
var i = number_of_interations;
while(--i)
{
  //do stuff
}

Put this together and the way to fill a large array is apparently to do:
Code: [Select]
var i = planned_array_size;
var array_name = [];
while (--i)
{
  array_name[i] = insert_value_or_function_call_here;
}

I've spent a bit of time recently looking at the comparative Javascript performance of JavascriptCore (Safari), SpiderMonkey (Firefox) and V8 (Chrome).

One thing that stood out to me was a test where SpiderMonkey and V8 destroyed JavascriptCore by a factor of almost 100, the test was meant to be about Math.trunc performance vs bitwise operators but Safari just performed like a dog in all cases. The test's preparation code was using the above syntax to fill a loop with random numbers then in the test was looping through the array flooring them and adding them up.

I found that if I changed the preparation code to loop forwards suddenly safari scored highest, changing it to set the array size with the array constructor advance made it perform even better. Notably this changes improved performance in all browsers though Safari in particular went to the top.

Conclusions:
Primary: you don't want to dynamically resize arrays backwards it kills performance; use the Array Constructor to size it
Secondary: Safari's JS engine is crazy fast when it's not dynamically resizing (as in it curb stomps V8 in a lot of tests I've been doing)

Try running this in a couple of browsers then consider bringing back that array constructor :):
https://jsperf.com/array-creations/1

(I note that those tests only show creation speeds, it was access speeds that pointed me to the issue, for those try out these two test pages and compare - I note the differences here are smaller except in Safari:
https://jsperf.com/or-vs-floor/43
https://jsperf.com/trun-vs-or
  • Last Edit: August 19, 2017, 07:53:48 am by Rhuan

Re: Javascript array size and performance
Reply #1
Firstly, I want to say that when it comes to optimization, never ever assume something is faster "because it should be."  Besides the issue of testing your assumptions, there's also the problem of readability/understandability vs speed, and if you're going to be sacrificing one, you'd better be making up for it with the other enough to warrant the change, and you better know how much you're gaining in one area over the other. 

Case in point, the ++i vs i++ debacle in C++.  When i is an integer, it's argued that ++i should be faster since it increments i, and then returns it (2 ops), instead of i++ which stores the value of it, increments i, and then returns the stored value (3 ops).  Since the 486 era of cpus, these two should actually go the same speed since each core of a cpu can do a limited number of operations in parallel (if the operations are independent of each other), so both end up returning after 2 ops.  Moreover, in the case of loops, i++ should actually be faster since it can do the loop check while it's storing i, so if the value of i is not immediately used in the loop, it can start the loop after 1 op whereas ++i has to increment the i and then do the check.  But, really this is all a mute point because compilers will optimize out stuff like this anyway, so why the hell bother in the first place?  If your code needs to know the difference between i++ vs ++i, then you're making your code more complicated and harder to understand for an optimization that doesn't even exist anymore.  The only case where ++i vs i++ makes a difference is when i is a complicated class and you're overloading ++ (though I'd worry about this as well since it's also potentially making the code less readable).

So the moral of that story?  Don't listen to other people, and test your optimization assumptions to make sure there is a speed gain and that it's worth the reduction in readability.  Don't even listen to my argument above, test the difference between ++i and i++ yourself in your compiler, language etc.

Ok, with that out of the way, I would always use the standard for loop to add stuff to an array.  For the reverse fill example you gave, my guess is that JavascriptCore doesn't realize that your array is going to be a fixed-size array and should be implemented as a list type instead of a hashmap.  Once you do it in the forward direction the compiler figures out it should be working on a vector and does it that way.  Then with the fixed size array, it knows from the start how big to make the list ahead of time.