2011-04-17 83 views
5

我需要在java中實現一個具有最大大小的緩存,並且想要使用內存中緩存的實際大小而不是緩存中元素的數量。這個緩存基本上將String作爲鍵和String作爲值。我已經使用Java的LinkedHashMap結構實現了緩存,但問題是如何知道緩存的實際大小,以便我可以調整策略以在大小過大時丟棄對象。LRU字節緩存java

想要使用工具包的getObjectSize()來計算它,但它看起來不像預期的那樣工作。

當我做getObjectSize(一個字符串),無論字符串的大小是什麼,它返回相同的大小:32.我想這只是使用字符串的參考大小或類似的東西,而不是內容。所以不知道如何有效地解決這個問題。

你有什麼想法嗎?

非常感謝!

回答

4

您可能要考慮使用Ehcachememory based cache sizing

+0

Thx,這應該使工作,可能比我實施的緩存更好,我猜。你會建議什麼類型的緩存?根據條目的數量或緩存的大小?知道應用程序應該在服務器上運行,並且可以使用機器上的所有可用內存。 – Abbadon 2011-04-17 14:28:52

1

如果您的鍵和值都是字符串,那麼計算很容易:字符串中的對象開銷+每個字符2個字節。在32位Sun JVM上,32字節的開銷聽起來正確。

有幾點需要注意:首先,用於存放緩存的地圖會增加自己的開銷。這將取決於哈希表的大小和地圖中的條目數量。就個人而言,我只是忽略所有開銷,並根據字符串長度進行計算。

其次,除非您通過身份跟蹤字符串,否則可能會因爲同一個字符串可能與多個密鑰存儲在一起而導致過度計數。由於通過身份跟蹤字符串會增加更多開銷,這可能不值得。

最後:雖然內存有限的緩存似乎是一個好主意,但它們很少。如果您足夠了解應用程序,則應知道平均字符串長度,並可根據條目數控制緩存。如果你不太瞭解你的應用程序,一個簡單的LRU過期策略可能會讓你陷入困境:一個大的條目會導致很多小的條目過期。如果發生這種情況,除非重建的成本與大小成正比,否則您的緩存效率會降低。

+0

+1 ...附加說明:*「字符」*實際上適用於Java字符。如果由於某些原因,OP使用的Unicode字符只能在Unicode 3.1以上纔可用,那麼需要兩個Java * char *(因爲一個Java * char *只能保存Unicode 3.0代碼點),因此需要4個字節每個「字符」:) – SyntaxT3rr0r 2011-04-17 14:11:01

+0

Thx的答案,這是非常有趣的,所以也許我會選擇參賽的人數。事實上,字符串通常有兩個值,最多140個字符的小字符串,以及代表一組值的非常大的字符串,通常小字符串應該更頻繁。重建條目的成本是運行一致的算法和帶寬,所以我認爲它與大小不成比例,但較大的條目更難以重建。大字符串也不太可能被訪問。 – Abbadon 2011-04-17 14:22:07

+0

@Syntax - 好點 - 當我在檢查文檔之前告訴你錯誤:-)時,我學到了一些東西.-我一直認爲'String.length()'返回的字符數和'String。需要使用codePointCount()來將補充字符轉換爲非BMP代碼點。我現在知道要更加小心。 – Anon 2011-04-17 14:52:56