For testing purposes I need to be sure that certain methods are not inlined when the respective code is compiled to produce the .class files.
How do I do it in Eclipse?
EDIT
For those who really need to know why, before they tell how, here is the explanation - I am testing a code, which examines and manipulates JVM byte code. This is why I want sometimes to avoid method inlining.
You don't; you have very little control over how the compiler and JIT optimize bytecode.
It's not clear to me why you'd want to do this, though.
Note that various JVM implementations may allow tweaking, e.q., -XX:MaxInlineSize= in HotSpot might be set to an impossibly-low number meaning no methods would be inlined. There may be an equivalent option in the Eclipse compiler, but I'd be wary.
Java methods are never inlined when producing the .class files (only by an optimizing JVM at run time), so you have nothing to worry about.
When it comes to Java inlining functions, you are entirely at the whim of the compiler. You have no say in it whatsoever.
There are some various metrics that it uses to determine if something should be inlined. I believe one of these is the number of bytecode instructions in the method. So if you had a method like this:
void foo() {
if(SOME_GLOBAL_BOOLEAN_THATS_ALWAYS_FALSE) {
// lots of statements here
}
// code here
}
You might be able to reduce the chance of it inlining on you, provided you were clever enough in your if statement to make sure it wasn't going to optimize it out on you.
Related
I have been pulled into a performance investigation of a code that is similar to the below:
private void someMethod(String id) {
boolean isHidden = someList.contains(id);
boolean isDisabled = this.checkIfDisabled(id);
if (isHidden && isDisabled) {
// Do something here
}
}
When I started investigating it, I was hoping that the compiled version would look like this:
private void someMethod(String id) {
if (someList.contains(id) && this.checkIfDisabled(id)) {
// Do something here
}
}
However, to my surprise, the compiled version looks exactly like the first one, with the local variables, which causes the method in isDisabled to always be called, and that's where the performance problem is in.
My solution was to inline it myself, so the method now short circuits at isHidden, but it left me wondering: Why isn't the Java Compiler smart enough in this case to inline these calls for me? Does it really need to have the local variables in place?
Thank you :)
First: the java compiler (javac) does almost no optimizations, that job is almost entirely done by the JVM itself at runtime.
Second: optimizations like that can only be done when there is no observable difference in behaviour of the optimized code vs. the un-optimized code.
Since we don't know (and the compiler presumably also doesn't know) if checkIfDisabled has any observable side-effects, it has to assume that it might. Therefore even when the return value of that method is known to not be needed, the call to the method can't be optimized away.
There is, however an option for this kind of optimization to be done at runtime: If the body (or bodies, due to polymorphism) of the checkIfDisabled method is simple enough then it's quite possible that the runtime can actually optimize away that code, if it recognizes that the calls never have a side-effect (but I don't know if any JVM actually does this specific kind of optimization).
But that optimization is only possible at a point where there is definite information about what checkIfDisabled does. And due to the dynamic class-loading nature of Java that basically means it's almost never during compile time.
Generally speaking, while some minor optimizations could possibly be done during compile time, the range of possible optimizations is much larger at runtime (due to the much increased amount of information about the code available), so the Java designers decided to put basically all optimization effort into the runtime part of the system.
The most-obvious solution to this problem is simply to rewrite the code something like this:
if (someList.contains(id)) {
if (this.checkIfDisabled(id)) {
// do something here
If, in your human estimation of the problem, one test is likely to mean that the other test does not need to be performed at all, then simply "write it that way."
Java compiler optimizations are tricky. Most optimizations are done at runtime by the JIT compiler. There are several levels of optimizations, the maximum number of optimizations by default will be made after 5000 method invocations. But it is rather problematic to see which optimizations are applied, since JIT compile the code directly into the platform's native code
In this article, I was surprised to read:
I always imagined that having a final method meant that the compiler would compile all calls to it using invokespecial instead of invokevirtual, to "devirtualize" the method calls since it already knows for sure at compile-time where to transfer execution. Doing this at compile time seems like a trivial optimization, while leaving this up to the JIT is far more complex. But no, the compiler doesn't do this. It's not even legal to do it!
Doing this at compile time seems like a trivial optimization, since it already knows for sure at compile-time where to transfer execution. What's the reason this doesn't happen?
Posting the answer that EJP pointed out in the comments:
Java has a separate compilation model, thus it forbids cross-file optimization (with a notable exception, compile-time constant inlining). What if you change the method to non-final, and do not recompile the clients? What if you do runtime bytecode replacement (search for "instrumentation")?
Side note: as an engineer, your expectations should be a function of the tool. This is not C++. Where you can afford an interpreter, bytecode optimization is premature optimization.
Keep your mind object-oriented. You ask the compiler to do it, let it decide the best behind the scenes; if a 20yo compiler does not do it, it's probably unimportant. -O is well documented (at least on Oracle's JDK) and it just inlines the private and static methods inside the file that declares them.
I found out that the C++ compiler does so but I want to know if the Java compiler does the same since in that answer they said adding static would do so but static is different in java and C++. In my case performance would matter since am using functions that are called only once per frame in a game loop and called nowhere else, to make it more readable
In my code I have it setup up similar to this, except with many more calls
while(running)
{
update();
sync();
}
and then update(), render() would call more methods that call other methods
private final void update()
{
switch(gameState)
{
case 0:
updateMainMenu();
renderMainMenu();
break;
case 1:
updateInGame();
renderInGame();
break;
//and so on
}
}
private final void updateInGame()
{
updatePlayerData();
updateDayCycle();
//and so on
}
private final void updatePlayerData()
{
updateLocation();
updateHealth();
//and so on
}
So would the compiler inline these functions since they are only used once per frame in the same location?
If this is a bad question, plz tell me and I will remove it.
A Java JITC will attempt to inline any functions that appear (based on runtime statistics) to be called often enough to merit it. It doesn't matter whether the function is called in only one place or dozens of places -- each calling site is analyzed separately.
Note that the decision is based on several factors. How big the method is is one -- if there are a lot of potential inlining candidates only the most profitable will be inlined, to avoid "code bloat". But the frequency of the call (multiplied by the perceived expense of the call) is the biggest "score" factor.
One thing that will discourage inlining is obvious polymorphic calls. If a call might be polymorphic it must be "guarded" by code that will execute the original call if the arriving class is not the expected one. If statistics prove that a call is frequently polymorphic (and including all the polymorphic variants is not worthwhile) then it's likely not sufficiently profitable to inline. A static or final method is the most attractive, since it requires no guard.
Another thing that can discourage inlining (and a lot of other stuff) is, oddly enough, a failure to return from the method. If you have a method that's entered and then loops 10 million times internally without returning, the JITC never gets a chance to "swap out" the interpreted method and "swap in" the compiled one. But JITCs overcome this to a degree by using techniques for compiling only part of a method, leaving the rest interpreted.
For future reference, you can view the bytecode of a .class file with javap -c MyClass to see what your compiled code looks like.
To answer your question: the Java compiler does not inline methods. The JVM, on the other hand, analyzes your code and will inline at runtime if necessary. Basically, you shouldn't worry about it -- leave it to the JVM, and it will inline if it finds it beneficial. The JVM is typically smarter than you when it comes to these things.
From http://www.oracle.com/technetwork/java/whitepaper-135217.html#method:
Method Inlining
The frequency of virtual method invocations in the Java programming language is an important optimization bottleneck. Once the Java HotSpot adaptive optimizer has gathered information during execution about program hot spots, it not only compiles the hot spot into native code, but also performs extensive method inlining on that code.
Inlining has important benefits. It dramatically reduces the dynamic frequency of method invocations, which saves the time needed to perform those method invocations. But even more importantly, inlining produces much larger blocks of code for the optimizer to work on. This creates a situation that significantly increases the effectiveness of traditional compiler optimizations, overcoming a major obstacle to increased Java programming language performance.
Inlining is synergistic with other code optimizations, because it makes them more effective. As the Java HotSpot compiler matures, the ability to operate on large, inlined blocks of code will open the door to a host of even more advanced optimizations in the future.
When does Java JIT inline a method call? Is it based on #times the caller method is called (if yes, what would that number be?), or some other criteria (and what would that be?)
I've read that JIT can inline 'final' methods, but it also inlines nonfinal methods based on runtime statistics, so want to know what is that triggering criteria.
I guess the answers would differ based on JVM implementation, but maybe there's something common across all of them?
The short answer is whenever it wants.
Very often a JITC will inline small final or pseudo-final methods automatically, without first gathering any stats. This is because it's easy to see that the inlining actually saves code bytes vs coding the call (or at least that it's nearly a "wash").
Inlining truly non-final methods is not usually done unless stats suggest it's worthwhile, since inlined non-finals must be "guarded" somehow in case an unexpected subclass comes through.
As to the number of times something may be called before it's JITCed or inlined, that's highly variable, and is likely to vary even within a running JVM.
the default inline threshold for a JVM running the server Hotspot compiler is 35 bytecodes.
Official docs
Typically JIT only inlines "small" methods by default. Other than that it's completely dependent on the implementation.
As I understand there is no clear rule to determine whether Java method will be JITed or interpreted while call.
So is there somehow to tell JVM that I need a certain method to be JITed. And is there a way to know for sure which method will be JITed and which not.
As far as I know you don't know (from inside the JVM) and can not enforce a method being JITed or not, but using -XX:+PrintCompilation JVM argument you can watch the JIT compiler doing it's work and check if a method gets JITed in that particular run of the program or not.
So is there somehow to tell JVM that I need a certain method to be JITed.
No, which methods are "JITed" and not is not up to you, and in fact, there is no guarantee that any method will ever be JITed. I suggest you leave these decisions to the JVM.
And is there a way to know for sure
which method will be JITed and which
not.
The (Oracle) Sun JVM is called HotSpot, which means it looks at which methods are called most, thus becoming "hot", and those methods are the first to be compiled. So some methods may never be compiled. But if you know the method is called a lot, it most probably be compiled. You can set the threshold with -XX:CompileThreshold=10000 VM options, which specifies how many invocations it takes to consider the method "hot".
I don't know any way to check whether current code is running in interpreted or compiled mode. VM crash logs show which methods in the stack trace are interpreted or compiled, maybe there's some way to get it in runtime.
There is a way to ask the jvm to compile a class, it is not guaranteed to do anything but should work on any jvm having a jit.
Compiler.compileClass(MyClass.class);
You can't tell and there is no way that it makes any difference barring bugs in HotSpot. The term 'JIT' is at least ten years out of date.