2013-08-02 62 views
2

我一直對一些yourkit快照感到困惑,似乎表明在特定的堆棧hashmap.put()被證明是昂貴的。HashMap放置性能

我們先來說說這個地圖關鍵是尚未覆蓋equals()hashCode()

是它HashMap.hash()Object.hashCode()真的有可能在某些情況下昂貴的一個非常複雜的對象嗎?

+0

大多數對象的默認哈希碼是它們在內存中的地址,因爲兩件事不能共享該空間,這個值是唯一的。另外它是一個本地功能,所以它應該超快。 –

+0

如果該鍵未被覆蓋,則將使用默認的'hashCode'。這只是返回應該是相當便宜的物品的內存位置。由於大量的對象衝突[很有可能](http://stackoverflow.com/a/1381288/2071828),這對於HashMap的性能具有巨大的,有害的影響,所以問題將會是非快速的。 。 –

+0

@BoristheSpider這豈不是不可能的兩個對象將具有相同的內存地址使它不可能有衝突?我假設Java的散列算法非常好。 –

回答

1

這當然是可以創建一個對象,它是昂貴的投入一個HashMap:

class Awful { 
    @Override 
    public int hashCode() { 
     try { 
      Thread.sleep(10000000); 
     } catch (InterruptedException e) { 
      Thread.currentThread().interrupt(); 
     } 
     return 1; 
    } 
} 

顯然,這是一個人爲的例子,但我已經看到了調用方法對Hibernate的支持實現,延遲加載對象。將所述對象放入列表中會導致大量非常昂貴的數據庫查找。

不覆蓋hashCode()該值是從對象的地址派生而來的,JVM已經在調用該方法的位置擁有該對象,所以它是(即時的)即時的。

+0

是的。這沒有道理。看起來這是一個你的軟件缺陷/問題。只要我將Map與List結構交換,成本就會分配給其他堆棧。肯定yourkit玩壞。 – Vikrant

1

這在理論上是可能的,但可能性很小。

如果您真的使用Object.hashcode()那麼代表System.identityHashCode(Object)這是相對便宜。此外,身份hashcodes不應該給你碰撞熱點...除非你真的不走運。

如果你看到一個表現的熱點,在HashMap.hash()Object.hashCode(),那麼也許原因是,你只是在做大量的HashMap查找。

1

你說你的分析器表示put作爲熱點,而不是哈希碼計算。 put不僅僅是哈希碼確定。特別是,如果地圖非常大,將會有很多家務工作完成。如果你的代碼做一點別的,而是調用put次的數量巨大,那麼自然,這將在探查的熱點出現。不過,它的表現可能沒有錯。

0

我相信yourkit不能總是被信任。在繁重的JIT優化分析器中,他們感到困惑,並開始顯示處於尷尬境地的成本。