垃圾收集干扰对象创建?
Garbage collection interfering with object creation?
我正在开发一个 WPF 应用程序,其中有一个 DevExpress DocumentGroup,它包含不同的面板,其中包含页面。我使用的一个名为 'overview' 的页面有一张非常大的图片 (10.000 x 7.000) 作为背景。当我单击一个按钮创建一个包含概览的新面板时,我可以在任务管理器中看到越来越多的内存被使用。
关闭概览面板后,内存使用量下降了一点,但从未像打开页面前那样低。如果我多次打开和关闭页面,内存使用量会达到 的临界点,程序会冻结并且永远不会加载概览。查看任务管理器显示,内存使用率急剧下降。
垃圾收集器不应该在我关闭时立即删除我的概览实例,从而删除对我的概览的所有引用吗?当我正在创建新的概览页面并因此中断创建过程时,垃圾收集器是否决定 'collect'?
通读MSDN about the fundamentals of GC,显示如下:
当满足以下条件之一时,将进行垃圾收集:
- 系统物理内存不足。
- 使用的内存
托管堆上分配的对象超过可接受的
临界点。这个阈值随着过程不断调整
运行。
- 调用了GC.Collect方法。在几乎所有情况下,你都会
不必调用此方法,因为垃圾收集器运行
不断地。此方法主要用于特殊情况和
测试。
因此,它并没有像您预期的那样在关闭概览后立即清除内存。 GC 会在需要时清除内存。
让你着迷的是 Fundamentals of Garbage Collection
中的这一部分
Ordinarily, the large object heap is not compacted, because copying
large objects imposes a performance penalty. However, starting with
the .NET Framework 4.5.1, you can use the
GCSettings.LargeObjectHeapCompactionMode
property to compact the large
object heap on demand.
所以你的镜像马上就被提升到Gen 2对象池,而且还被添加到大对象堆中。当收集器在 workstation 模式下 运行(Windows 7、8 等机器的默认设置,它是 server Windows 服务器版本)那么这些对象将永远不会被收集或压缩。
我很确定强制 GC.Collect()
对你绝对没有任何作用,因为收集器(在工作站模式下)将忽略大对象堆。
我已经看到在 Windows7 机器上测试一个繁重的消息处理服务,在收到几条 100k 消息后,应用程序将因内存不足异常而终止。 将收集器切换到服务器模式解决了我的问题。
来自 MSDN 条目 <gcServer>
Element:- 将其添加到项目的 app.config 文件
<configuration>
<runtime>
<gcServer enabled="true"/>
</runtime>
</configuration>
更新
好的,删除终结器,这不是它的目的,它对垃圾收集没有任何影响或产生负面影响。
调用 CG.Collect() 并不能保证您会看到内存使用率下降,Collector 是一个复杂的野兽,预测它在任何给定情况下会做什么是一件傻事。
在这个阶段您几乎只能做两件事,而且您可能需要同时做这两件事。
确保没有对大对象的引用,包括
侦听该对象引发的事件的事件处理程序。
运行 它通过内存分析器,就像上面评论中提到的 ANTS。
我正在开发一个 WPF 应用程序,其中有一个 DevExpress DocumentGroup,它包含不同的面板,其中包含页面。我使用的一个名为 'overview' 的页面有一张非常大的图片 (10.000 x 7.000) 作为背景。当我单击一个按钮创建一个包含概览的新面板时,我可以在任务管理器中看到越来越多的内存被使用。
关闭概览面板后,内存使用量下降了一点,但从未像打开页面前那样低。如果我多次打开和关闭页面,内存使用量会达到 的临界点,程序会冻结并且永远不会加载概览。查看任务管理器显示,内存使用率急剧下降。
垃圾收集器不应该在我关闭时立即删除我的概览实例,从而删除对我的概览的所有引用吗?当我正在创建新的概览页面并因此中断创建过程时,垃圾收集器是否决定 'collect'?
通读MSDN about the fundamentals of GC,显示如下:
当满足以下条件之一时,将进行垃圾收集:
- 系统物理内存不足。
- 使用的内存 托管堆上分配的对象超过可接受的 临界点。这个阈值随着过程不断调整 运行。
- 调用了GC.Collect方法。在几乎所有情况下,你都会 不必调用此方法,因为垃圾收集器运行 不断地。此方法主要用于特殊情况和 测试。
因此,它并没有像您预期的那样在关闭概览后立即清除内存。 GC 会在需要时清除内存。
让你着迷的是 Fundamentals of Garbage Collection
中的这一部分Ordinarily, the large object heap is not compacted, because copying large objects imposes a performance penalty. However, starting with the .NET Framework 4.5.1, you can use the
GCSettings.LargeObjectHeapCompactionMode
property to compact the large object heap on demand.
所以你的镜像马上就被提升到Gen 2对象池,而且还被添加到大对象堆中。当收集器在 workstation 模式下 运行(Windows 7、8 等机器的默认设置,它是 server Windows 服务器版本)那么这些对象将永远不会被收集或压缩。
我很确定强制 GC.Collect()
对你绝对没有任何作用,因为收集器(在工作站模式下)将忽略大对象堆。
我已经看到在 Windows7 机器上测试一个繁重的消息处理服务,在收到几条 100k 消息后,应用程序将因内存不足异常而终止。 将收集器切换到服务器模式解决了我的问题。
来自 MSDN 条目 <gcServer>
Element:- 将其添加到项目的 app.config 文件
<configuration>
<runtime>
<gcServer enabled="true"/>
</runtime>
</configuration>
更新
好的,删除终结器,这不是它的目的,它对垃圾收集没有任何影响或产生负面影响。
调用 CG.Collect() 并不能保证您会看到内存使用率下降,Collector 是一个复杂的野兽,预测它在任何给定情况下会做什么是一件傻事。
在这个阶段您几乎只能做两件事,而且您可能需要同时做这两件事。
确保没有对大对象的引用,包括 侦听该对象引发的事件的事件处理程序。
运行 它通过内存分析器,就像上面评论中提到的 ANTS。