【问题标题】:Understanding .NET GC and OutOfMemory Exceptions了解 .NET GC 和 OutOfMemory 异常
【发布时间】:2023-04-03 02:35:02
【问题描述】:

我正在对 .NET 2.0 Windows 服务应用程序中的 OutOfMemory 异常进行故障排除。为了更好地理解这个问题,我首先编写了一个简单的 .NET WinForm 测试应用程序,该应用程序通过构建一个 ArrayList 直到引发 OOM 异常来生成 OOM 异常。异常被捕获并记录下来,我可以单击表单按钮再次运行 OOME。我发现奇怪的是在第 4 次运行时,下一次 OOME 之前消耗的内存量大约是一半。每次运行时,下面列出的结果都是一致的。 Eyeballing TaskManager 也确认了该行为。不幸的是,Perfmon 在试图获得更好的统计数据时冻结了。有人可以解释为什么 3 次运行后内存限制会降低吗?我对GC的理解相当肤浅。您还可以看到我在再运行几次后运行了 GC.Collect(),但它对降低限制没有帮助。

更新:我还发现对于每个数组列表项使用 const 字符串与使用新对象有很大不同。代码很简单:

const string TEST_TEXT = "xxxxxxxxxx";
ArrayList list = new ArrayList();
while (true)
{
    list.Add(TEST_TEXT);
}

开始循环:内存 10,350,592

  • 抛出 OOM 异常
  • 数组大小:134,217,728

结束循环:内存550,408,192

开始循环:内存 550,731,776

  • 抛出 OOM 异常
  • 数组大小:134,217,728

结束循环:内存 551,682,048

开始循环:内存 551,813,120

  • 抛出 OOM 异常
  • 数组大小:134,217,728

结束循环:内存 551,772,160

开始循环:内存 551,903,232

  • 抛出 OOM 异常
  • 数组大小:67,108,864

结束循环:内存282,869,760

开始循环:内存 283,004,928

  • 抛出 OOM 异常
  • 数组大小:67,108,864

结束循环:内存 282,910,720

GC.Collect 手动触发

开始循环:内存14,245,888

  • 抛出 OOM 异常
  • 数组大小:67,108,864

结束循环:内存283,344,896

【问题讨论】:

  • 你的测试程序到底做了什么?它是如何“构建数组”的?
  • 请发布您的代码。
  • 参见上面的代码示例。
  • 这样的字符串字面量是实习的。对 ArrayList 的每次添加只会创建对同一内存块的新引用(此外,ArrayList 在 .Net 2.0 及更高版本中是邪恶的:不要使用它)。
  • 只是好奇为什么 ArrayList 在 2.0+ 中被认为是邪恶的。与使用通用等效项相比?

标签: .net garbage-collection out-of-memory


【解决方案1】:

以下几点综合起来,希望能为您提供足够的信息来回答您的问题:

  • 不管它的名字,OutOfMemory exceptions are just as likely to mean you are out of Address Space as physical RAM.
  • GC.Collect 收集所有未完成的 RAM。 .Net 中的垃圾收集是非确定性的,这意味着无法强制运行时清理所有 RAM。
  • .Net 中的垃圾收集器是,这意味着当一个对象在收集中幸存下来时,它会向上移动到更高的代,从而使其更不可能被收集。
  • 当您的 OutOfMemory 异常被抛出时,您的数组可能已经在几次收集尝试中幸存下来,或者甚至被移到了 LargeObjectHeap。
  • 数组大小是固定的。要将新元素添加到数组中,您必须完全重新分配数组。 (使用列表之类的结构可能会获得更好的测试结果)。

【讨论】:

    【解决方案2】:

    由于您正在构建数组,我假设您为每次运行构建一个大数组。如果是这种情况,它将存储在大对象堆中(因为它将> 85000 字节)。 LOH 不像分代堆那样压缩,因此您看到的大小下降可能是由于堆碎片造成的。

    【讨论】:

    • 现在几乎没有理由使用 ArrayList,但在这种情况下并没有什么不同,因为 ArrayList 在内部也使用数组。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-09
    • 2017-05-04
    • 1970-01-01
    • 1970-01-01
    • 2015-07-28
    • 2018-06-18
    • 2015-04-25
    相关资源
    最近更新 更多