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