2011-04-17 84 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