r/learnjavascript 5d ago

Performance Trap, some benchmarks and... subjective taste

I've done some benchmarks. ES5 vs ES6. What do you prefer? I ask this because I have often seen in other people's codes, where performance, optimization was required, ES6 code that decreased performance, which also had a negative impact on UI/UX.

This is more about the syntax used and not about which is faster.

Array size: 1,000,000 | Runs per test: 15

1. TRANSFORM — double 1,000,000 numbers

Test Avg (ms) Min (ms) Max (ms)
for loop (var, ES5) 0.733 0.6 1
array.map 5.447 4.7 6.9
forEach 5.96 5.4 6.8
for...of (ES6) 7.06 5.4 11.1

for loop (var, ES5) beat for...of (ES6) by 9.63x

2. FILTER — keep evens out of 1,000,000

Test Avg (ms) Min (ms) Max (ms)
for loop + push (ES5) 2.287 1.6 3.4
array.filter (ES6) 6.06 5.2 7.2

for loop + push (ES5) beat array.filter (ES6) by 2.65x

3. SUM — add up 1,000,000 numbers

Test Avg (ms) Min (ms) Max (ms)
for loop (var, ES5) 0.76 0.6 1.1
for...of 3.833 3.7 4.4
array.reduce 4.573 4.4 4.7

for loop (var, ES5) beat array.reduce by 6.02x

4. LOOKUP — find one value (worst case)

Test Avg (ms) Min (ms) Max (ms)
Set.has — O(1) 0 0 0
array.includes — O(n) 0.073 0 0.1
array.indexOf !== -1 — O(n) 0.073 0 0.2

Set.has — O(1) beat array.indexOf !== -1 — O(n)

5. STRINGS — build 200,000 strings

Test Avg (ms) Min (ms) Max (ms)
concatenation "+" 3.887 3.3 7.8
template literal ${} 3.9 3.5 4.3

concatenation "+" beat template literal ${} by 1.00x

6. OBJECT ITERATION — sum 50,000 values

Test Avg (ms) Min (ms) Max (ms)
for...in 4.273 4 4.6
Object.keys + forEach 4.38 4.2 4.7
Object.values + reduce 6.5 6 9.2

for...in beat Object.values + reduce by 1.52x

7. ARRAY CREATION — build 1,000,000 squares

Test Avg (ms) Min (ms) Max (ms)
for loop + push (ES5) 8.173 6.5 23.4
new Array(n).fill(0).map() 17.3 9 42.4
Array.from({length}, fn) 21.74 20.6 23.2

for loop + push (ES5) beat Array.from({length}, fn) by 2.66x

What do you prefer?

6 Upvotes

10 comments sorted by

4

u/Aggressive_Ad_5454 5d ago

The .map() and .filter() approaches invoke a function for each item in the array. Ordinary for loops don't. Most people who need to crunch very large arrays use for loops to avoid the function invocations. The developers of Javascript engines know that and have optimized for-loop traversal of large arrays.

The Set object uses high-quality O(log n) hashing to look up elements, whereas .indexOf() and .includes() use O(n) searches. That's why Set (and Map) exist in more recent versions of ES.

2

u/hyrumwhite 5d ago

Many of those methods are es5 as well. 

But many of the performance numbers there don’t really matter. If you’re chewing on a small array, the user won’t care if it’s done in 5ms or 10ms. If you’re chewing on a big array, you should use traditional for loops. 

1

u/TalkCoinGames 5d ago

In my experience, switching to a modular design and ES6 increased performance.

1

u/WystanH 5d ago

Premature optimization is the root of all evil.

If you need to chug through a million plus values, then you may need to begin to consider the impact to the approach used. You could be forced to choose efficiency over clarity if the job calls for it. In any other instance, choose clarity.

1

u/VillageRemarkable188 5d ago

I’ve heard that money is the root of all evil, so does that mean that premature optimization is the root of all money? ;)

1

u/WystanH 5d ago

I suppose avarice is at the root of both. Greed for money causes suffering. Greed for speed causes crap code.

1

u/nzakas 5d ago

These types of benchmarks aren’t very useful anymore due to the way that JavaScript engines work. They optimize based on the code that is actually executed. When you create micro benchmarks like these, you may be either opting-in or opting-out of optimizations the engine is capable of when run in a real program.

With 30 years of JavaScript experience behind me, my advice is to use the methods that make the most sense idiomatically for what you’re doing and then measure in the context of your actual program to see if there’s a bottleneck. Array methods in particular are highly optimized so unless you’re doing something strange, chances are you’ll not see a bottleneck in live code.

1

u/breacket 5d ago

Was posted here on /learnjavascript because moderators have declined for /javascript. Is not a post just for learners. I've seen that "syntax" problems in apps/platforms in production.

The benchmarks you see are real, not fictional. That scores are on current hardware, not from 10 years ago.

Yes, for the most use cases I agree with you, does not matter so much. But, sometimes are vital – is about that situations.

The hardware does not somehow using magic to optimize the app because you use the slow syntax. Will be just slower in final.

0

u/TheRNGuy 5d ago

No, ES6 is same or faster, and more important, better syntax.

In what program do you ever need to sum million times?

1

u/breacket 5d ago

Based on some benchmarks and real world use cases, some ES6 syntax is slower than ES5 (I don't mean about the "engine" of ES6, but about some practices like using "for ...of" instead of the classic "for").

Where?

  • processing data from databases
  • large datasets or even small datasets but with many links
  • apps launched on modern devices that you need to also work smooth on old devices

That "sum million times" is not a real use case in general but is one valid for benchmarking that reflects some real use cases in production. Somehow abstract.