2009-11-16 137 views
1

以下哪項在Java 6 HotSpot VM上更優化?優化在循環內創建對象

final Map<Foo,Bar> map = new HashMap<Foo,Bar>(someNotSoLargeNumber);  
for (int i = 0; i < someLargeNumber; i++) 
{ 
    doSomethingWithMap(map); 
    map.clear(); 
} 

final int someNotSoLargeNumber = ...; 
for (int i = 0; i < someLargeNumber; i++) 
{ 
    final Map<Foo,Bar> map = new HashMap<Foo,Bar>(someNotSoLargeNumber);  
    doSomethingWithMap(map); 
} 

我認爲他們都作爲明確的意圖,所以我不認爲風格/增加的複雜性是一個問題在這裏。

直覺上,它看起來像第一個會更好,因爲只有一個'新'。但是,考慮到沒有對映射的引用,HotSpot是否能夠確定爲每個循環創建相同大小的映射(Entry [someNotSoLargeNumber]),然後使用相同的內存塊(即不是做了大量的內存分配,只是調零可能比每個循環調用clear()快)?

一個可以接受的答案是鏈接到描述HotSpot VM實際上可以做的不同類型優化的文檔,以及如何編寫代碼來幫助HotSpot(而不是簡單的attmepts手動優化代碼)。

+4

時間它自己,看看。 – 2009-11-16 19:12:29

+0

我的猜測是第一個選擇,但我沒有數據支持它,所以我不會寫這個答案。看起來第二個選項會要求垃圾收集不夠聰明以確定匹配對象是否存在並且未被使用。我會關注這個問題,因爲我對答案很感興趣。 – martinatime 2009-11-16 19:16:14

回答

7

不要把時間花在這種微觀優化上,除非你的分析師說你應該這樣做。特別是,Sun公司宣稱,現代的垃圾收集器做的非常好,短版活的對象和新的()變得越來越便宜

+0

它將從倖存者空間轉移到可能會導致大多數問題的終身一代。所以新的每一次迭代都是可能的勝利(和更好的代碼)。不值得擔心。 – 2009-11-16 20:24:03

+0

這並不是說我試圖優化代碼,我只是想第一次正確編寫代碼,並且他們都完成了同樣的事情,我想我會檢查是否有任何方法可以幫助JVM。我認爲第二個選擇是更好的代碼,因爲映射的範圍是循環,正如文章所述,即使JVM現在不能優化代碼,它將來也可能是可能的。 好文章順便說一句。 – SimonC 2009-11-17 09:11:06

1

這是一個非常緊密的循環在「相當大數字「,所以通常我會說在循環之外移動實例。但總的來說,我的猜測是你不會注意到很大的區別,因爲我敢打賭,你的doSomethingWithMap將佔用大部分時間讓GC迎頭趕上。