Does JavaScript (let's say on V8 engine, since it's probably the fastest) that was JIT-compiled perform slower than managed languages that are previously compiled to a byte code (for example Java or .NET languages)?
If yes - why?
I mean I understand that JavaScript requires more time to be parsed compared to a byte code, but after compilation to machine code they should perform equally well since all those languages are similar feature-wise...
First of all, I want to stress that there is no way of giving you a precise answer to this question. There may be situations in which a JavaScript program executing on a JIT VM like V8 or SpiderMonkey outperforms an equivalent program written in Java, executed on the JVM. And there are certainly cases where the opposite is true [1].
Second, it is unlikely that bytecode in itself has any significant impact on runtime performance. Indeed, a modern JVM like HotSpot will end up transforming the bytecode into an internal intermediate representation (IR) for optimized compliation, much like V8 does with the JavaScript source code.
The key difference between Java and JavaScript is the availability of type information (and note that this is a fundamental difference between the languages, not their implementations!). Since Java is statically typed, the compiler knows the type of every variable* at compile time. This means that an expression like a + b denotes a unique operation (such as integer or floating-point addition), whereas in JavaScript it could mean any number of other things too (such as string concatenation). This means that a JavaScript JIT is required to generate code to test for every possible correct and incorrect combination of types, unless it can somehow prove that a and b always take on some specific type(s).
The problem extends beyond primitive types, of course. For instance, what should the JavaScript expression foo.bar evaluate to? It depends on the type of the value in foo, which is unknown at compile time; a naïve implementation would represent objects as hash tables and perform a lookup whenever a property is referenced (needless to say, that would be horrendously slow). In Java, if foo is an instance of some class that declares a public instance variable bar, the compiler can simply generate a load at a constant offset from the start of the object in memory.
The remedy that seems to be most prevalent in contemporary JavaScript implementations is the inline cache (IC), a concept that is given a much better explanation in [2] than I could hope to provide. Since inline caches can be used to gather type information that can be fed to an optimizing compiler, it is entirely possible for a JavaScript program to catch up to a Java program provided that the set of types appearing at each program point is small and stable.
[1] For a couple of examples, see http://benchmarksgame.alioth.debian.org/u32/javascript.php. At the time of this writing, HotSpot beat V8 on most benchmarks.
[2] http://mrale.ph/blog/2012/06/03/explaining-js-vms-in-js-inline-caches.html
(*) Well, it knows the static type of every variable. Of course, if your function takes an argument of type Object it is almost as difficult to reason about as an untyped variable in JavaScript, but the set of operations that can be performed on it is much smaller (for example, there's no Object + Object in Java).
To keep it short, Javascript and Java are very different languages. Statically typed, compiled languages like Java/C# have an extra optimization step at compile time, and the produced bytecode is already optimized for the target architecture, which is a huge advantage if you ask me, and it offloads the runtime a LOT.
The engines that execute Javascript (e.g. V8 or Chakra) have to do much more at runtime, and they do a lot of assumptions/guesses about the structure of objects, expected behavior over time etc. and the inlining, caching and other execution optimizations are much harder to do. The dynamic nature, extensive use of polymorphic objects and other features of the Javascript language are really a problem here. However, if you know the internals of these engines you can do a lot to optimize your code.
Regarding actual runtime performance between Javascript and Java, benchmarks are your best friends. As @Elliot Frisch suggested you can pick a sample algorithm and do the measurements using the V8 command line tools for JS, and the Java command line for Java.
You will probably discover that in some scenarios V8 executed JS comes relatively close to Java (or even C++), but for others it is far slower, and it all depends on optimizations specific to your code, the specific runtime you are targeting and other factors. The number of combinations is huge, so you will not find a single answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With