Suppose I have code like :
log.info("Now the amount" + amount + " seems a bit high")
and I would replace the log method with a dummy implementation like :
class Logger {
...
public void info() {}
}
Will the optimizer inline it and will the dead code removal remove the parameter construction if no side effects are detected?
I would guess that the compiler (javac) will not, but that the just in time compiler very likely will.
For it to work however, it has to be able to deduct that whatever instructions you use to generate the parameter have no side effects. It should be able to do that for the special case of strings, but it might not for other methods.
To be sure, make a small benchmark that compares this with the code that Jesper suggested and see, whichever is faster or if they are equally fast.
Also see here: http://www.ibm.com/developerworks/java/library/j-jtp12214/index.html#3.0
The important answer is: it might do.
I don't think you should be relying on any particular behaviour of the optimiser. If your code runs acceptably fast without optimisation, then you may or may not get a performance boost, but the good news is your solution will be fine regardless. If performance is dreadful when non-optimised, it's not a good solution.
The problem with relying on the optimiser is that you're setting yourself up to conform to an invisible contract that you have no idea of. Hotspot will perform differently in other JDK/JRE versions, so there's no guarantee that just because it runs fine on your exact JVM, it'll run fine elsewhere. But beyond that, the exact optimisations that take place may depend on environmental issues such as the amount of free heap, the amount of cores on the machine, etc.
And even if you manage to confirm it works fine in your situation right now, you've just made your codebase incredibly unstable. I know for a fact that one of the optimisations/inlinings that Hotspot does depends on the number of subclasses loaded and used for a non-final class. If you start using another library/module which loads a second implementation of log - BANG, the optimisation gets unwound and performance is terrible again. And good luck working out how adding a third party library to your classpath toasts your app's internal performance...
Anyway, I don't think you're asking the real question. In the case you've described, the better solution is not to change the info method's implementation, but change the calls to no-ops (i.e. comment them out). If you want to do this across a whole slew of classes at once, at compile time, you can use a type of IFDEF like so:
public class Log
{
public static final boolean USE_INFO = true;
public void info()
{
...
}
...
}
and then in your class:
if (Log.USE_INFO)
{
log.info("Now the amount" + amount + " seems a bit high");
}
Now the compiler (javac, not Hotspot) can see that the boolean condition is constant and will elide it when compiling. If you set the boolean flag to false and recompile, then all of the info statements will be stripped from the file completely as javac can tell that they will never be called.
If you want to be able to enable/disable info logging at runtime, then instead of a constant boolean flag you'll need to use a method and here's there's nothing for it but to call the method every time. Depending on the implementation of the method, Hotspot may be able to optimise the check but as I mentioned above, don't count on it.
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
I want to do the following
int sum = x+y;
sum = Math.max(sum,x);
but that line of code tends to take longer than
int sum = x+y;
if(x>sum)sum=x;
I hope this is not inappropriate to ask, but can someone explain why this is?
I already looked in the source code and all Java is doing is
return (a >= b) ? a : b;
Maybe because Java's Math class is being created for the first time like any other Singleton or something like that, because no one used it before that, like class loader operation.
Method calls aren't free (even ignoring the potential class load that Roey pointed out): They involve pushing the arguments and a return address on the stack, jumping to a different location in the code, popping the arguments off the stack, doing the work, pushing the result on the stack, jumping back, and popping the result off the stack.
However, I suspect you'd find that if you had a Math.max call in a hotspot in your code (a place that was run a LOT), Oracle's JVM's JIT would optimize it into an inline operation to speed it up. It won't bother if there doesn't seem to be any need, preferring speed of compilation of bytecode to machine code over optimization; but it's a two-stage compiler, where the second stage kicks in to more aggressively optimize hotspots it detects in the code.
microbenchmarking in Java is a very hard job in general. The example and statement cannot be generalized and as usual, the answer to your question is "it depends". ;). First of all, the source code in you see in the JDK implementation for Math.max is a default, which is not used at all on modern hardware. The compiler replaces this call with a CPU operation. Read more here.
This of course does not answer your question why your code is 'faster' now. Probably, it was not executed at all, because of dead code elimination, a compiler feature. Can you give us some surrounding code? Details about how often it is called is useful as well. Details about hardware also. Very important as well: Disable all power save features and all background tasks if you do 'measurements'. Best is to use something like JMH
Cheers Benni
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.
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.
Before I ask my question can I please ask not to get a lecture about optimising for no reason.
Consider the following questions purely academic.
I've been thinking about the efficiency of accesses between root (ie often used and often accessing each other) classes in Java, but this applies to most OO languages/compilers. The fastest way (I'm guessing) that you could access something in Java would be a static final reference. Theoretically, since that reference is available during loading, a good JIT compiler would remove the need to do any reference lookup to access the variable and point any accesses to that variable straight to a constant address. Perhaps for security reasons it doesn't work that way anyway, but bear with me...
Say I've decided that there are some order of operations problems or some arguments to pass at startup that means I can't have a static final reference, even if I were to go to the trouble of having each class construct the other as is recommended to get Java classes to have static final references to each other. Another reason I might not want to do this would be... oh, say, just for example, that I was providing platform specific implementations of some of these classes. ;-)
Now I'm left with two obvious choices. I can have my classes know about each other with a static reference (on some system hub class), which is set after constructing all classes (during which I mandate that they cannot access each other yet, thus doing away with order of operations problems at least during construction). On the other hand, the classes could have instance final references to each other, were I now to decide that sorting out the order of operations was important or could be made the responsibility of the person passing the args - or more to the point, providing platform specific implementations of these classes we want to have referencing each other.
A static variable means you don't have to look up the location of the variable wrt to the class it belongs to, saving you one operation. A final variable means you don't have to look up the value at all but it does have to belong to your class, so you save 'one operation'. OK I know I'm really handwaving now!
Then something else occurred to me: I could have static final stub classes, kind of like a wacky interface where each call was relegated to an 'impl' which can just extend the stub. The performance hit then would be the double function call required to run the functions and possibly I guess you can't declare your methods final anymore. I hypothesised that perhaps those could be inlined if they were appropriately declared, then gave up as I realised I would then have to think about whether or not the references to the 'impl's could be made static, or final, or...
So which of the three would turn out fastest? :-)
Any other thoughts on lowering frequent-access overheads or even other ways of hinting performance to the JIT compiler?
UPDATE: After running several hours of test of various things and reading http://www.ibm.com/developerworks/java/library/j-jtp02225.html I've found that most things you would normally look at when tuning e.g. C++ go out the window completely with the JIT compiler. I've seen it run 30 seconds of calculations once, twice, and on the third (and subsequent) runs decide "Hey, you aren't reading the result of that calculation, so I'm not running it!".
FWIW you can test data structures and I was able to develop an arraylist implementation that was more performant for my needs using a microbenchmark. The access patterns must have been random enough to keep the compiler guessing, but it still worked out how to better implement a generic-ified growing array with my simpler and more tuned code.
As far as the test here was concerned, I simply could not get a benchmark result! My simple test of calling a function and reading a variable from a final vs non-final object reference revealed more about the JIT than the JVM's access patterns. Unbelievably, calling the same function on the same object at different places in the method changes the time taken by a factor of FOUR!
As the guy in the IBM article says, the only way to test an optimisation is in-situ.
Thanks to everyone who pointed me along the way.
Its worth noting that static fields are stored in a special per-class object which contains the static fields for that class. Using static fields instead of object fields are unlikely to be any faster.
See the update, I answered my own question by doing some benchmarking, and found that there are far greater gains in unexpected areas and that performance for simple operations like referencing members is comparable on most modern systems where performance is limited more by memory bandwidth than CPU cycles.
Assuming you found a way to reliably profile your application, keep in mind that it will all go out the window should you switch to another jdk impl (IBM to Sun to OpenJDK etc), or even upgrade version on your existing JVM.
The reason you are having trouble, and would likely have different results with different JVM impls lies in the Java spec - is explicitly states that it does not define optimizations and leaves it to each implementation to optimize (or not) in any way so long as execution behavior is unchanged by the optimization.