I already worked with -XX:+PrintCompilation
, and I know the basic techniques of the JIT-compiler and why JIT-compilation is used.
Yet I still have not found out how the JVM decides to JIT-compile a method, i.e. "when the right time has come to JIT-compile a method".
Am I right in the assumption that every method starts being interpreted, and as long as it is not categorized as "hot method" it will not be compiled? I have something in the back of my head that I read that a method is considered "hot" when it was executed at least 10.000 times (after interpreting the method 10.000 times, it will be compiled), but I have to admit that I am not sure about this or where I've read this.
So to sum up my question:
(1) Is every method interpreted as long as it not has been categorized as "hot" method (and therefore has been compiled) or are there reasons for methods to get compiled even if they are not "hot"?
(2) How does the JVM categorize methods into "non-hot" and "hot" methods? Number of execution? Anything else?
(3) If there are certain thresholds (like number of executions) for "hot" methods, are there Java flags (-XX:...
) to set this thresholds?
The JIT compiler is enabled by default, and is activated when a Java method is called. The JIT compiler compiles the bytecodes of that method into native machine code, compiling it "just in time" to run. When a method has been compiled, the JVM calls the compiled code of that method directly instead of interpreting it.
A Just-In-Time (JIT) compiler is a feature of the run-time interpreter, that instead of interpreting bytecode every time a method is invoked, will compile the bytecode into the machine code instructions of the running machine, and then invoke this object code instead.
Although the JIT is not actually part of the JVM standard, it is, nonetheless, an essential component of Java. In theory, the JIT comes into use whenever a Java method is called, and it compiles the bytecode of that method into native machine code, thereby compiling it “just in time” to execute.
In order to improve performance, JIT compilers interact with the Java Virtual Machine (JVM) at run time and compile suitable bytecode sequences into native machine code.
HotSpot compilation policy is rather complex, especially for Tiered Compilation, which is on by default in Java 8. It's neither a number of executions, nor a matter of CompileThreshold
parameter.
The best explanation (apparently, the only reasonable explanation) can be found in HotSpot sources, see advancedThresholdPolicy.hpp.
I'll summarize the main points of this advanced compilation policy:
i
;b
. Backward branches typically denote a loop in the code.Every time counters reach certain frequency value (TierXInvokeNotifyFreqLog
, TierXBackedgeNotifyFreqLog
), a compilation policy is called to decide what to do next with currently running method. Depending on the values of i
, b
and current load of C1 and C2 compiler threads it can be decided to
Key parameters here are TierXInvocationThreshold
and TierXBackEdgeThreshold
. Thresholds can be dynamically adjusted for a given method depending on the length of compilation queue.
Compilation queue is not FIFO, but rather a priority queue.
C1-compiled code with profile data (tier 3) behave similarly, except that thresholds for switching to the next level (C2, tier 4) are much bigger. E.g. an interpreted method can be compiled at tier 3 after about 200 invocations, while C1-compiled method is subject for recompilation at tier 4 after 5000+ invocations.
InlineFrequencyRatio
, InlineFrequencyCount
).The main parameter to control this is -XX:CompileThreshold=10000
Hotspot for Java 8 now uses a tiered compilation by default using a number of stages of compilation from level 1 to 4. I believe 1 is no optimisation. Level 3 is C1 (based on the client client) and Level 4 is C2 (based on the server compiler)
This means that a little optimisation can happen earlier than you might expect and it can keep optimising long after it has reach the 10K threshold. The highest I have seen is escape analysis eliminating a StringBuilder after one million calls.
Note: a loop iterating many times can trigger the compiler. e.g. a loop of 10K times can be enough.
1) Until a method is considered hot enough, it is interpreted. However some JVMs (e.g. Azul Zing) can compile methods on start up and you can force the Hotspot JVM to compile a method via an internal API. Java 9 may also have an AOT (Ahead Of Time) compiler but it is still being researched AFAIK
2) Number of calls, or number of iterations.
3) Yes -XX:CompileThreshold=
being the main one.
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