我一直对一些 yourkit 快照感到困惑,这似乎表明在特定堆栈hashmap.put()
中被证明是昂贵的。
假设这张地图的关键是一个非常复杂的对象,它没有被覆盖equals()
或hashCode()
在某些情况下真的有可能HashMap.hash()
或代价高昂吗?Object.hashCode()
您说您的分析器指示put
为热点,而不是哈希码计算。put
不仅仅是哈希码的确定。特别是,如果地图非常大,就会做很多家务工作。put
而且,如果您的代码除了调用大量次之外几乎没有其他作用,那么这自然会在分析器中显示为热点。不过,它的性能可能没有任何问题。
这在理论上是可能的,但极不可能。
如果您真的在使用Object.hashcode()
,那么代表System.identityHashCode(Object)
相对便宜。此外,身份哈希码不应该给你碰撞热点......除非你真的很不走运。
如果您在HashMap.hash()
和中看到性能热点,Object.hashCode()
那么原因可能是您只是在进行大量HashMap
查找。
当然可以创建一个放入 HashMap 的成本很高的对象:
class Awful {
@Override
public int hashCode() {
try {
Thread.sleep(10000000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return 1;
}
}
显然这是一个人为的例子,但我已经看到了在 Hibernate 支持的延迟加载对象上调用方法的实现。将所述对象放入列表会导致大量、非常昂贵的数据库查找。
在不覆盖hashCode()
的情况下,该值是从对象的地址派生的,JVM 在调用方法时已经拥有该地址,因此它(尽可能好)是即时的。
我相信你的工具包并不总是值得信任的。在重度 JIT 优化分析器下,他们会感到困惑,并开始在尴尬的位置显示成本。