views:

67

answers:

2

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 optimiwer inline it and will the dead code removal remove the parameter construction if no side effects are detected?

+3  A: 

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

inflagranti
+1  A: 

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.

Andrzej Doyle