15

在我的应用程序中,我使用了一个字典(支持添加、删除、更新和查找),其中键和值都可以序列化或可以序列化(值可能是非常大的对象图)。当字典变得如此之大以至于将其完全保存在内存中时,我开始偶尔触发OutOfMemoryException(有时在字典方法中,有时在代码的其他部分中)。

在尝试用数据库完全替换字典后,性能下降到无法接受的水平。

对字典使用模式的分析表明,通常一小部分值是“热的”(经常访问),其余的(大部分)是“冷的”(很少或从不访问)。很难说何时添加新值是热的还是冷的,此外,随着时间的推移,某些值可能会在冷热部分之间来回迁移。

我认为我需要一个字典的实现,该字典能够在内存不足事件时将其冷值刷新到磁盘,然后按需重新加载其中一些并将它们保留在内存中,直到下一个内存不足事件发生时它们的热/冷状态将被重新评估。理想情况下,实现应该根据应用程序中的内存使用情况巧妙地调整其冷热部分的大小和刷新间隔,以最大限度地提高整体性能。因为应用程序中存在多个字典实例(具有不同的键/值类型),我认为他们可能需要协调他们的工作流程。

您能否建议如何实施这样的字典?

4

3 回答 3

2

为 64 位编译,在 64 位上部署,添加内存。把它留在记忆中。

在你自己成长之前,你也可以看看 WeakReference http://msdn.microsoft.com/en-us/library/ms404247.aspx。当然,这需要您重建那些被回收的对象,但人们应该希望那些被回收的对象不会被太多使用。它附带了一个警告,即它自己的指南声明避免使用弱引用作为内存管理问题的自动解决方案。相反,开发一个有效的缓存策略来处理您的应用程序的对象。

当然,您可以忽略该准则并有效地使用您的代码来解释它。

您可以实施缓存策略,并在到期时保存到数据库,获取获取和缓存。当然使用滑动到期,因为您关心保留那些最常用的。

但是请记住,最常用与最重是一种权衡。每天丢失一个对象 10 次需要 5 分钟才能恢复,这比丢失一个对象 10000 次需要 5 毫秒来恢复更让用户烦恼。

上面有人提到了网络缓存。如前所述,它使用回调进行自动内存管理,这取决于您是否想在您的应用程序中使用它。

而且......最后但并非最不重要的一点是,看看分布式缓存。通过分片,您可以将大字典拆分到几台机器上。

于 2013-08-20T08:49:44.213 回答
0

我过去也有类似的问题。

您正在寻找的概念是带有 LRU(最近最少使用或最近使用)队列的读取缓存。

IDictionary 是否有任何 LRU 实现?

当您将内容添加到字典中时,请跟踪最近最少使用的内容,将它们从内存中删除并将它们保存到磁盘。

于 2013-08-14T15:10:45.370 回答
0

只是一个想法-从未这样做过,也从未使用过System.Runtime.Caching

在MemoryCache周围实现一个包装器,它将:

  1. 添加指定了驱逐回调的项目。回调会将被驱逐的项目放置到数据库中。
  2. 如果在检索期间 MemoryCache 中不存在该项目,则从数据库中获取项目并将其放回 MemoryCache。
  3. 如果您期望对数据库和内存中都丢失的项目有很多请求,那么您可能还需要为现有/丢失的项目实现布隆过滤器或缓存键。
于 2013-07-21T20:41:11.200 回答