Java 优化器会删除空方法调用的参数构造吗?

发布于 2024-09-06 21:21:34 字数 252 浏览 1 评论 0原文

假设我有这样的代码:

log.info("Now the amount" + amount + " seems a bit high")

并且我会用一个虚拟实现替换日志方法,例如:

class Logger {
   ...
   public void info() {}

}

优化器是否会内联它,如果没有检测到副作用,死代码删除是否会删除参数构造?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

和我恋爱吧 2024-09-13 21:21:34

我猜编译器(javac)不会,但即时编译器很可能会。

然而,为了让它工作,它必须能够推断出您用来生成参数的任何指令都没有副作用。对于字符串的特殊情况,它应该能够做到这一点,但对于其他方法可能无法做到这一点。

可以肯定的是,做一个小的基准测试,将其与 Jesper 建议和查看的代码进行比较,以更快者或它们是否同样快者为准。

另请参阅此处:http://www.ibm。 com/developerworks/java/library/j-jtp12214/index.html#3.0

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

小霸王臭丫头 2024-09-13 21:21:34

重要的答案是:可能会

我认为您不应该依赖优化器的任何特定行为。如果您的代码在没有优化的情况下运行速度可以接受,那么您可能会也可能不会获得性能提升,但好消息是您的解决方案无论如何都会很好。如果未优化时性能很糟糕,那么这不是一个好的解决方案。

依赖优化器的问题在于,您正在让自己遵守一个您不知道的无形合同。 Hotspot 在其他 JDK/JRE 版本中的表现会有所不同,因此不能保证它在您的 JVM 上运行良好,在其他地方也能运行良好。但除此之外,发生的确切优化可能取决于环境问题,例如空闲堆的数量、机器上的核心数量等。

即使您设法确认它现在在您的情况下工作正常,您刚刚使您的代码库变得非常不稳定。我知道 Hotspot 所做的优化/内联之一取决于加载和用于非最终类的子类的数量。如果您开始使用另一个加载 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) ) 可以看到布尔条件是常量,编译时会忽略它。如果将布尔标志设置为 false 并重新编译,则所有信息语句都将从文件中完全删除,因为 javac 可以告诉它们永远不会被调用。

如果您希望能够在运行时启用/禁用信息日志记录,那么您需要使用一个方法,而不是使用常量布尔标志,这里除了每次调用该方法之外没有其他任何方法。根据方法的实现,Hotspot可能能够优化检查,但正如我上面提到的,不要指望它。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文