3

I noticed some unexpected result during working with big arrays in js. In my test I'm creating big array of some class instances with for loop and within loop I'm assigning same string to all object's "x" property and after array initialization doing some calculation with this array. If constructor initializes "x" property with null, array always processing better, even if it's doing extra statement. Why this is happening ? Here is my code for testing. I tested in on chrome.

function f1() {
    var P = function () {
        this.value = 1
    };
    var big_array = new Array(10000000).fill(1).map((x, index)=> {
        p = new P();
        if (index > 5000000) {
            p.x = "some_string";
        }

        return p;
    });
    big_array.reduce((sum, p)=> sum + p.value, 0);
}

function f2() {
    var P = function () {
        this.value = 1;
        this.x = null;
    };
    var big_array = new Array(10000000).fill(1).map((x, index)=> {
        p = new P();
        if (index > 5000000) {
            p.x = "some_string";
        }

        return p;
    });
    big_array.reduce((sum, p)=> sum + p.value, 0);
}


(function perform(){
    var start = performance.now();
    f1();
    var duration = performance.now() - start;

    console.log('duration of f1  ' + duration);


    start = performance.now();
    f2();
    duration = performance.now() - start;

    console.log('duration of f2 ' + duration);
})()

Output:

duration of f1 14099.85
duration of f2 11694.175000000001
4
  • That's probably noise. In my case they are the same. Plus i couldn't figure the point of reduce operation in the test. Commented Jun 25, 2016 at 17:30
  • It could be due to the fact the in f2 you have one extra statement inside of the P function, which probably slows down the overall performance. Running the same code on my computer gives me: ~2233 for f1 and ~5913 for f2.. Commented Jun 25, 2016 at 17:31
  • Sorry guys I didn't copy whole code, I changed question, now its clear, unexpected behavior is that f2 always performes better, even it doing extra statement. Commented Jun 25, 2016 at 17:45
  • Doesn't matter here, but still you should make p a local variable Commented Jun 25, 2016 at 19:15

2 Answers 2

3

In my Firefox browser f2 runs approximately 4 times faster than f1. The reason is that the Just-in-Time JavaScript compiler tries to optimise code based on expected object structures. As mentioned on mdn:

Fortunately, objects and properties are often "predictable", and in such cases their underlying structure can also be predictable. JITs can rely on this to make predictable accesses faster.

This predicting will of course work better if properties are "declared" within the object constructor, which is where the optimiser will look for doing its magic.

Once a structure is assumed, it becomes more costly to still added a property "later".

However, there are different engines out there, which have different optimisers, and so this result can be very different on different browsers. But it seems good practice to include the definition of properties in the constructor, even when their value is not yet known.

This will bring improvement for those engines that benefit from that, and will not bring much of a cost in performance on other engines. Also it may increase readability of your code.

I tested this on Windows 10, FF 47.0 and Chrome 51.0.2704.106, and got these results:

        FireFox     Chrome
 --------------------------
 f1      6,400      11,400
 f2      1,700       9,600     

These are averages over several runs.

Sign up to request clarification or add additional context in comments.

4 Comments

Interesting, seems chrome doesn't do this?
Or maybe Firefox doesn't do it that well in the case of the f1 scenario... depends how you look at it ;-). A cross-browser test on the same machine would be interesting.
@loxxy Chrome definitely does it (/did it circa 2012) with great deltas in performance between the two ("great" being subjective, based on what you're actually changing and how many you're changing). If they've improved their compiler and data-structures to the point where the difference is negligible then that's great. There are some good Google dev talks from around that time, on high-performance code in Chrome as a basis for how other browsers would likely start to behave.
Well, I have to take back my previous comment. I just tested on Chrome and FF, and FF stands out in how fast f2 is executed. See paragraph I added to my answer.
0

Not surprisingly, there was no (or little) performance difference for me & this is the result I got...

duration of f1  11782.384999999951
duration of f2 11347.524999999965

If you tried it in browser console, & tested only once, it is possible that f2 got staled a bit for that particular test.

4 Comments

Even calling the f1 function twice shows different results. This kind of benchmarking is pointless and doesn't prove anything.
I changed question, now its clear, unexpected behavior is that f2 always performes better, even it doing extra statement. I forgot to add if statement, which is the key of difference rasults.
@VahagnNikoghosian sorry, it still doesn't produce any noticeable difference.
@loxxy just doubling array and if statement size, I'm getting 5 second diff(30 and 25).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.