2014-01-10 128 views
6

我是一個交易的C++開發人員,但最近我一直在做點Java。我正在從事的這個項目是由一名開發人員完成的,而且我一直在尋找他正在圍繞垃圾收集工作做些奇怪的事情。java垃圾收集和臨時對象

案例和點,他實現了自己的字符串類,以避免GC

應用程序的這部分花費了大量的二進制文件格式,並將其出口到CSV放緩。這意味着爲文件中的每一行建立一個字符串(百萬)。爲了避免這些臨時字符串對象,他創建了一個字符串類,它只是重用了大量字節。

/** 
HACK 
    A Quick and Dirty string builder implementation optimized for GC. 
    Using String.format causes the application grind to a halt when 
    more than a couple of string operations are performed due to the number of 
    temporary objects allocated while formatting strings for drawing or logging.  
*/ 

這實際上有幫助嗎?這真的需要嗎?這比僅僅在循環外部聲明一個String對象並將其設置在循環內部更好?

該應用程序還有一個哈希映射,其中包含值的雙打。地圖中的鍵是相當靜態的,但值經常變化。 GC對雙打怕他做了一個myDouble類作爲值使用HashMap中

/** 
* This is a Mutable Double Wrapper class created to avoid GC issues 
* 
*/ 
public class MyDouble implements Serializable { 
    /** 
    * 
    */ 
    private static final long serialVersionUID = C.SERIAL_VERSION_UID; 
    public double d; 

    public MyDouble(double d) { 
     this.d = d; 
    } 
} 

這是瘋了,完全沒有必要的,對吧?

+2

爲什麼不用替代方法測試它,看看它是否有所作爲?根據寫入時間的不同,很可能JVM自那時以來已經有了很大的改進,並且代碼已不再需要,但仍然完全有可能大幅超越標準內存分配器,因爲它必須是標準的,並且自己的代碼,你可以專門爲你的場景編寫它。 – Dukeling

+0

明智的意思是否落後於基準?如果沒有,請自己想一些,並將信譽評分停靠幾分。現在您可以量化更改的影響,並可以在不會不當影響性能的情況下開始簡化代碼。 – delnan

+2

回答你的第一個問題:是的,它*可以*幫助,但是看起來他已經在這裏重新發明了輪子。現在我們使用'StringBuilder'類,它基本上對char緩衝區做了同樣的事情並允許可變長的字符串。要回答第二個問題:不,在循環外部創建字符串引用並將其設置在循環內部仍然會創建一大堆字符串。在java中字符串文字是一種「特殊情況」。如果你的應用程序創建了許多獨特的小字符串,或者附加了很多(我懷疑是這種情況),GC可能非常忙碌。 – CodeChimp

回答

3

確實,字符串連接可能是Java中的瓶頸,因爲String是不可變的。這意味着每個級聯會創建一個新的String,除非以前創建的匹配String因此位於字符串池中(請參閱string interning)。無論哪種方式,它肯定會導致問題。

但是,您的前任不是第一個遇到過這個問題的人,並且處理需要連接Java中的許多String的標準方法是使用StringBuilder

double(或任何基本事項)被用作局部變量時,它會一直保留在堆棧上,它佔用的內存會隨着堆棧幀一起釋放(不確定它們是否受到GC或採用JVM在運行時關心)。但是,如果double是對象上的字段,它將存儲在堆上,並在收集包含它的對象時收集。

沒有看到如何使用double值,很難說,但很可能使用Map增加了GC負載。

總之,是的,這是肯定的,正如你所說的'瘋狂和完全沒有必要'。這些過早的優化只會使代碼複雜化,使其更容易出現錯誤,並使日後的維護變得更加困難。黃金法則實際上應該始終如一,構建最簡單的工作,分析並優化。

+0

感謝您對StringBuilder的建議 – Taz