【问题标题】:How can Java inline over virtual function boundaries?Java 如何在虚函数边界上内联?
【发布时间】:2018-05-02 14:46:11
【问题描述】:

我正在阅读一些关于 Java 是否可以比 C++ 更快的材料,并看到了以下引用:

Java 可以比 C++ 更快,因为 JIT 可以内联虚函数边界。

Why Java Will Always Be Slower than C++ (wayback link)

这是什么意思?这是否意味着 JIT 可以内联虚函数调用(可能是因为它可以访问运行时信息)而 C++ 必须通过其 vtable 调用该函数?

【问题讨论】:

    标签: java function jit


    【解决方案1】:

    您的问题的答案是肯定的:这就是引用文本的意思。

    JIT 将分析所有加载的类。如果它可以确定在任何给定点只能调用一个可能的方法,它可以避免分派并(如果合适的话)内联方法体。

    相比之下,C++ 编译器不知道所有可能的子类型,因此无法确定是否可以对(虚拟)方法进行这种优化。 (当链接器运行时,为时已晚......)

    其他答案说您可以在 C++ 中手动进行此优化...但假设您(程序员)可以自己进行分析,并将方法从虚拟更改为非虚拟。但如果你弄错了,你就有一个 bug 需要追查。

    顺便说一句,我们可以假设这种优化对于普通的 Java 应用程序值得的。如果不是,JIT 编译器的人就不会实现它。毕竟,毫无价值的优化只会让 Java 应用程序启动更慢。

    【讨论】:

    • 一个好处是 getter 和 setter 可以内联,这意味着完全的抽象保护(对接口和所有代码进行编码),而无需每次都自动支付惩罚。
    【解决方案2】:

    由于将 Java 字节码编译为机器代码被推迟到运行时,JVM 可以执行 profile-guided optimization 和其他需要在代码运行之前不可用的信息的优化。这甚至可能包括“去优化”,即撤销之前进行的优化,以便进行其他优化。

    更多信息可以在 Wikipedia 上的 adaptive optimization 下找到,其中包括与内联相关的优化。

    【讨论】:

    • 我了解存在可以使用配置文件信息来确定是否进行这些优化的 C++ 编译器。 C++ 的真正问题是标准链接模型意味着调用者和被调用者不一定编译在一起。
    • 是的,新的 gcc 可以做这种链接时优化(LTO)。
    【解决方案3】:

    就其价值而言,Java、C++、Assembly 将提供相对相同的性能。

    是的,手动优化的 C++、C 或 Asm 可以实现更好的性能......但是,对于大多数应用程序(尝试除严重图形应用程序之外的所有应用程序),这不是瓶颈,而且 -较低的实施成本弥补了任何感知到的较低性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-08
      • 2012-10-09
      • 1970-01-01
      • 2013-08-28
      • 1970-01-01
      • 2017-06-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多