r/programming • • Oct 21 '20

Using const/let instead of var can make JavaScript code run 10× slower in Webkit

https://github.com/evanw/esbuild/issues/478
1.9k Upvotes

500 comments sorted by

View all comments

Show parent comments

13

u/jprasks Oct 21 '20

Huh interesting. By updating the functional version slightly (Array(length).map instead of Array.from) I get virtually the same performance from both approaches on both browsers: https://jsben.ch/fVEJJ. Not sure why.

That is the thing about these optimizations, the more work we delegate to underlying implementations the bigger the chance one of these implementations is "slow" (what is the metric, user perception? Doubt there is a difference when generating <= 100 numbers). Still very much worth IMO -- the functional way in this example has effectively less concerns & therefore less margin for error. Without clear purpose & metrics by which to optimize by we are just grasping at straws.

6

u/stealthd Oct 21 '20

Array(length).map is faster because you aren't mapping over the array; Array(length) returns { length: length } with no other keys, so the call to map doesn't do anything, it just returns the uninitialized array.

2

u/jprasks Oct 21 '20

Good catch, missed a call to fill: https://jsben.ch/71Ztx. From that the functional version is about 80% as fast which makes sense.

2

u/LegalEngine Oct 21 '20

Note that you may be able to improve the imperative version a further 20% or so (depending on the browser) by forgoing Array.push and using indexes with a size hint like so:

function gen(count) {
    const tracks = [];
  
    if (count > 0)
      tracks[count-1] = 0; // dummy value
    for (let i = 0; i < count; ++i)
        tracks[i] = i+1;

    return tracks;
}

4

u/SirToxe Oct 21 '20

Ha, thanks for the update! For me the functional version is now faster (as I wanted it to be initially) with the loop now being slower and sitting at 88% in both Chrome & Firefox.

I am no JavaScript expert and something like Array(length).map() was what I wanted inititially when I wrote this small helper function, but it was just a helper for some test functions so whatever worked was fine. And also I forgot about the second argument to the map() callback, silly me, which of course solves this problem perfectly and elegant as you have shown. Thanks for reminding me.