.NET MemoryCache:它如何强制执行内存限制?

时间:2016-07-23 00:28:53

标签: c# asp.net caching memory garbage-collection

.NET roadmap document是C#对象的缓存。某些对象可能具有复杂的结构,而其他对象可能具有不安全的引用。 C#是否为实现MemoryCache做了一些魔术,还是只计算每个对象的浅层大小?

我怀疑后者是这样的。但是,如果我在缓存中多次放置相同的对象(例如,用于跟踪缺失的项目),是否会将该大小记录一次,或者是否包含该实例的每个条目?

4 个答案:

答案 0 :(得分:6)

.NET MemoryCache类似于ASP.NET Cache类。如果我们查看ASP.NET Cache,我们会看到一个名为CacheItemRemovedCallback的函数。从Cache中删除Item时会触发此操作。

此函数为CacheItemRemovedReason提供回调函数。如果我们查看原因,我们会看到一个项目可以从缓存中删除,因为系统将其删除以释放内存。因此,虽然PhysicalMemoryLimit给出了缓存可以在单个步骤中使用的物理内存的百分比,但我认为它们会将其留给系统以在缓存达到限制时清除缓存。

如果您确实将Cache项目放入具有Add功能的缓存中,则会将其添加为新的CacheItem实例。所以会被多次考虑。如果您使用函数AddOrGetExisting,它将检查该项是否已在缓存中。如果是这样,它将使用该实例而不是新实例。那么它将被记录一次。

希望这能帮助你朝着正确的方向前进。

答案 1 :(得分:2)

阅读文档时,缓存似乎没有尝试计算它正在缓存的对象的大小。这是有道理的,因为它不是可以在任何类型的进程本身内完成的(你可以为固定大小的结构,或固定大小结构的数组,但这是关于它);一点谷歌搜索将确认给你。但它确实知道计算机上有多少RAM;你可以从new Microsoft.VisualBasic.Devices.ComputerInfo().AvailablePhysicalMemory自己得到这个。因此,缓存可能会做两件事:

  1. 跟踪上次使用每个对象的时间。
  2. 在某个时间间隔内轮询内存统计信息。
  3. 然后在每次轮询时,可用内存量在可接受的限制范围内,或者不是。如果它在可接受的范围内,它什么都不做。如果不是,则开始删除项目,最后一次访问的项目最早被删除。它会不断删除项目,直到内存恢复到可接受的限制范围内。

    如果您考虑一下,几乎所有可以使用缓存可用的信息。

    这个策略没问题,但是如果你有其他对象持有对缓存中项目的引用,它显然会崩溃,因为从缓存中删除项目不会释放垃圾收集。这是回调的重点,要执行清理以确保不再有对该对象的引用。

答案 2 :(得分:1)

这是来源。如果你看一下调用AddOrGetExisting的Add方法:referencesource.microsoft.com的实现,你的第二个问题的答案是显而易见的。

我不知道大小,但我猜你认为没有任何魔法是正确的。如果您有兴趣,也可以深入检查来源。

答案 3 :(得分:-2)

您无法轻松设置MemoryCache类的PhysicalMemoryLimit或CacheMemoryLimit成员,因为它们没有实现setter (至少在.Net 4.0版本中)。

我同意其他答案,如果您只想缓存一个对象的单个实例,则应该使用AddOrGetExisting。如果不是,您可以使用不同的密钥缓存备用项。