What are the advantages of just-in-time compilation versus ahead-of-time compilation?
Solution 1:
Greater portability: The deliverable (byte-code) stays portable
At the same time, more platform-specific: Because the JIT-compilation takes place on the same system that the code runs, it can be very, very fine-tuned for that particular system. If you do ahead-of-time compilation (and still want to ship the same package to everyone), you have to compromise.
Improvements in compiler technology can have an impact on existing programs. A better C compiler does not help you at all with programs already deployed. A better JIT-compiler will improve the performance of existing programs. The Java code you wrote ten years ago will run faster today.
Adapting to run-time metrics. A JIT-compiler can not only look at the code and the target system, but also at how the code is used. It can instrument the running code, and make decisions about how to optimize according to, for example, what values the method parameters usually happen to have.
You are right that JIT adds to start-up cost, and so there is a time-constraint for it, whereas ahead-of-time compilation can take all the time that it wants. This makes it more appropriate for server-type applications, where start-up time is not so important and a "warm-up phase" before the code gets really fast is acceptable.
I suppose it would be possible to store the result of a JIT compilation somewhere, so that it could be re-used the next time. That would give you "ahead-of-time" compilation for the second program run. Maybe the clever folks at Sun and Microsoft are of the opinion that a fresh JIT is already good enough and the extra complexity is not worth the trouble.
Solution 2:
The ngen tool page spilled the beans (or at least provided a good comparison of native images versus JIT-compiled images). Executables that are compiled ahead-of-time typically have the following benefits:
- Native images load faster because they don't have much startup activities, and require a static amount of fewer memory (the memory required by the JIT compiler);
- Native images can share library code, while JIT-compiled images cannot.
Just-in-time compiled executables typically have the upper hand in these cases:
- Native images are larger than their bytecode counterpart;
- Native images must be regenerated whenever the original assembly or one of its dependencies is modified.
The need to regenerate an image that is ahead-of-time compiled every time one of its components is a huge disadvantage for native images. On the other hand, the fact that JIT-compiled images can't share library code can cause a serious memory hit. The operating system can load any native library at one physical location and share the immutable parts of it with every process that wants to use it, leading to significant memory savings, especially with system frameworks that virtually every program uses. (I imagine that this is somewhat offset by the fact that JIT-compiled programs only compile what they actually use.)
The general consideration of Microsoft on the matter is that large applications typically benefit from being compiled ahead-of-time, while small ones generally don't.
Solution 3:
Simple logic tell us that compiling huge MS Office size program even from byte-codes will simply take too much time. You'll end up with huge starting time and that will scare anyone off your product. Sure, you can precompile during installation but this also has consequences.
Another reason is that not all parts of application will be used. JIT will compile only those parts that user care about, leaving potentially 80% of code untouched, saving time and memory.
And finally, JIT compilation can apply optimizations that normal compilators can't. Like inlining virtual methods or parts of the methods with trace trees. Which, in theory, can make them faster.