2011-05-10 61 views
0

我想讀取一些XML文件並將其轉換爲圖形(無圖形,只是一個模型)。但是由於文件非常大(2,2 GB),我的模型對象(包含所有信息)變得更大(4倍於文件大小)。從HashMaps中刪除未使用的已分配內存

通過網絡搜索我試圖找到方法來減少對象的大小。我嘗試了不同的集合類型,但想要堅持一個HashMap(因爲我必須有隨機訪問)。實際的鍵和值只佔少量分配的內存。大多數哈希表是空的...

如果我沒有完全錯誤的垃圾收集不幫我釋放分配的內存並減少散列表的大小。是否有其他方式來釋放未使用的內存並縮小散列表?或者有沒有辦法完成哈希?或者我只是使用另一個集合?

由於提前,

塞巴斯蒂安

+0

這裏改進的關鍵是避免將所有2.2 GB文件一次讀入內存 – 2011-05-10 18:35:57

回答

1

HashMap通常恰好大陣列填充至容量的一定百分比的參考文獻。如果只有80%的地圖被填充,剩餘的20%的數組單元未被使用(即,爲空)。額外的開銷實際上只是空的(空)單元。

在32位CPU上,每個數組單元通常爲4個字節(儘管某些JVM實現可能分配8個字節)。這並不是那麼多未使用的空間。

一旦您的地圖填充完畢,您可以將其複製到另一個HashMap,以更合適(較小)的尺寸給出更大的填充百分比。

你的問題似乎意味着你有更多的分配但未使用的對象,你擔心。但情況如何?

補遺

一旦映射被幾乎充滿到容量(典型地超過95%左右),將較大的陣列被分配,舊數組的內容被複制到新的數組,然後小陣列留下垃圾收集。這顯然是一個昂貴的操作,因此爲地圖選擇合理的初始大小是提高性能的關鍵。

如果可以(超出)估計所需的單元數量,則預分配映射可以減少甚至消除調整大小的操作。

+1

調整陣列大小時將調整爲舊大小的兩倍。在最壞的情況下,只有一個項目導致分配一個巨大的數組。 – 2011-05-10 18:46:20

+0

TreeSets可能變得更可預測(即使完美的HashMap也會比完美的TreeMap小得多)。問題是幾乎不可能獲得一個接近完美的HashMap(從內存佔用)。 – MeBigFatGuy 2011-05-10 19:03:24

0

你在問什麼不是很清楚,不清楚是否內存是由放在hasmap中的對象或由hashmap本身取得的,不應該是這種情況,因爲它只保存引用。

在任何情況下,看看WeakHashMap,也許它是你在找什麼:它是一個散列圖,它不保證密鑰保存在裏面,它應該用作一種緩存,但從你的描述我真的不知道它是否是你的情況。

+0

已經嘗試過。它使用更少的內存,但GC似乎扔掉了對象,我後來需要:( – 2011-05-11 15:30:48

0

如果你減少散列表的內存佔用量,你總是可以將數據放入數據庫。根據訪問數據的方式,如果您在數據庫前面引入緩存,您仍然可以獲得合理的性能。

0

有一點可能會發揮作用,那就是您可能有引用較舊較大字符串的子字符串,這些子字符串會使GC無法收集太大的字符數組。

當您使用某些XML解析器將屬性/值作爲大字符串的子字符串返回時,會發生這種情況。 (子字符串只是較大字符串的有限視圖)。

嘗試把你的字符串在地圖上做這樣的事情:

map.put(new String(key), new String(value)); 

注意,GC則可能會得到更多的工作,當你填充圖來做,這可能不是如果幫你你沒有那麼多引用較大字符串的子字符串。

0

如果你對這個真的很嚴重,你有空閒時間,就可以讓自己的實現基於minimal perfect hashing

如果你的鍵是字符串Map接口的,那麼所以顯然是可用於地圖你here。 我自己沒有嘗試過,但它吹噓減少內存使用。

0

您可能會給the Trove collections一槍。他們將其作爲java.util集合的更高效的時間和空間替代來廣告。