5 ms·
Because the JVM has had 27 years of R&D work done to it. If you have a really hot path a JIT will typically continually recompile it in the background with more
by Veliladon 3y ago
Because the JVM has had 27 years of R&D work done to it. If you have a really hot path a JIT will typically continually recompile it in the background with more and more optimization work and start putting the loop through that progressively more optimized code. When you're doing gigabytes of FizzBuzz the JIT will quickly have something pretty comparable to the best native code.
- colmmacc 3y agoIt doesn't matter for FizzBuzz, but in general JIT should really out-perform "native" statically compiled compilers on most real-world workloads. While there's a small penalty for the profiling JIT needs, there are massive gains for data and access dependent optimizations that static compilation can't achieve without explicit hints. For example, a JIT can observe the most commonly accessed data and re-order it to optimize for the pre-fetching pipeline. Or it can re-order operations to optimize for cache-line hotness.
- pkolaczk 3y ago> but in general JIT should really out-perform "native" statically compiled compilers on most real-world workloads. In theory, yes, but in practice I've never seen it happen. Best I ever saw was matching C speed at toy benchmarks. Even in this benchmark here, Java is decent, but does not beat even the naive implementations in C/Rust. Also, AOT compilers can do PGO as well, so they can use the same techniques. But they also have way more time and resources, so they can do things like whole program optimization, which is something JITs cannot do because they have much smaller computation and memory budget. It happened already many times to me that the first naive version of a C/C++/Rust program/function I wrote was already faster than a carefully tuned Java equivalent. AOT compilers for "fast languages" got really good these days. The design of language also influences how well it can be optimized by the compiler. E.g. it might look impressive JVM can devirtualize dynamic calls at runtime, but C++/Rust often don't have to do this at all as programs in those languages tend to have very few virtual calls if any at all.
- AlotOfReading 3y agoIf you didn't need more evidence, the fact that the Java community has been slowly moving towards AoT with GraalVM should cement it. Java's JITs are damn impressive pieces of engineering, but the structural advantages of traditional compilation still win out surprisingly often.
- jabradoodle 3y agoThe move towards AOT is mostly for lower startup times and lower memory usage, not to make the application faster in general.
- DeathArrow 3y ago>Java is decent, but does not beat even the naive implementations in C/Rust. Java doesn't beat C in this benchmark but beats Rust with ease.
- pkolaczk 3y agoThere is not enough data to conclude that. There are 3 Java implementations slower than the faster Rust one, and there are 2 Java implementations faster. But there are only 2 data points for Rust in total. Also, technically there is nothing C can do that Rust can't.
- pier25 3y agoWill V8 be able to do the same some day?
- lordgrenville 3y agoMy understanding is that a statically typed language is inherently faster than a dynamically typed one, no matter how much you optimise the latter. The JS interpreter/VM simply has a lot more work to do than the JVM.
- saagarjha 3y agoNo. Well…it’s complicated.
- xxs 3y agoJava is a lot better source (and target) to optimize for than JS. It's quite bit more work to have all numbers being floating point by default.
- curling_grad 3y agoI think WASM will be the mainstream for frontend before that happens... But you never can't predict the future!
- xxs 3y agooddly enough fizzbuzz stuff likely needs an on the stack code replacement, i.e. compiling and replacing the currently executed code, which tends to be subpar. The submitted code snippets for Java do not need OSR, though... yet they can be improved further, e.g. should drop the use of String entirely (which would not feel very Java). The other attempt to convert int -> String (byte) uses the naive way to divide by 10 on each iteration, Java.'s Integer.toString does it way better. Edit: on a 2nd thought, having a dedicated direct buffer [same allocation, different slices] per all the 8 out of 15 ares for numbers and NOT converting int->String each operation but adding 15 would be a pretty boon as most of the time the change would be only the last 2 bytes, and there won't be any 'div' to be had. Div is generally slow (compared to L1/L2 cache misses, and L3 hit), there is not algorithm to parallelize it, and there is one (few) unit that can perform div, unlike 'add')