【问题标题】:Why calling GC.Collect() multiple times free some memory that usually isn't cleaned?为什么多次调用 GC.Collect() 会释放一些通常不会被清理的内存?
【发布时间】:2013-04-18 18:30:10
【问题描述】:

我在 GC 中发现了一件奇怪的事情,当我的应用程序删除了对许多大对象的引用时,它仍然会消耗大量内存,在我的情况下大约 300mb。即使我调用GC.Collect(),这块内存也不会被清理

然后我尝试在几秒钟内随机调用它 10 次,结果:释放了 200mb 的内存,导致我的应用程序只吃 100mb 而不是 300mb 的私有内存(不是虚拟的,而是物理/常驻内存)

这是为什么?如何让 GC 自动清理此内存而无需手动调用?

【问题讨论】:

  • 您的对象有多大?超过 85,000 字节?如果是这样,它们就在大对象堆上。 GC 对 LOH 的规则与对其他内存的规则不同。如果它们在 LOH 上,您可能正在查看内存碎片。
  • 您可以使用 sos.dll msdn.microsoft.com/en-us/library/bb190764.aspx 查看内存中哪些对象是活动的,哪些对象持有对它们的引用。这可能有助于缩小导致您观察的原因
  • 我不能使用sos,因为我有Visual Studio的免费版本,但是我的对象通常不是那么大,其中大部分,有些可能是

标签: c# memory


【解决方案1】:

要么:

  1. 您仍然在某处持有对大对象的引用,因此即使调用 GC.Collect 也无法清理它。

  2. 非托管内存占此内存消耗的大部分。您没有正确处置该非托管资源。

【讨论】:

  • 是的,这很可能是 2,因为我正在使用一些可能导致内存释放延迟的第 3 个 c++ 库......或者我不知道,但在我看来,实际上调用 GC.Collect MULTIPLE TIMES 导致了这一点。这很奇怪
  • 也许某个没有引用的对象可能包含对另一个对象的引用,并且对于链中的 10 个其他对象来说也是如此。所以在每次运行 GC.Collect 一个它们被删除并清理另一个引用?
  • @Petr 这可能是因为集合导致终结器运行,最终将导致非托管内存被释放。如果您等待收集发生一次,然后等待更长时间等待终结器队列运行,您会看到同样的事情。 “正确”的解决方案是手动处理 IDisposable 对象,而不是将其留给终结器。
  • @Petr 对于您的第二条评论,不。如果有一个完整的对象图相互引用,但它们都没有被根对象引用,那么它们都将被清除。调用多个集合对您没有任何帮助。它正在调用一个,然后等待一段时间。您在那段时间所做的事情无关紧要。
【解决方案2】:

垃圾收集器将在需要更多内存时收集任何未使用的对象。一个对象只有在你没有引用它时才被使用。使用内存分析器查看哪些对象占用了您的内存以及它们未被收集的原因。

除此之外,您永远不需要致电GC.Collect。垃圾收集器功能强大,并且经过优化,可以选择何时执行。

【讨论】:

  • 这就是我想做的:不要打电话。但是由于某种原因没有实际调用它 - 内存没有被释放:/这就是问题
  • 当时为什么需要释放内存?如果其他东西需要内存,GC 会自动释放它,否则,它会花费时间。
  • GC 不知道其他应用程序,因此它无法知道系统是否需要该内存,或者其他应用程序是否需要
  • @Petr 托管对象将由 GC 自动收集。无论您调用多少次GC.Collect,GC 都不会收集非托管对象。您必须手动释放它们,例如通过实现 IDisposable pattern
【解决方案3】:

今天有很多关于 SO 的 GC 问题!

也许它会在过了这么长时间之后把它清理干净。如果您的程序内存不足并在没有额外调用的情况下死掉,请将其保留,否则可能没有必要。

【讨论】:

  • 好吧,但是这台机器上还有其他程序,他们需要一些内存 :) 即使有足够的内存供程序使用...为什么我要换掉只是因为 GC.Collect 没有决定运行:|我希望它在任何时候都运行,而不是仅在系统运行 OOM 时运行
  • 回答您的问题 - 它的设计方式有很多原因。那些其他程序也需要 CPU 周期,而 GC 也可能正在处理其他一些程序。 GC 正确地推迟以允许其他程序一些 CPU 时间,然后它会颠簸并清理房屋。内存压力是一个困难的野兽...我建议阅读 .NET 垃圾收集器的工作原理,这样您就可以了解引擎盖下的实际情况。从长远来看,了解平台将使您的代码更好。你没有说明你的程序是被送去swap的,其实不应该是这样的。
猜你喜欢
  • 2019-01-23
  • 2022-01-10
  • 2011-11-21
  • 1970-01-01
  • 1970-01-01
  • 2022-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多