慢性不合适的System.OutOfMemoryException发生

时间:2012-07-07 00:58:58

标签: c# out-of-memory

这应该是一个连续运行的,无人值守的控制台应用程序的问题:我看到来自System.OutOfMemoryException的应用程序退出频繁出现在调用堆栈深处的各种方法中 - 通常System.String.ToCharArray()System.String.CtorCharArrayStartLength()System.Xml.XmlTextReaderImpl.InitTextReaderInput(),但有时会在System.String.Concat()电话的筹码中MongoCollection.Save()来电,以及其他不太可能的地方。

对于它的价值,我们使用并行任务,但这实际上是服务器上运行的唯一应用程序,并且应用程序的线程数永远不会超过60.在某些情况下我知道抛出一些其他异常的原因,但OutOfMemoryException在这些上下文中没有任何意义,并且它会产生问题:

  • 根据TaskManager和Perfmon日志,当发生这种情况时,系统的8GB可用内存中最小为65%
  • 虽然异常处理程序有时会触发&记录异常,它们不会阻止应用程序崩溃,并且
  • 没有用户交互就没有继续这个例外(除非你禁止Windows错误报告,这不是我们想要的系统范围,或者将应用程序作为服务运行,这对我们的使用来说可能是次优的 - 情况下)

所以我知道上面提到的解决方法,但我真正喜欢的是一些解释 - 理想情况下是一个基于代码的处理程序 - 用于意外的OOM异常,以便我们可以使用适当的延续逻辑。有什么想法吗?

3 个答案:

答案 0 :(得分:2)

在使用3GB内存时获取该异常表明您运行的是32位应用程序。将其构建为64位应用程序,它将能够使用尽可能多的内存(接近8GB)。

至于为什么它首先失败了......你使用的数据有多大?如果它不是很大,你是否寻找对数据的引用要比它们所需的时间长得多(即内存泄漏),从而阻止正确的GC?

答案 1 :(得分:2)

您需要对应用程序进行概要分析,但这些异常的最常见原因是过多的字符串创建。此外,过多的序列化可能会导致这种情况和过多的Xslt转换。

答案 2 :(得分:1)

你有很多大于或等于85000字节的对象吗?每个这样的对象都将转到大对象堆,即not compacted。即与小对象堆不同,GC将移动对象以填充内存空洞,这可能导致碎片化,这对于长期应用程序来说是一个潜在的问题。

从.NET 4开始,情况仍然如此,但似乎是some improvements in .NET 4.5

快速而肮脏的解决方法是确保应用程序可以通过将其构建为“x64”或“任何CPU”来使用所有可用内存,但真正的解决方案是尽量减少大型重复分配/释放周期对象(即如果可能的话,使用对象池或完全避免大对象)。

您可能还想查看this