Hacker News new | past | comments | ask | show | jobs | submit login

It seems to me there is no reason we shouldn't be able to create an "optimizing babel" that could be doing performance optimizations based on the target JS engine and version, as a build step. I don't think we need to go to a completely different source language and a compilation to WASM in order to get permission to create such an optimization tool.

Such a tool would give you the benefits you're praising about the WASM compilation workflow: Separately maintained, engine-specific optimizations that can be applied at build-time and don't mess up the maintainability of your source code.




But what if I want to target all the engines, including future ones? The compiler could compile separate versions for each engine, I guess, and you could choose which one to load at runtime based on the UserAgent string ... but even then everyone would have to recompile their websites every time a new browser version comes out.

The advantage of WebAssembly is supposed to be (I think) that it's simpler and will give more consistency between browsers, so browser behaviour will be less surprising, and you can thus get away with compiling a single version.

And if you take this approach of compiling JavaScript to a simple and consistent subset of JavaScript that can be optimized similarly in all engines, you'd end up more or less targeting asm.js, the predecessor to WebAssembly. :)


JS engines already do insane levels of optimization, and they do it while watching the code execute so they understand the code better than any preprocessing tool can hope to.

What could a tool like you're describing do that the engines don't do themselves?


I assume that JITs don't do very expensive optimizations because they have to do a trade off between execution speed and compilation time. JITs are also fairly blind on the first execution of a piece of code. Static optimizations are not made obsolete by the existence of JITs.


Expensive optimizations like what? Can you give a before/after example of something such a tool might do?

(Note: I'm glossing over the case where one is using bleeding-edge syntax that a JS engine doesn't yet know how to optimize. In that case preprocessing out the new syntax is of course very useful, but I don't think this is the kind of optimization the GP comment was talking about.)


JIT engines usually don't do static analysis. I'm not sure if that is because the cost for that is that much higher, but a hint towards why could be that the engine simply does not know which parts of the (potentially huge amounts of) code that was loaded is actually going to be needed during execution, so analysing all of it is likely to bring more harm than gain.

As an example for something that static analysis could have caught, take the example from the article about the "Argument Adaptation"[0]. Here the author uses profiling to learn that by matching the exact argument count for calling a function, instead of relying on the JS engine to "fix that", the performance can be improved by 14% for this particular piece of code. Static analysis could have easily caught and fixed that, essentially performing a small code refactoring automatically just like the author here did manually.

[0] http://mrale.ph/blog/2018/02/03/maybe-you-dont-need-rust-to-...


I replied in main to your other comment, but regarding the "Argument Adaptation" issue it's maybe worth noting that I'm 90% sure V8 would have optimized this automatically if not for the subsequent issue (with monomorphism). I'm dubious that the former issue could be statically fixed as easily as you suggest, but either way I think it should be considered a symptom of the latter issue.


Well, for one, the compiler could rearrange key assignment of similarly shaped objects, so that they actually are similarly shaped objects to the JIT .... but that seems like really dangerous territory


Something like that would probably speed up more code than it breaks, but it would be a breaking change, so probably not what could be strictly considered optimization.


The author has proven exactly this point: By going through a number of engine-specific / implementation-specific code transformations they have achieved a significant performance boost for hot code, which, for whatever reason, the JS engines themselves failed to attain with the optimization repertoire they already have.

Also, remember that JS engines are not all-powerful and all-knowing in their optimization techniques, it's still just a limited number of individually imperfect humans working on them, just like the rest of us. So naturally there are going to be opportunities for other humans to utilize and help complete the picture and increase the overall value and effectiveness.

Maybe in this case there is room specifically for a JS-syntax-level tool that also has more freedom in terms of execution time and related concerns, because it can execute at build-time, potentially pull in or bundle much more information about optimizations with it (imagine using (potentially expensive) ML model to search for probable performance wins, actually do micro- or macro-benchmarks during the build step), be maintained outside of the implementation of a JS engine and thus have the additional benefits of a potential broader contributor base and a faster and more focused release cycle, etc. Or this may not be a good idea after all. I cannot tell. All I know is that if we actually do see that there are and will continue to be optimization gaps in the JS engines themselves, then there is a way to fill them, and likely without having to switch to basically entirely different (frontend) technology stacks.


> By going through a number of engine-specific / implementation-specific code transformations they have achieved a significant performance boost for hot code, which, for whatever reason, the JS engines themselves failed to attain with the optimization repertoire they already have.

I think you're mischaracterizing what happened a little. Most of the author's improvements weren't engine- (or even JS-) specific, they were algorithmic improvements. But for the first two that were engine-specific, it's not like he applied a rote transformation that always speeds up scripts when you apply it. Rather, the author (himself a former V8 engineer) saw from the profile results that certain kinds of engine optimizations weren't being done, and rewrote the code in such a way that he knew those specific optimizations would take place as intended. Sure, a deep ML preprocessor might do the same - but only after trying 80K other things that had no effect, and on code that wasn't even hot, no?

More to the point though, it strikes me that you say JS engines aren't all-powerful, but in the same breath you seem to assume that just because V8 didn't optimize the code in question that it can't. It seems very likely to me that any case you can find where a preprocessor improves performance is a case where there's a fixable engine optimization bug. Sure, in principle one could build a preprocessor for such cases, but it seems more useful to just report the engine bugs.


You're basically describing asm.js -- a subset of javascript that is known to be easy for engines to turn directly into native code and execute, that you can use as a compilation target.

The difference between asm.js and WASM is mostly just that WASM is more compact and easier to parse, while asm.js is a more gradually compatible upgrade story.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: