1

这是一个应该是连续运行的无人值守控制台应用程序的问题:我看到过于频繁的应用程序退出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 异常,以便我们可以使用适当的延续逻辑。有任何想法吗?

4

3 回答 3

2

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

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

于 2012-07-07T01:04:14.560 回答
2

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

于 2012-07-07T01:07:13.503 回答
1

您是否有很多大于或等于 85000 字节的对象?每个这样的对象都将进入未压缩的大对象堆。即与Small Object Heap 不同,GC不会移动对象来填充内存空洞,这会导致碎片,这对于长期存在的应用程序来说是一个潜在的问题。

从 .NET 4 开始,情况仍然如此,但似乎他们在 .NET 4.5 中做了一些改进

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

您可能还想看看这个

于 2012-07-07T09:36:26.703 回答