Ask HN: What are the hidden performance tricks for JavaScript?
I am currently working on a heavy JS-based tool where every millisecond counts. I've been searching for lesser-known JavaScript performance tricks that go beyond typical optimizations like using web workers or removing unused code. It feels like uncovering hidden knowledge.
One discovery I've made is that using new Array is significantly faster than Array.from or push()[0].
Could you share any similar insights or lesser-known performance optimizations you've come across?
[0] https://www.measurethat.net/Benchmarks/ShowResult/506720
16 comments
[ 3.0 ms ] story [ 48.8 ms ] threadThis makes no sense to me, since checking type is supposedly the first step of each equality operator’s algorithm, but this is the result JSBench keeps returning me.
• Learn Rust! When I learned how memory worked, it made me a much better JS dev.
• Check out Casey Muratori's courses on performance. Some are free on YouTube.
• Start from scratch with a data-oriented approach. What bits do you need to move around, and why? What's the best way to store and shape those bits?
• Can/should you use WASM instead?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
I don't know what you've tried already, but typically SVGs are very slow to work with. If you're drawing to a canvas anyway, you should see if you can skip the XML altogether and do the math to draw directly to the canvas (or use a helper lib like Konva or Pixi or D3 etc.). Can any of the line generation and stringification be offloaded to WASM, which can often be several times faster than JS? Can any of it be offloaded to a GPU, depending on which platforms you need to support?
I'm still not sure what the actual use case is for a bunch of random polylines (is it a visualization of something? a scientific calculation? background graphics?). If they don't represent any actual data and are just a graphical nicety, can you fake them somehow (bitmap sprites with different transformations)? And does it have to happen client-side in real time (can you just prerender it?)?
This isn't necesarrily unknown, but knowing that there's a cost associated with promises and async/await will get you pretty far in terms of performance. I remember the idea first clicking when I watched this : https://www.youtube.com/watch?v=SMBvjmeOotA
The video you posted is a bit chaotic, so I don't really want to watch 1.5 hours just to get something that could be summarized in one line. But anyway... I understand the downsides of promises calls, but there are also advantages, such as not blocking page rendering, which I heavily rely on.
Never use .forEach(), always use a for loop. Same applies to methods like .map().
Some calculations are just much more expensive to do than others. Exponentiation for example is much more expensive than multiplication. You want to write your code in a way that not only considers the total number of operations, but also minimises expensive operations.
Caching can help if you're doing repetitive computations.
If you're absolutely pushing performance to the max you will probably want to look at doing some clever stuff with WebGL2, WASM or Web Workers. Wherever you can avoid this though I would recommend it because it will make your code much more complicated and won't even necessarily out perform because of overheads.
Edit: Also check out this guy on YT, https://www.youtube.com/watch?v=WLwTlC1R2sY He does some really interesting deep dives into JS performance.
Do you mean TypedArray? [0]
> Never use .forEach(), always use a for loop. Same applies to methods like .map().
I just found it out yesterday [1]. It's a nice trick. I already changed all forEach (even tho it maked my eyes a little bit wet).
> some clever stuff with WebGL2, WASM or Web Workers
I already use Web Workers with async calls to divide main task into smaller pieces and not to block main render. But I am pretty new to this concept so I don't grasp fully what is the overhead of using this method.
Thank you for the video - will check it now.
[0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
[1] https://leanylabs.com/blog/js-forEach-map-reduce-vs-for-for_...
Yes, generally you'll want Float32Array, but I guess which TypedArray you'll want to use in your code use will depend on use.
> I already use Web Workers with async calls to divide main task into smaller pieces and not to block main render. But I am pretty new to this concept so I don't grasp fully what is the overhead of using this method.
If you can you'll want to use a "transferable object" to reduce overheads when passing data into worker thread, https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers...
If you're using Web Workers this is a great video to watch and it discusses "transferable objects" around the 7 minute mark, https://www.youtube.com/watch?v=pQPqhZRUz3U
The other thing I forgot to mention was to avoid using async/await wherever possible. I'm guessing you're not using it unnecessarily anyway, but it will add a significant overhead to your method calls if you are.
always remember the fastest code is the code that is not executed at runtime.
https://github.com/prettydiff/wisdom/blob/master/performance...
The techniques mentioned are stupid fast to the fewest milliseconds, but most JavaScript developers find this incredibly unpopular.
Use chrome profiler