一种字典,可以将不经常访问的元素保存到磁盘中

时间:2013-07-21 19:40:37

标签: c# database serialization dictionary out-of-memory

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

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

字典使用模式的分析表明,通常较小部分的值是“热”(经常访问),其余(较大部分)是“冷”(很少或从不访问)。很难说如果新的值是热的还是冷的,那么一些值可能会随着时间的推移在热点和冷点之间来回移动。

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

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

3 个答案:

答案 0 :(得分:2)

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

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

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

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

但请记住,最常用的和最重的是权衡。每天丢失一个对象需要花费5分钟才能恢复,这会让用户感到烦恼,而不是丢失10000倍的工具,只需要5ms即可恢复。

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

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

答案 1 :(得分:0)

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

MemoryCache周围实施一个包装器:

  1. 添加指定了逐出回调的项目。回调会将被驱逐的项目放入数据库。
  2. 如果在检索过程中MemoryCache中没有该项,则从数据库中获取项目并将其放回MemoryCache中。
  3. 如果您期望在数据库和内存中丢失大量项目请求,您可能还需要为当前/缺失的项目实现bloom过滤器或缓存键。

答案 2 :(得分:0)

我过去也遇到过类似的问题。

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

Is it there any LRU implementation of IDictionary?

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