我在字典中保留了一个大缓存,其值为IEnumerable<KeyValuePair<DateTime, Double>>
。我会定期从字典中删除项目,并定期将项目添加到字典中。我一次又一次得到一个System.OutOfMemoryException。我想知道垃圾收集器为什么不来救我?
答案 0 :(得分:3)
请记住,正如@Gabe所提到的那样,堆可能会碎片化。即使你可能有空闲内存,它也可能没有足够大的块来分配字典,当它执行它的大小时。
也许您可以使用模式和实践库MSDN Library Link中的缓存块来帮助您实现良好的缓存。也许您可以选择一种不动态分配内存的算法,并且具有固定数量的条目?
另请注意,如果没有可以使用的内存,那么缓存大小就会出现问题,而不是垃圾收集器。
答案 1 :(得分:2)
很有可能GC 很多时候都会拯救你,但你有时会超越它的能力。
为了绝对清楚,这是Dictionary<DateTime, Double>
还是Dictionary<SomeKeyType, IEnumerable<KeyValuePair<DateTime, Double>>>
?如果是后者,那么也许你会在其他地方保留参考文献?
你的缓存有多大?你有监控来跟踪它吗?是什么让你觉得这是导致问题的字典?如果您可以控制缓存的数量,那么您是否尝试过缩小尺寸?
答案 2 :(得分:2)
既然你问为什么GC没有拯救你,我会给出答案。
使用带垃圾收集器的编程语言/环境可以让您更轻松,但不会使内存管理成为过去。
如果你在一台32位xp的机器中分配大量内存超过2 gig,你就会到达第一个.Net内存边界之一。在内存中保持2演出总是一个坏主意。
在运行大型数据库等的内存受限机器上,您将很快达到可用内存的界限。由于GC不能识别操作系统,因此它可能会注意到内存不足的情况(创建像位图这样的巨大对象可能会触发这种情况)。一旦你设置了一个巨大的对象,没有任何帮助,手动调用GC.Collect。
在内存中保存一本大词典是一个非常简单的描述。你能告诉我们这个系列中有什么东西,理论上这些东西有多大。
如果您的意思是2,147,483,647项,则可能达到整数大小限制。
总结一下:
答案 3 :(得分:0)
我不确定,对不起我,如果我错了,但也许当大于85kB时字典存储在大对象堆中(如字节[90000])
像加布赛义德一样:我可以看到,大型对象堆可能会碎片化,并且您无法在点之后增长字典
当LOH碎片化时,它有时没有足够的空间来存储带有contigus地址的对象。这就是造成OutOfMemory异常的原因。它更像是LOH异常中的Out Of Contigus空间。