3 ms·
I don't think this article is rolling anything too low-level by hand. Avoiding allocations is generally good advice. Compilers have a hard time eliminating th
by pizlonator 10y ago
I don't think this article is rolling anything too low-level by hand.
Avoiding allocations is generally good advice. Compilers have a hard time eliminating them for you and so you can't be guaranteed that the compiler will eliminate a pointless optimization. Any allocation that isn't eliminated brings you one step closer to a GC, and it makes sense to optimize GCs away.
Using bitfields is a classic trick that is harder to do for the implementation than it is for the user. If an implementation wanted to turn a bunch of boolean fields into a bitfield, it would have to first prove that they are all boolean, then it would have to recompile all accesses to those fields into bitfield accesses, and then it would have to walk the whole heap to make sure that there weren't any more objects that used the old shape (separate fields) instead of the new one (bitfield). You could skip the last step if boolean fields were always eagerly represented as bitfields (which would surely slow down start-up time, something that JS implementations don't want to do because page loading is so important) or if you were happy to live with objects having both representations simultaneously (which would slow down every access). I'm guessing that a good implementation would wait for the next GC after realizing that a cluster of fields is proved boolean, and then it would reshape those objects while GCing. So, it would be one of those "maybe you'll get it if you're lucky" optimizations that make you look good on benchmarks but won't really help developers. Even if an implementation did have any version of this trick - even one that worked eagerly, there are so many parts to the proof burden for the optimization that the smart play for users would still be to do the optimization themselves rather than hope that the compiler gets it right.
Finally, I love the no-op function trick. This is not a low-level optimization at all! It's just a simple and clever way to structure your code that results in you getting to hook into the JS implementation's existing watchpoint optimizations: JS VMs will certainly set a watchpoint on a global function pointer that has been immutable so far, and they will definitely inline calls to that function via that global pointer subject to that watchpoint. So, by doing something that looks perfectly clean at a high level you are getting some really gnarly optimizations for free.