17

我有一个网站,我缓存了很多信息。我看到有关在 asp.net 缓存中存储内容的信息相互矛盾。

例如,假设我有这个数据结构:

 Dictionary<string, List<Car>> mydictionary;

我可以用字符串键将整个内容存储为“MyDictionary”,然后在我拉出对象后向下钻取。

 HttpContext.Cache.Add("MyDictionary",  
   mydictionary, 
   null, 
   Cache.NoAbsoluteExpiration,
   new TimeSpan(10, 0, 0),
   CacheItemPriority.Normal,
   null);

 var myDict = HttpContext.Cache["MyDictionary"] as Dictionary<string, List<Car>>;

我可以做的另一件事是将它分解并将每个项目分别存储在我的字典中的缓存中(假设缓存无论如何都是字典)。

 Dictionary<string, List<Car>> mydictionary;

 foreach (var item in mydictionary.Keys)
 {
      HttpContext.Cache.Add(item, mydictionary[item], null, Cache.NoAbsoluteExpiration, new TimeSpan(10, 0, 0), CacheItemPriority.Normal, null);
 }

 var myitem = "test";
 var myDict = HttpContext.Cache[myItem] as List<Car>;

性能影响是否会有很大不同(假设我假设一切都在内存中?)

4

3 回答 3

14

在这里添加一个额外的答案,因为我觉得现有的答案捕捉到了“什么”,但还没有捕捉到“为什么”。

最好将单个条目单独存储在缓存中的原因与性能无关。相反,它与允许系统执行适当的内存管理有关。

ASP.NET 缓存中有很多逻辑可以弄清楚当它遇到内存压力时该怎么办。最后,它需要踢出一些项目,并且需要以尽可能少的破坏性方式执行此操作。它选择踢出哪些项目很大程度上取决于它们最近是否被访问过。还有其他因素,例如在缓存时传递的标志。例如,您可以使一个项目不可移动,并且它永远不会被踢出。

但是回到这个问题,如果您将整个字典存储为单个项目,那么您只给 ASP.NET 内存管理器留下两个选项:保持整个内容处于活动状态,或者杀死整个内容。即,您完全失去了将“热门”项目保留在缓存中的好处,而您很少访问的占用内存的项目则被踢出。换句话说,您失去了任何级别的缓存粒度。

当然,您可以选择在字典中实现自己的方案来删除很少使用的项目。但是那时你正在重新发明轮子,而你的新轮子将无法正常工作,因为它不会与系统的其余部分协调。

于 2012-04-09T05:13:10.197 回答
7

正如你所说,对此有两种相反的意见。

它真正归结为缓存条目可能应该在需要时以最细粒度的级别存储。我的意思是,如果您每次使用字典中的每个条目时都使用它,那么将其存储在字典级别。

如果您只使用字典中的一项,并且您不阅读字典,则将它们存储在个人级别。

因此,如果您将整个集合视为一个单元,则将其缓存为一个单元。如果集合是随机访问的,并且一次只需要某些项目,则将其存储在单个单元的级别。

于 2012-04-09T04:17:06.123 回答
3

到目前为止,第二种方式更好。

想想必须考虑许多对象。每次你必须得到 1 个值时,你只需要得到它,而不是抓取整个字典,然后从中得到你想要的。

这并不是说缓存中使用的算法来确定最常用项目的优先级(如果我还记得的话,MRU)。

我只是建议您在将其作为最终实现之前使用它来衡量性能增益。

于 2012-04-09T00:56:17.900 回答