假设我的代码如下:
log.info("Now the amount" + amount + " seems a bit high")
我会用一个虚拟实现替换log方法,如:
class Logger {
...
public void info() {}
}
如果没有检测到副作用,优化器会内联并删除死代码吗?
答案 0 :(得分:3)
我猜测编译器(javac)不会,但是编译器很可能会及时编译。
然而,要使其工作,它必须能够推断出用于生成参数的任何指令都没有副作用。它应该能够针对字符串的特殊情况执行此操作,但它可能不适用于其他方法。
可以肯定的是,制作一个小基准,将其与Jesper建议和看到的代码进行比较,以较快者为准,或者如果它们同样快速。
另见:http://www.ibm.com/developerworks/java/library/j-jtp12214/index.html#3.0
答案 1 :(得分:1)
重要的答案是:可能。
我认为您不应该依赖依赖优化器的任何特定行为。如果您的代码在没有优化的情况下快速运行,那么您可能会或可能不会获得性能提升,但好消息是您的解决方案无论如何都会很好。如果在未优化时性能可怕,那么这不是一个好的解决方案。
依赖于优化器的问题在于,您要使自己符合您不知道的无形合同。 Hotspot在其他JDK / JRE版本中的表现会有所不同,所以不能保证只是因为它在你的确切JVM上运行良好,它在其他地方运行良好。但除此之外,发生的确切优化可能取决于环境问题,例如可用堆的数量,机器上的核心数量等。
甚至如果你现在确定它在你的情况下工作正常,那么你的代码库就会非常不稳定。我知道Hotspot所做的一个优化/内联取决于加载和用于非final类的子类的数量。如果你开始使用另一个加载log
- BANG的第二个实现的库/模块,优化就会解开,性能再次变得糟糕。祝你好运如何在你的类路径中添加第三方库来改善应用程序的内部性能......
无论如何,我认为你不会问真正的问题。在您描述的情况下,更好的解决方案不是更改info
方法的实现,而是将调用更改为no-ops(即将其注释掉)。如果你想同时在一大堆课程中完成这项工作,在编译时,你可以使用一种类型的IFDEF:
public class Log
{
public static final boolean USE_INFO = true;
public void info()
{
...
}
...
}
然后在你的课堂上:
if (Log.USE_INFO)
{
log.info("Now the amount" + amount + " seems a bit high");
}
现在编译器(javac,而不是Hotspot)可以看到布尔条件是常量并且在编译时会忽略它。如果将boolean标志设置为false并重新编译,那么所有的info语句都将从文件中完全删除,因为javac可以告诉它们永远不会被调用。
如果您希望能够在运行时启用/禁用信息日志记录,那么您需要使用一种方法而不是常量布尔标志,而这里除了每次都调用该方法之外没有任何内容。根据方法的实现,Hotspot 可以能够优化检查,但正如我上面提到的,不要依赖它。