6

Recently I took part in a discussion over the efficiency of Java. As I listened, plenty of arguments against Java were that interpreting is "extremely time consuming" and because of it even simple Java programs run way slower than similar one's compiled directly to machine code.

An answer to that was that Java code is often compiled directly to machine code, if only JVM calculates it makes program faster than if it was interpreted in a standard way.

My questions are: when does JVM actually "decide" to perform just-in-time compilation? What are the criteria that make JIT more efficient than standard bytecode interpreting? I mean, the compilation takes some time itself, and as far as I understand, it is all supposed to happen when the program is already running?

3yakuya
  • 2,622
  • 4
  • 25
  • 40

1 Answers1

10

This varies widely depending on your JVM and its settings. Wikipedia:

For example, Sun's Java Virtual Machine has two major modes—client and server. In client mode, minimal compilation and optimization is performed, to reduce startup time. In server mode, extensive compilation and optimization is performed, to maximize performance once the application is running by sacrificing startup time. Other Java just-in-time compilers have used a runtime measurement of the number of times a method has executed combined with the bytecode size of a method as a heuristic to decide when to compile.[4] Still another uses the number of times executed combined with the detection of loops.[5]

A rough approximation for a vanilla HotSpot JVM in -server mode is that JIT occurs when the JVM notices that a certain method has been called a lot, usually more than some specific number of times. (This is why the JVM is called "HotSpot" -- because it identifies and optimizes "hot spots" in your code.) At this point, the JVM knows a few things:

  • It knows that this method is worth spending the time to optimize, because, well, it gets called a lot.
  • It knows a lot about the real-world characteristics of this function:
    • if one branch of an if statement is much more common than another, so it can improve branch prediction
    • if e.g. a List passed to this method is usually an ArrayList, so it can make optimizations and inlinings for the specific case of an ArrayList.

Note that if you compiled in advance to machine code, you wouldn't have a lot of this information to optimize with -- the compiler doesn't know in advance which paths tend to be more common than others. But if you wait to do your optimization until you have real-world data, you can make better optimization decisions.

Some more details on what the JIT does are here.

Community
  • 1
  • 1
Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • +1 for "a certain method has been called a lot" ... "It knows that this method gets called a lot" :) But seriously, good answer. – William Morrison Aug 13 '13 at 23:34
  • I am not sure if I understand it well, but the JVM will only know a method is called often after it is already called many times. I mean as the JVM interprets bytecode "on-line", it does not "know" how many times will a method be called again, right? Or does the compiler add such information to the bytecode at compilation time? If not, there would always be a chance that this method was only called a lot at the beginning of the program, and later it is unused - in such case, if JVM performed JIT with such method, it would simply waste time (or lots of time, if the method was big itself). – 3yakuya Aug 13 '13 at 23:47
  • No, of course it doesn't know that in advance; it guesses that if a method has been called lots before, it will continue to be called lots. But that's a perfectly valid assumption in practice. – Louis Wasserman Aug 13 '13 at 23:49
  • So the risk I described is simply taken into account as in practice it does not happen too often. Considering this facts, Java shouldn't be much slower than codes compiled directly into machine code. I mean it may take more time to start (servers) but when it is already running it should be pretty fast. Is my logic correct with this? (in the same discussion I've heard that Java Virtual Machine itself is pretty good). – 3yakuya Aug 13 '13 at 23:54
  • 3
    That's...sort of accurate. In some ways, Java can be _faster_ than precompiled machine code, because it knows more about the runtime characteristics of the code, but Java can be slower than other languages to get started and to "warm up" the hot spots in your code. – Louis Wasserman Aug 14 '13 at 00:00