【问题标题】:Improving Comparable<T> compareTo performance提高 Comparable<T> compareTo 性能
【发布时间】:2009-03-10 16:36:22
【问题描述】:

我分析了我的代码,发现实现Comparable&lt;T&gt; 的类在

中花费的 CPU 时间增加了 8 倍
compareTo(Object)

比在

compareTo(T)

我认为速度变慢是因为此方法的虚拟表查找。


有没有办法强制静态调用函数?(就像在非虚拟 C++ 方法中一样)

我仍然想使用Comparable&lt;T&gt; 接口,因为我将TreeSet 与此对象一起使用,并且我不想重写此代码。


编辑:不,我没有实现 compareTo(Object) - 这是由分析器自动生成和报告的

【问题讨论】:

  • 而且这两个 compareTo 是完全一样的,除了强制转换?
  • 通常会有一个桥接方法,compareTo(Object) 调用 compareTo(ThisConcreteType)。大概后者几乎什么都不做。 -server 可能有助于内联。
  • 完成了粗略的性能计算?
  • 桥接方法应该由编译器自动生成,因为实现 Comparable 只需要您编写 compareTo(T) 方法。
  • 是的,但是桥接方法仍然会被执行并出现在分析器中。

标签: java performance comparable virtual-functions


【解决方案1】:

您看到compareTo(Object) 的原因是因为Type Erasure。它只是意味着在运行时不再需要类型信息来比较值。 您减速的最有可能的原因是 1)非常非常大的TreeSet,有很多元素 2) - 更有可能 - 你的 compareTo 方法做一些昂贵的事情。因为它被非常频繁地调用(通常是 n*ln(n) 次),所以它应该被有效地实现

【讨论】:

  • 我确实故意使用了一个大的 TreeSet,这就是为什么我试图让它尽可能快 - 它只有一个取消引用和两个比较。
  • 仅在必要时使用 treeSet。如果您只需要在特定时间对集合进行排序,请使用 HashSet 并在需要排序时对其进行排序,而不是一直。
【解决方案2】:

不,在这种情况下您不能强制进行静态调用。

invokespecial 指令可以“非虚拟”调用实例方法。当目标在编译时已知时使用此指令,例如构造函数或私有方法。在其他情况下——即使目标方法是final——也会使用invokevirtualinvokeinterface 指令。

【讨论】:

  • 学究点:或者在这种情况下更可能是invokeinterface,因为Comparable是一个接口。
【解决方案3】:

由于 java 在运行时执行 not preserve 泛型类型,理想情况下它们的行为应该相同。可能是其他原因导致了问题。

【讨论】:

    【解决方案4】:

    我认为放缓是因为 为此进行虚拟表查找 方法。

    您不必猜测这是否属实。 只需暂停几次,您就会在表演中抓住它。 完整显示调用堆栈,包括对库例程的调用。

    我的猜测(可能是错误的)是它正在经历 9 码的 OLE 风格调用 hoo-haw。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多