【问题标题】:C#: Will GC collect if it needs memory, or will it give out of memory exception?C#:如果需要内存,GC 会收集,还是会发出内存不足异常?
【发布时间】:2011-08-28 07:15:05
【问题描述】:

我的代码中有一个循环,它生成许多 byte[] 数组(每个数组大约 1 到 2 MB),用数据填充它们,然后丢弃引用。因此,即使参考仅保留 短时间内,我可以看到私有工作集在增长。

现在,如果我尝试在循环后分配一个大数组(~ 400 MB),我会得到内存不足的异常吗?还是分配会强制GC收集瞬态数据?

谢谢!

【问题讨论】:

    标签: c# memory-management garbage-collection large-object-heap


    【解决方案1】:

    生成许多 1-2MB 的数组是个坏主意。即使您避免出现内存不足的情况,性能也会受到影响。在大对象堆上分配许多短期对象是当前 GC 处理不好的一种分配模式。

    我强烈建议尽可能回收它们。实现一个池,一旦您不再需要它们,就将它们扔到其中。然后在分配时首先检查您是否可以满足来自池的请求。这种模式为我的一个程序带来了巨大的性能优势。

    我认为全内存会强制进行 GC,但如果非托管分配发生在同一时间,您仍然可以获得 OOM。

    【讨论】:

    • “在大对象堆上分配许多短期对象是当前 GC 处理不好的分配模式。”想在这里找到您的来源吗?
    • @Andy 这是我自己的经历。我有一个项目每秒将多个屏幕截图放入数组中,一旦我使用池化来重用数组,性能就会变得更好。
    • 我认为原因很简单,就是您分配的每秒大量内存一直在强制 GC。对于大型对象,即使每秒分配相对较少,您也会分配和丢弃大量内存。我在某处读到 LOH 对象仅在 Gen2 收集期间收集,但我不确定。
    【解决方案2】:

    如果你担心它,你可以随时调用 GC.Collect();在循环之后的那个大数组之前,这将强制所有代的垃圾收集。但是不要在循环中做,除非你不关心时间,因为这可能会相当慢(对于循环来说太慢了,对于一次性的事情来说却不是那么慢。)

    【讨论】:

      【解决方案3】:

      这真的取决于。你不能确定垃圾收集器会及时丢弃。使用字节数组你是相当安全的,但是如果你大量使用它们而不使用dispose() 方法,大多数对象都被丢弃得太晚了。
      即使您可能已丢弃所有引用,这也会导致内存不足异常。
      如果您遇到问题,可以尝试GC.Collect(0);,尽管这通常是不可取的。

      【讨论】:

      • Dispose 与 GC 无关。
      • 如何在这里提供帮助?我认为字节数组甚至没有它。
      • Dispose 实际上并不释放内存。它通常会释放非托管资源。
      • 如果我没记错的话,使用 dispose 会将对象标记为已完成,从而导致在收集垃圾时不必运行终结器。这让 GC 可以更轻松地释放内存。
      • 即使那是正确的,除非在非常特殊的情况下,否则您不必担心。
      猜你喜欢
      • 2011-03-08
      • 2014-06-07
      • 1970-01-01
      • 2012-01-23
      • 1970-01-01
      • 2016-07-27
      • 2010-09-17
      • 1970-01-01
      相关资源
      最近更新 更多