我在寫一些需要在內存中保存大量數據的「大數據」軟件。我用C++編寫了一個很好的原型。然而,實際的最終用戶通常使用Java編碼,因此他們要求我也編寫一個Java原型。java內存大小優化
我已經完成了對java內存佔用和一些初步測試的背景閱讀。例如,假設我有這個對象
public class DataPoint{
int cents, time, product_id, store_id;
public DataPoint(int cents, int time, int product_id, int store_id){
this.cents = cents;
this.time = time;
this.product_id = product_id;
this.store_id = store_id;
}
}
在C++中,這個結構的大小是16字節,這是有道理的。在Java中,我們必須是間接的。如果我創建了這些對象(例如,10米),並在 之前使用Runtime.totalMemory() - Runtime.freeMemory(),然後根據需要進行劃分,則每個結構將獲得大約36個字節。一個~2.4倍的內存差異是非常討厭的;當我們試圖在內存中保存數以億計的數據點時,它會變得很難看。
我在某處讀到,在Java這種情況下,它更好地將數據存儲爲數組 - 實質上是基於列的存儲而不是基於行的存儲。我想我明白這一點:基於列的方式減少了引用的數量,並且JVM甚至可以智能地將這些字符串打包成8字節的字。
還有什麼其他的技巧可以用來減少本質上是一個非常大的維度(數百萬/數十億個數據點)和一個非常小的維度(O(1)列數量的內存塊的內存佔用/變量)?
結果將數據存儲爲每個條目恰好使用16個字節的4個int數組。教訓:小的對象在java中具有討厭的比例開銷。
totalMemory還包含空閒內存,請嘗試使用totalMemory()來測量 - freeMemory() – Henry
如果您想要一個非常準確的數字,請使用應用程序的堆轉儲並使用Memory Analyzer(http ://www.eclipse.org/mat/)以獲得準確的數字。 2nd - 這個數據的訪問模式是什麼?也許你可以通過使用一些可以將未使用的部分分頁到磁盤的緩存庫來獲得更多的空間?說你的點分成10K項目的數組,並將這些「塊」存儲在infinispan(http://www.jboss.org/infinispan/)或類似的? – radai
@亨利好點!使用totalMemory()進行測量 - freeMemory()爲每個結構提供36個字節的值。優於52,但仍是C++的2倍。 – andyInCambridge