确切地说,MemoryCache的内存限制是什么意思?

时间:2015-08-08 03:20:59

标签: c# .net caching memorycache

System.Runtime.Caching.MemoryCache是.NET Framework(版本4+)中的一个类,它使用字符串作为键来缓存内存中的对象。超过System.Collections.Generic.Dictionary<string, object>,这个类有各种各样的花里胡哨,让你可以配置缓存增长到多少(以绝对或相对的方式),为不同的缓存项设置不同的过期策略,等等更多。

我的问题与内存限制有关。 MSDN上的所有文档似乎都没有令人满意地解释这一点,并且Reference Source上的代码相当不透明。很抱歉将所有这些打成一个问题&#34;,但我无法弄清楚如何将一些问题纳入他们自己的问题中,因为他们实际上只是对整体问题的看法不同问题:&#34;你如何将惯用的C#/ .NET与一个通常有用的内存缓存的概念进行协调,该缓存具有几乎完全在托管代码中实现的可配置内存限制?&#34;

  1. 密钥大小是否计入MemoryCache占用的空间?实习池中的键怎么样,每个键应该只添加对象引用的大小到缓存的大小?
  2. 在确定存储在池中的对象大小时,MemoryCache是​​否考虑的不仅仅是它存储的对象引用的大小? 我的意思是......它必须,对吗?否则,配置选项对于常见情况极具误导性......对于剩下的问题,我将假设它存在。
  3. 鉴于MemoryCache几乎肯定会考虑超过缓存中存储的值的对象引用的大小,它有多深?
    1. 如果我正在实施这样的事情,我会发现非常难以考虑&#34;孩子的内存使用情况&#34;个别物品的成员,而不是拉入父母&#34;参考资产。
    2. 例如,想象一下游戏应用程序中的一个类PlayerPlayer具有一些特定于玩家的状态,其封装在public PlayerStateData PlayerState { get; }属性中,该属性封装了玩家正在查看的方向,他们持有多少个链轮等等,以及对整个游戏状态public GameStateData GameState { get; }的引用,可用于从仅了解玩家的方法返回游戏(更大)状态。
    3. 在考虑缓存贡献的大小时,MemoryCache是​​否同时考虑PlayerStateGameState
    4. 也许它更像是&#34;直接存储在缓存中的对象占用的托管堆上的大小,以及&#39 ;可通过这些对象的成员访问&#34;?
    5. 似乎将GameState对限制的贡献的大小乘以5是愚蠢的,因为5个玩家被缓存......但是再一次,可能的实现可能只是那,并且在不计算PlayerState的情况下很难计算GameState
  4. 如果一个对象在MemoryCache中多次存储,每个条目是否分别计入限制?
  5. 与前一个相关,如果一个对象直接存储在MemoryCache中,而且间接存储在另一个对象的成员中,那么它们对内存限制有什么影响?
  6. 如果一个对象存储在MemoryCache中,但也被一些完全与MemoryCache断开连接的其他活动对象引用,哪些对象计入内存限制?如果它是一个对象数组呢?有些(但不是全部)对象有外来引用吗?
  7. 我自己的研究引导我SRef.cs,我在获得here之后放弃了试图理解,后来导致here。猜测所有这些问题的答案将围绕寻找和冥想最终填充存储在该句柄中的INT64的代码。

1 个答案:

答案 0 :(得分:1)

我知道这已经很晚了,但我已经在源代码中进行了大量挖掘,试图了解发生了什么,现在我有一个相当不错的主意。我会说MemoryCache是​​MSDN上记录最差的类,对于那些试图优化其应用程序的人来说,它会让我感到困惑。

MemoryCache使用特殊的&#34;大小的参考&#34;测量物体的大小。它看起来像内存缓存源代码中的一个巨大的黑客,涉及反射来包装一个名为&#34; System.SizedReference&#34;的内部类型,从我可以告诉它导致GC设置对象图的大小它指向第2代收藏。

从我的测试中,这将包括父对象的大小,因此包括父等引用的所有子对象,但我发现如果你引用父对象弱引用(即通过{{1或者WeakReference)然后它不再被视为对象图的一部分,所以这就是我现在对所有缓存对象所做的。

我认为缓存对象需要完全自包含或使用对其他对象的弱引用才能使内存限制正常工作。

如果你想自己玩它,只需从WeakReference<>复制代码,创建一个对象图并指向一个新的SRef实例,然后调用GC.Collect。收集后,大致的大小将设置为对象图的大小。