垃圾回收运行得太晚 - 导致OutOfMemory异常

4

请问有人能解释一下吗?

我有一个应用程序,它有很大的内存占用(和内存波动)。没有内存泄漏,垃圾收集器(GC)通常很好地释放资源。

然而,偶尔会出现GC不及时的情况,导致内存不足异常。我想知道这是为什么?

我使用了非常好的REDGate分析工具,应用程序呈典型的“锯齿状”图案 - OOMs发生在锯齿的顶部。不幸的是,分析工具不能用于识别内存波动的来源。

是否可以设置一种内存“软限制”,在该限制下强制进行GC? 目前,只有当内存达到其绝对限制时才执行GC,导致OOM。


1
想知道为什么一次需要这么多内存中的数据。。 - Simon Whitehead
1
我会运行内存分析器,因为往往情况下当你遇到内存溢出异常时,你正在做一些你不想做的事情。手动调用垃圾回收器并不能解决问题 - 如果可以的话,那么你在第一次就不会遇到OOM异常了。 - lahsrah
停止分配和收集内存,而是考虑使用池类型架构。这样可以减少在不确定GC的情况下出现的内存抖动问题。 - spender
1
“没有内存泄漏”这不是过于乐观了吗? - dowhilefor
你是否创建了许多大于85KB的对象? - Henrik
显示剩余6条评论
3个回答

2

垃圾回收“没有及时发生”实际上是不可能的。它们发生在新内存分配将Gen-0推向一定限制之前。因此,它们总是在内存分配将内存推向其限制之前发生。这种情况在全球每天发生多次,如果有任何错误都不为人所知,我会感到惊讶。

您是否考虑过实际上分配的内存超过了可用内存?在大多数32位机器上,操作系统只允许您访问2GB。

还有其他一些可能性:

  1. 您的应用程序是否使用非托管内存?
  2. 您的应用程序是否固定了任何内存?如果是,那可能会导致碎片问题,特别是如果您没有释放固定。

这个问题似乎在询问是否可以设置限制。您能否添加有关如何确定Gen-0限制的任何信息。例如,它是否考虑了整体空闲系统内存。 - crokusek

1

如果你使用了很多内存并且进行了大量的垃圾回收,那么我想你应该考虑“享元”设计模式。

例如,如果你频繁进行字符串垃圾回收,请参考String.Intern(string s)。Msdn 参考


1
什么是“轻量级”设计模式? - spender
我现在也很好奇。@Thomas,你有这个设计模式的来源吗? - Simon Whitehead
最初@Thomas写了“轻量级设计模式”,也许他指的是享元模式或类似的东西,但在进行一些语法修正时,我将“轻量级”一词放入括号中,这给我们带来了“‘轻量级’”这个词,使我们感到困惑。对此表示抱歉。 - alex.b
谢谢Aleksey,我在想法语(设计模式Poids-mouche - http://fr.wikipedia.org/wiki/Poids-mouche_(patron_de_conception)),对于我的糟糕的翻译感到抱歉。我是指Flyweight。 - Thomas
我已经为你 Thomas 修改了 Wording 为 Flyweight。 - Martin Brown

-1

你可以使用GC.collect()来强制垃圾回收器执行其工作。但这并不是首选方法。

使用内存分析工具(如memprofiler)来检测泄漏。几乎所有的代码都会在某些时候出现泄漏。


4
请使用正确的拼写。这不是聊天。 - Daniel Hilgarth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接