【问题标题】:Java method calls faster than virtual method calls in C++?Java 方法调用比 C++ 中的虚拟方法调用更快?
【发布时间】:2013-02-01 21:11:38
【问题描述】:

刚刚在维基百科中偶然发现了这个:

Java 可以比 C++ 更快地访问派生实例方法 由于 C++ 的额外虚拟表查找而派生的虚拟方法。 但是,C++ 中的非虚方法不受 V-Table 的影响 性能瓶颈,因此表现出类似的性能 Java的。

这是正确的吗?据我所知,Java 中的所有调用都是虚拟的,并且仍然依赖于虚拟表,因此我的常见逻辑表明 Java 调用不可能比虚拟 C++ 调用更快。

是我误导还是文章有误?无论如何 - 有没有比虚拟表更快的方法在运行时解决调用?

【问题讨论】:

  • 除非它解释了 Java 如何处理多态调用,否则我很想在这方面打电话给 BS。 (我相信它也使用 v-tables。)
  • PS 虽然我知道的每个编译器都使用 v-tables,但据我所知,标准并没有规定必须这样做;他们可以使用任何他们想要的虚拟调度方法。
  • 这是营销。 Java 中的 一些 调用可能比 C++ 虚拟调用更快,但大多数调用在 C++ 中不是虚拟调用。然后呢?
  • 你必须非常努力地让我相信 C++ 中的 vtable 查找,它只是一个额外的索引间接,即一条指令,比 Java 需要做的任何事情都具有更高的成本。跨度>
  • @EJP - 文字只是说 Java 中最快的函数调用可以比 C++ 中最慢的函数调用更快。营销说话!

标签: java c++ performance call virtual


【解决方案1】:

阅读 source 以获取该报价:

因为编译器知道哪些类被实际加载并被 调用,它知道哪些方法可以去虚拟化和内联。 (值得注意的是,现代 java 编译器也知道如何“反编译” 在之后加载覆盖方法的情况下的内联调用 发生 JIT 编译。)

虽然我不明白为什么 C++ 编译器不能做到这一点。

【讨论】:

  • JIT 的优化作用于运行时信息,C++ 是静态编译的。这种差异应该有利于 JVM,但现实中的差异可能纯粹是学术上的。
  • 在 JIT 期间什么样的运行时信息对此有用?
  • JVM 知道真正加载和使用了哪些类。 C++ 可能只知道声明了哪些类,并且只有在进行整个程序优化时才知道。否则它甚至不知道。大量的虚拟调用实际上是单态的。 JVM 可以轻松地检查并去虚拟化。 C++ 不能,因为它不能保证调用是单态的。此外,JVM 使用内联缓存和程序专业化来实现 C++ 可以使用模板实现的类似效果。
【解决方案2】:

这可能与 JIT 编译执行的优化有关。在某些情况下,我可以想象 JVM 会检测到某个(虚拟)调用总是引用某个实现并且不需要查找。

OTOH,C++ 编译器也可以推断在某些情况下不需要查找并生成同样好的代码。此外,C++ 不需要虚函数,因此还有 Java 不提供的替代方法。

也就是说,如果您需要 virtual 在 C++ 中提供的功能,那么我通常无法想到更好的替代方案。如果您关心性能,请注意virtual 通常是有成本的,并且应该只在需要时使用。

总的来说,我发现像你引用的那种说法没有帮助和误导(当然不是你的错)。

【讨论】:

  • 说实话,整篇文章都充满了狂热的味道,非常乐观和过于理想化。
  • 世界上有三种谎言——谎言、该死的谎言和基准。鉴于 C++ 的质量足够差,而 Java 代码的质量足够好,我希望可以构建一个基准来证明 Java 的运行时“优于 C++”。反之亦然...
猜你喜欢
  • 1970-01-01
  • 2013-05-01
  • 2012-09-05
  • 1970-01-01
  • 2013-02-05
  • 1970-01-01
  • 1970-01-01
  • 2012-06-21
  • 1970-01-01
相关资源
最近更新 更多