Another "easy" optimization opportunity: don't use .forEach() unless necessary. I noticed it was used in the benchmark.
.forEach() has the overhead of a function call on every iteration, you can't break out of the loop early if needed, and the scoping is different depending on whether or not you use a classical function or an arrow function.
// After
export enum Options {
None = 0, Flag1 = 1 << 0, Flag2 = 1 << 1, Flag3 = 1 << 2, TotalBits = 3,
}
i would recommend using `const enum` for performance, since it will get inlined.So, my experience with doing this kind of thing(and I did plenty of stuff with Actionscript back when) is that it's actually helpful to write your own codegen, even if you're still targeting the high level environment as output, because then you can define a syntax that clarifies the kind of language butchery you're doing, which in nearly every instance has something to do with allocation. Everything that needs to be fast can be programmed towards a preallocated chunk of integers, and cursors that operate over them. When you need to step outside of that and do something a bit higher level, you just bolt on idiomatic JS code and, you know, reuse objects in your algorithms by doing some load and store ops on them, or making them relative to a stack or a pool or whatever. It doesn't have to be an all-or-nothing thing.
This doesn't slow down game development very much, because, while you are adding a bunch of non-idiomatic, less debuggable stuff, again, your bottleneck is almost always about allocation and stuff that just needs to be a fast "array of whatever." Sometimes you iterate over the array, sometimes you indirect or you have a temporary buffer. But it's something that you can plan to have not be totally perfect and still address a hotspot where you would be allocating thousands of times a frame otherwise and thrashing the GC.