3

Are there examples of what static compiler could optimize when JIT could not ?

For example, some optimization of C++ compiler which could not be done by .NET JIT ?

SethO
  • 2,703
  • 5
  • 28
  • 38
Old Programmer
  • 546
  • 1
  • 4
  • 17

5 Answers5

9

None. Proof: Take any compiler and use it as a JIT. QED.

However, JIT is limited in execution time, so it's unacceptable to do complex optimizations there.

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
  • 2
    @Thomas: Trying won't prove it for every possible combination of language, compiler, platform, optimization under consideration etc... So trying will prove nothing. See [Proof](http://en.wikipedia.org/wiki/Mathematical_proof). – Yakov Galka Dec 12 '10 at 21:35
  • 2
    Of course it does. The "proof" is correct. And there is already LLVM which can store its intermediate form and do every optimization possible at runtime that it can do at compile time. – Axel Gneiting Dec 12 '10 at 21:38
  • @Axel: actually the IR is not the fully optimized form. There are backends tranformers which take the IR and optimizes it for the final architecture (depending on its instruction set). @ybungalobill: I think you nailed down the most important issue with JIT, since it got to be "fast" it cannot do too much in term of optimization. – Matthieu M. Dec 13 '10 at 07:22
2

This answer has a list of optimizations and strategies used by the JIT optimizer. They are not fundamentally different from what a native code optimizer does.

One constraint in the jitter is that it cannot spend a great deal of time analyzing the code. Every millisecond it burns affects the responsiveness of the program. Two strategies help. Assemblies can be pre-jitted by ngen.exe, all of the .NET assemblies are and it is wise to do the same with your own assemblies. As long as they are 'large', less time might be spent jitting the code than finding and loading the .ni.dll file on disk.

And the jitter compiles code on demand, just before a method starts executing. Which tends to spread the cost over time, relevant to code that runs at human time where responsiveness matters.

One detail worth noting is that a jitter can take advantage of core specific instructions. That's an edge that is largely gone, cores are not that different these days. But it will readily generate 64-bit code on a x64 operating system without doing anything special.

A typical number that's bandied about is that jitted machine code is 85% as efficient as native precompiled code. Take that with several large lumps of salt, the quality and nature of the source code is always first.

Community
  • 1
  • 1
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
1

In general there are no things that a static complier can do that a JIT compiler cannot - since the JIT compiler has all the information that an equivalent static compiler would have - and more. A JIT compiler has one huge advantage - it knows the exact environment the code will be run in.

There may be specific optimizations available in C++ that aren't in C# due to language features. But again it's more likely to be the other way around - it's easier to reason about C# in the absence of pointers for example.

When looking at optimization in C# much of the optimization occurs in the translation from C# to IL, not by the JIT.

James Gaunt
  • 14,631
  • 2
  • 39
  • 57
  • 1
    I'm not sure what the justification is for the last paragraph. Almost none of the optimizations are done by the C# compiler. The C# compiler has a quite weak optimizer. See http://blogs.msdn.com/b/ericlippert/archive/2009/06/11/what-does-the-optimize-switch-do.aspx for details. – Eric Lippert Dec 12 '10 at 23:23
  • I thought I had read that somewhere - but of course I stand corrected. – James Gaunt Dec 13 '10 at 14:12
  • @Eric: Is it intentional that C# compiler has a weak optimizer? I don't know the consequences of introducing optimizations early on, so it this a way to make sure you don't commit optimizations that can't be changed later on? Like is the plan to introduce all sorts of optimizations at once when the time is right? (like when there is some sort of breakthrough) – Joan Venge Dec 13 '10 at 21:14
  • 1
    @Joan: it's simply that the jitter can do a much better job. Remember, the C# compiler just spits IL. Consider an optimization like, say, inlining. We don't know what the machine code size is going to be, we don't know whether on the actual processor what the cost of an extra call vs the cost of an extra cache miss is; without that sort of information, we can't know whether inlining a hunk of IL is a good idea or not, so we don't even bother to try. Many optimizations deal with register scheduling; IL doesn't even have the notion of registers. And so on. – Eric Lippert Dec 13 '10 at 23:41
  • @Eric: Thanks Eric, I got it now. Lastly would it be safe to say that the C# compiler has no code that uses the actual machine specs? Like no code that checks how much memory the compiling pc has, how fast and what type the cpu has, etc? – Joan Venge Dec 14 '10 at 00:07
  • 1
    @Joan: That is correct; the compiler of course cannot assume that the compilation machine has the same specification as the target machine! Developers often have more buff machines than their customers. But more generally, the compiler proper doesn't change its behaviour based on machine specs. The IDE might, and Visual Studio as a whole might. For example, VS could notice that you have a four-proc box and decide to do CPU-bound portions of a build in parallel. I don't know if VS does that or how it works; that is not my area of expertise. – Eric Lippert Dec 14 '10 at 00:37
  • @Eric: Thanks Eric, really appreciate your reply. – Joan Venge Dec 14 '10 at 00:40
1

The primary issue here is run-time and resources. It takes 61 hours to compile Visual Studio- and I don't even know what kind of build machine they have. JITs, however, have to run with a fraction of the machine's real resources and in milliseconds. There's no way that they could possibly optimize as strongly.

Puppy
  • 144,682
  • 38
  • 256
  • 465
0

A static compiler is run well in advance, while a JIT is done shortly before the code is executed. A static compiler has a lot more time to run, and so optimizations which take a long time to perform are often done by static compilers but not by JIT compilers. In principle a JIT could do these optimizations, but the additional time it takes to perform them makes them impractical.


On the other hand, a modern JIT can in some cases make more aggressive assumptions about the code (producing faster code than a static compiler can), because it has the option of falling back to a less-optimized version if those assumptions turn out to be incorrect.

Anon.
  • 58,739
  • 8
  • 81
  • 86