5 ms·
I still think that http://steve-yegge.blogspot.com/2008/05/dynamic-languages-strike-back.html http://steve-yegge.blogspot.com/2008/05/dynamic-languages-st... is
by btilly 5y ago
I still think that http://steve-yegge.blogspot.com/2008/05/dynamic-languages-strike-back.html http://steve-yegge.blogspot.com/2008/05/dynamic-languages-st... is one of the best overviews ever of how JavaScript managed to become as fast as traditional compiled languages despite being filled with features to make it slow.
What's amazing is that that talk came out several months before V8, the first JavaScript engine that actually used the ideas in that talk. But, of course, that talk was possible because V8 was already under development.
- bestouff 5y agoIn my experience JS is not as fast as compiled languages.
- nicoburns 5y agoIt's not, but it's much closer than other dynamic languages like Python, PHP, Ruby, etc. For numerical code (which avoids allocation) it's often pretty close.
- hu3 5y agoMicrobenchmarks I know, but it looks like a magnitude slower than C++ to me: https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/node-gpp.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- nicoburns 5y agoI see a factor of 2 in the closest benchmarks. A factor of 4-5 for the middlish ones, and a factor of 10 for the least close. But it's worth noting that a lot of the those C++ examples are making heavy use of SIMD.
- netr0ute 5y agoCan you do SIMD with JS? If not, then C++ has the real advantage.
- pineconewarrior 5y agoSIMD.js was abandoned in browsers but you can use SIMD in WASM.
- mhh__ 5y agoI was about to write that I'd be disappointed if V8 didn't vectorize simple loops, but I googled it and apparently it doesn't so maybe I should be disappointed.
- ygra 5y agoIs there any JIT that does auto-vectorization? I kinda got the feeling from C/C++ compilers that auto-vectorization is brittle and unpredictable even there and that's with all the time an AoT compiler can invest into optimization. A JIT always has to tread the line (or multiple lines in case of tiered compilation) between optimization effort and benefit. And the usual trade-off between larger and smaller code. So speculatively unrolling short loops just to see whether anything could be vectorized is perhaps out of scope for most JITs and even in AoT-compiled languages the preferred way of getting the most out of vector instructions is just to explicitly vectorize hot loops as a programmer, as the result is often better than what the compiler could do.
- kaba0 5y agoYeah the JVM does autovectorization, but this feature is very finicky (everywhere, not only in JIT context). That’s why in Java now you have the Vector API, which allows one to create very low-level, but reliably vectorizable code (with the added benefit of sane fallback to for loops on non-supported CPUs)
- fenomas 5y agoThose benchmarks run the program once from a cold start, right? When people talk about JS nearing c++ performance I think they generally mean cases like the steady-state performance of a game loop, after the JS engine has had a chance to observe the hot code for a little while.
- igouy 5y agoAnd some of those runtimes are 45 cpu secs. If that’s not enough chance to observe the hot code…
- billfruit 5y agoHow about vs Java? How does JS engines compare against the JVM?
- invalidname 5y agoJava is a bit closer to native and works really nicely for AoT with GraalVM. It has the advantage of being more predictable so a JIT can make far more assumptions and doesn't need to revert as many optimizations.
- mhh__ 5y agoYeah, in some informal sorting tests I noticed that Node was roughly as fast as dmd, the D compiler which is basically optimized for fast builds. Compared with LLVM and GCC it wasn't even close.
- Zababa 5y ago> as fast as traditional compiled languages I don't think JS is as fast as traditional compiled languages. Java/C# are faster, Go is faster, OCaml/Haskell are faster, Common Lisp is faster, C/C++/Rust are faster.
- IainIreland 5y agoEh, with the benefit of 14 years of hindsight, I want to push back on some of the things in that talk. (Context: I work on SpiderMonkey.) First, all the stuff about tracing and trace trees is kind of obsolete. SpiderMonkey abandoned TraceMonkey a long time ago. (To the best of my knowledge, V8 never implemented a tracing JIT at all.) The problem with tracing is that you can get really good performance when everything goes right, but it's brittle. There's a reference in the talk to how implementations of the Game of Life can have exponential blow-up, for example. You can usually fix any individual pathological case, but the inherently exponential number of possible paths through a program make it difficult to completely eliminate weird performance cliffs. If your goal is to maximize performance on a known set of benchmarks, go wild. If you want a robust engine that can handle whatever weird code the web is throwing at you, tracing JITs are (as far as I can tell) a dead end. (Counterpoint: LuaJIT seems to be doing alright with tracing, although it may just solve the problem by punting to the programmer: https://github.com/lukego/blog/issues/29 https://github.com/lukego/blog/issues/29. That's more feasible when you don't have multiple engines with performance cliffs in subtly different places.) Second, the idea that JIT-compiled code can be faster than AOT-compiled code has been floating around for a long time, but I don't think it really holds in the general case. Doing work at runtime isn't free: not just time spent compiling, but also time spent profiling and validating that your speculative optimizations continue to be correct. SpiderMonkey had a top-tier optimizing compiler, IonMonkey, that got pretty darn close to native code on hot benchmark loops. We tracked whole-program information to ensure that type checks could be elided in inner loops. (For example, if the `x` property of a certain set of objects only ever contained 32-bit integers, then we could unbox it without checking the type. If any code elsewhere ever stored a non-integer value in that property, we would notice and invalidate the optimized code.) We threw IonMonkey away, because it was too brittle. In practice, real-world code falls off the happy path often enough that we got better performance by accepting that even your highly optimized JS code will include some runtime checks. Invalidation and recompilation are real costs. So is the upkeep of all the global data necessary to support Ion. There's an engineering tradeoff between pushing up the performance ceiling and bringing up the performance floor; we've been happy with our choice to shift focus more towards the latter. Our numbers are down on artificial benchmarks, but it seems to have paid off in real-world performance. (Also, bugs in the optimizing compiler are significantly less likely to be exploitable.) A lot of really smart people have done some incredible work on the JVM. Nevertheless, I'm still not aware of any code written in Java instead of (say) C++ or Rust because Java was faster. I think it's more accurate to say that JIT compilation can be fast enough that the other advantages of the language can make it the right choice.