【发布时间】:2014-02-26 07:20:44
【问题描述】:
我正在实现一个 LRU 缓存。在将数据放入缓存时,我需要检查我是否有足够的内存来存储新数据,如果没有,则调用缓存逐出例程。如何检查可用内存?
【问题讨论】:
标签: c#
我正在实现一个 LRU 缓存。在将数据放入缓存时,我需要检查我是否有足够的内存来存储新数据,如果没有,则调用缓存逐出例程。如何检查可用内存?
【问题讨论】:
标签: c#
我需要检查我是否有足够的内存来存储新数据,如果没有则调用缓存逐出例程。
这是一个非常糟糕的主意。你不应该这样做。
正如 Raymond Chen 经常说的:当两件事试图做到这一点时会发生什么?假设您在两个不同线程上的同一地址空间中有两个组件。现在你遇到了最糟糕的竞争条件:两个组件都询问是否有足够的内存。假设其中一个有足够的内存,但不是两个。什么神奇的力量告诉他们其中一个做缓存驱逐而不是另一个?没有这样的力量。两者都会尝试分配内存,而一个会失败。
即使没有两件事,基本想法也很糟糕。这里的想法是尽可能靠近悬崖边缘行走,但不要太近以至于你从悬崖上掉下来。 这是从悬崖上掉下来的秘诀。你永远不应该在任何地方,甚至是模糊地接近悬崖的边缘。你应该看看那 20 亿字节的虚拟地址空间,然后想:“哇,这太可怕了。我永远不会接近用完它。”如果您确实认为自己可能会用完,那么您需要将一些工作转移到另一个进程中,或者使用内存映射文件并管理您自己的虚拟内存。
所以让我们退后一步。缓存是一种性能优化,它通过以更少的时间换取更多的内存使用来工作。您应该问自己的问题是我的客户几乎不能接受什么水平的性能?量化它。那么先问一下,没有缓存的性能已经可以接受了吗?如果可以,那你就不需要烧内存了;你已经足够好了。如果它还不够好,那么尝试提出一个固定大小的缓存,以提供足够好的性能。只有当你不能做到这一点时,你才应该使用更高级的技术。
大型缓存的常用技术是让垃圾收集器负责缓存:使缓存成为弱引用的缓存。弱引用是不阻止垃圾回收但也不鼓励垃圾回收的引用;基本上,如果感觉内存不足,GC 会收集一些弱引用对象。您的缓存逻辑基本上是:缓存所有内容。当需要搜索缓存时,询问弱引用是否已被收集。如果答案是肯定的,则从缓存中删除弱引用。如果答案是否定的,则将其转回强引用并使用该对象。这种技术有效,但也有其缺点:即,您只是让 CLR GC 团队负责调整缓存。他们可能对什么是好的缓存策略有不同的想法。
【讨论】:
不完全是您的要求,但就您而言,我会去检查MemoryFailPoint
【讨论】: