如何调查终结队列和终结幸存者

时间:2013-11-21 12:47:09

标签: c# performance garbage-collection dispose finalizer

我正在调查我们的应用程序中的GC和内存使用,并注意到我们似乎有成千上万的终结幸存者。不幸的是,这个数字并不能真正告诉我我们是否有问题。然而,我们看到了一般性能问题,并且我们确实使用了大量内存,并在GC中花费了大量时间。

理想情况下,我们无法控制的任何内容都应该进入终结队列。这是一个错误,如果它。我可以使用一些方法或工具来检查这个吗?我听到的一个建议是使用终结器进行特殊构建,只要它们被执行就会记录,但这需要付出很多努力,并且只适用于我们拥有类型的对象。有更简单的方法吗?

是否值得调查最终幸存者?如果是这样,怎么样?

2 个答案:

答案 0 :(得分:5)

WinDbgPsscor2Psscor4扩展名一起使用(取决于您的应用程序使用的版本)。不幸的是,.NET 4.5还没有版本。设置调试环境(安装WinDbg并复制到其文件夹Psscor文件)后,创建进程的转储。例如,借助Procdump工具

,您可以轻松完成
procdump -ma <PID>

然后使用File加载转储 - &gt;打开Crush Dump选项。加载适当版本的Psscor:

.load psscor4

然后执行命令从Microsoft服务器下载符号(如果需要),确保您有互联网连接:

!symfix

从现在起你应该可以访问很多非常有趣的命令(查找!help列出它们)。要查看终结队列:

!finalizequeue

在那里你将有一个对象列表,如:

7aa143e0      166       20,584 System.Diagnostics.PerformanceCounter
79b5f6c8      543       21,720 System.Reflection.Emit.DynamicResolver
673893a8      953       22,872 System.Web.HttpResponseUnmanagedBufferElement

这可能对你有很大帮助。但您也可以检查这些对象(!do 7aa143e0),查找引用(!gcroot <address>)等。

答案 1 :(得分:0)

  

是否值得调查最终幸存者?

是的,因为最终确定会对性能和资源产生影响。

  

若然,怎么样?

我建议进行代码检查。

您的类型是否有终结器?如果是,这些是否正确实施?如果直接控制非托管资源,则只需要终结器。如果你有一个终结器,你应该实现IDisposable并使用确定性清理。这样做可以确保永远不会调用终结器。 GC.SuppressFinalize(this)方法中对Dispose的调用可确保实例未完成,因为它已被处理掉。

如果终结器在库代码中,那么这些类型将(或应该)实现IDisposable,您必须确定性地处理这些实例以确保永远不会调用它们的终结器。

相关问题