【问题标题】:C# garbage collection in intense memory using application使用应用程序在密集内存中收集 C# 垃圾
【发布时间】:2015-04-05 04:18:17
【问题描述】:

我有一个图像编辑器程序。许多编辑器操作需要在内存中复制图像。图片可能非常大,一秒钟内可以进行多次编辑,因此内存使用量很大。

我准确地Dispose() 每个未使用的图像。但是当我分析我的应用程序时,我注意到在激烈的编辑操作期间内存消耗增长(我什至得到了OutOfMemoryException 几次)。在几秒钟不活动后,它会恢复到正常值,因此没有内存泄漏。所以我认为原因是垃圾收集发生得太少了。我在每次编辑操作后都输入了GC.Collect(),它有帮助,现在内存消耗稳定了。

但是我想知道这是否是一个好方法?根据 MSDN:

可以通过调用 Collect 来强制进行垃圾回收,但大多数情况下应该避免这样做,因为它可能会产生性能问题。

我不需要收集应用程序中的所有内容,只需销毁几个对象(Bitmap's)。我可以以某种方式告诉 GC 只收集这些对象吗?或者也许有另一种方法来优化这个过程?

【问题讨论】:

  • 你不能重复使用位图,这样你就不必一直创建新的了吗?
  • Bitmap 类是单一的 .NET 类,它提醒您调用 Dispose() 很重要。错过一个,您的程序因 OOM 导致的可能性显着增加。该类完全太小(24 字节),无法自行及时触发 GC。内存分析器往往没有帮助,它只会向您显示您使用了位图(您已经知道它确实如此)和一大块没有详细信息的非托管内存。需要进行彻底的代码审查才能找到错误。在这里无法获得帮助。

标签: c# garbage-collection


【解决方案1】:

搞乱垃圾收集器总是一个棘手的问题,几乎在所有情况下都应该避免。

从性能的角度来看,最好的办法是通过重用对象和缓冲区来尽可能避免涉及 GC。如果可能的话,这通常会以增加复杂性为代价,因此需要权衡取舍。

否则,推荐的方法是设计您的应用程序以使 GC 更容易:

  • 确保在不再需要对象时尽早取消对它们的引用,以便快速收集它们。幸运的是,作为第 0 代或第 1 代。
  • 在取消引用之前对实现它的对象调用 Dispose,以避免 GC 必须保留对象以调用终结器。

由于我怀疑您已经这样做了,剩下的就是彻底的性能测试。如果您不频繁地释放一些大型对象,因此 GC 很难预测间隔,并且如果您调用 GC.Collect(),您可以证明您的应用程序性能更好(无论这意味着什么),然后继续。

据我所知,您无法控制 GC 收集的内容。你甚至不能确定它会在调用 GC.Collect() 时收集你刚刚发布的大对象,如果它们已经进入 GC 第一代或第二代。这就是为什么你必须测试和测量你的特定用例的原因。

一个问题是,对于您的应用程序来说,GC 赶上几秒钟而内存使用量下降是否真的很重要?

【讨论】:

  • 是的,正如我所提到的,即使在我的开发机器上,它有时也会导致OutOfMemoryException,并且客户端机器的可用内存量可能较低。无论如何,谢谢您的建议和解释,我会标记您的答案,因为它是最完整的。
  • 感谢@Aleksey,很抱歉错过了您提到OutOfMemoryException
【解决方案2】:

如果您可以在任何实现 IDispose 的东西上使用“使用”,请执行此操作。另一种选择是您的程序组织得很糟糕,无法管理流程。

您应该始终让框架在可能的情况下进行处理。

要问自己的问题:

  • 我是在创建新的对象实例而不是重用现有对象吗?

  • 我可以在使用后将任何对象设置为空吗?还是完全丢弃?

  • 哪条线路导致泄漏?我建议运行该程序并 将任务管理器切换到一边-然后逐步通过-您会看到坡道 在您逐步完成时实时使用。

  • 我可以批处理吗?如果我要管理 100 张图片,我可以分成 10 组吗 10 个?

【讨论】:

    【解决方案3】:

    您可以在此过程中使用“使用”范围。

    using(var bmp = new Bitmap(image))
    {
    /// your code
    }
    

    【讨论】:

    • using 作用域只是保证Dispose 在块之后被调用的一种便捷方式。我实际上正在使用它,但它并没有解决问题。 msdn.microsoft.com/en-us//library/yh598w02.aspx
    • Thios 不会触发垃圾收集器,它只是将对象标记为“准备收集”
    猜你喜欢
    • 2015-06-15
    • 1970-01-01
    • 2021-04-30
    • 2019-02-10
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 2017-03-15
    • 2011-03-10
    相关资源
    最近更新 更多