2011-08-30 120 views
4

我在尋找一些想法,也許已經有一些具體的實現,如果有人知道任何,但我願意自己編寫想要的緩存。Java內存感知緩存

我想要一個緩存,只緩存許多演出,因爲我配置。與應用程序的其餘部分相比,緩存部分將使用近100%的內存,因此我們可以將應用程序的已用內存概括爲緩存大小(+垃圾)。

是否有方法可以猜測使用了多少內存?還是依靠軟指針會更好?軟指針並始終運行在jvm內存限制的頂部可能會非常不方便,並且有很多cpu週期用於內存清理?我可以對現有對象進行一些分析,例如myObject.getMemoryUsage()

LinkedHashMap有足夠的緩存命中我的目的,所以我不必編寫一些戰略緩存怪物,但我不知道如何正確解決這個問題。有任何想法嗎?我不希望OOME飛到任何地方。

什麼是最佳實踐?

回答

1

我會推薦使用Java Caching System。雖然如果你想自己推出,我不知道有什麼方法可以在內存中獲取對象大小。您最好的選擇是擴展AbstractMap並將值包含在SoftReferences中。然後,您可以將java堆大小設置爲您想要的最大大小。儘管如此,你的實現還必須找到並清除陳舊的數據。只是使用JCS可能更容易。

2

SoftReference不是一個好主意,因爲它們傾向於一次變得更清晰。這意味着,當您從GC獲得性能提升時,您還需要重新構建緩存。

您可以使用Instrumentation.getObjectSize()來獲取對象的淺層大小並使用反射來獲取深層大小。但是,這樣做相對昂貴,而不是你想要經常做的事情。

爲什麼不能將大小限制爲多個對象?事實上,我會從最簡單的緩存開始,只添加你真正需要的緩存。

LRU cache in Java.

編輯:跟蹤你使用多少內存的一種方法是序列化值,並將其存儲爲一個byte []。這可以給你相當精確的控制,但是可以使你的解決方案減慢高達1000倍。 (沒有什麼是免費的;)

+0

我喜歡LinkedHashMap。但是定義對象的數量是模糊的,因爲沒有人可以阻止系統調整緩存大小。但是如果我從運行時抓取已用內存,然後增加或減少對象的數量,自動設置緩存大小又如何呢? –

+0

哦,我看到java只有Runtime.getTotalMemory(),但沒有getCurrentMemory()... sh ** –

+1

但是,如果沒有實際問題,它可能會很低,因爲它可能有很多免費GC之後的內存。 –

1

SoftReferences的問題是他們給垃圾收集器增加了更多工作。雖然它不符合你的要求,HBase的是爲了防止緩存有助於垃圾收集一個非常有趣的策略,將暫停:它們存儲在本機內存緩存:

你的用例的一個好的開始是將所有的數據存儲在磁盤上。它可能看起來很幼稚,但由於I/O緩存,經常訪問的數據將駐留在內存中。我強烈建議從光油緩存系統閱讀這些架構說明:

0

我找到的最好的做法是,如果可以委派的Java之外的緩存功能。 Java在管理內存方面可能很好,但專用緩存系統不僅僅適用於簡單的LRU緩存。

有與GC很大的成本,當它在踢。

的EHCache是​​比較受歡迎的,我知道的一個。從另一個答案的Java緩存系統也很好。但是,我通常將該工作卸載到底層函數(通常是應用程序服務器的JPA持久層,我讓它在那裏處理,因此我不必在應用程序層處理它)。

如果你正在緩存其他數據,如網頁請求,http://hc.apache.org/httpclient-3.x/也是另一個很好的候選人。

但是,只要記住你還有一個「文件系統」,寫入已檢索的文件系統數據絕對沒有錯。我已經多次使用該技術修復由於ByteArrayOutputStreams使用不當而導致的內存不足錯誤