【问题标题】:How to capture a process memory dump of a .NET process when .NET is not in the middle of a garbage collection (GC)当 .NET 不在垃圾收集 (GC) 中间时,如何捕获 .NET 进程的进程内存转储
【发布时间】:2016-02-14 02:09:01
【问题描述】:

在捕获转储文件并对其进行分析时(例如在WinDbg中),我经常收到警告说数据可能不准确,或者命令可能无法访问,因为转储文件时进程正在GC中间被收集了。

在做内存分析时,我们经常这样做,因为进程上的内存很高,内存压力很大,我猜这迫使.NET经常进行GC。

如何避免在 GC 期间进行转储?有没有办法知道何时可以安全地捕获转储文件?

【问题讨论】:

  • 您可能想使用 PerfView,它的设计考虑到了这个问题。帮助 |用户指南有一个名为“GC Heap collection: To Freeze or not to Freeze?”的部分。其中讨论了这一点。下载链接为:microsoft.com/en-us/download/details.aspx?id=28567
  • 如果您需要帮助,请通过实施/测试我的答案给我留言。
  • @Mark:在你的应用中,有没有后台进程?我的意思是,如果用户不使用它,它还能在幕后处理一些事情吗?
  • @Mark:也许我们可以使用ProcDump-pl 开关。
  • @Thomas 我已经用ProcDump 测试了你的方法,它对我来说效果很好。我也更新了答案,希望对您有所帮助...

标签: c# .net memory-leaks garbage-collection dump


【解决方案1】:

我不是这方面的专家,但我注意到您可以使用 .NET 运行时的性能计数器来监控一些有趣的事情 - 其中之一是垃圾收集器在运行期间分配的字节数这是最后一个系列。 Performance Counters in the .NET Framework中对Allocated Bytes/second的描述:

显示每秒在垃圾收集堆上分配的字节数。此计数器在每次垃圾回收结束时更新,而不是在每次分配时更新。该计数器不是一段时间内的平均值;它显示最后两个样本中观察到的值之间的差异除以样本间隔的持续时间。

根据我的测试,如果您将性能监视器的更新间隔设置为 1 秒,并仔细查看 Allocated Bytes/second 的指示器,在收集完成后,它似乎显示了 0 的值。所以我假设,无论收集是否正在进行,您都可以从这个值中得出。

我通过在 VS 2015 中构建一个小应用程序来检查它,它能够显示是否正在进行垃圾收集。如果是这种情况,则指标的值不为0。

更新(感谢 Thomas)

可以使用ProcDump 监控性能计数器并以自动方式创建转储。 正确的做法是:procdump ProcessName -s 1 -ma -pl "\.NET CLR Memory(ProcessName)\Allocated Bytes/second" 1000,如果值低于 1000,则会触发转储。

这应该可以工作,因为如果没有进行垃圾收集,则该值仅为零。

如果您不是在英文版操作系统上运行,则必须找出性能计数器的正确语言特定名称(可以通过查看上面提供的 MSDN 链接并切换到其他语言来完成那里)。例如。德国名字会 是"\.NET CLR-Speicher(ProcessName)\Zugeordnete Bytes/Sek."

【讨论】:

  • 感谢您的回答。你能让答案更实际一点吗?这是否意味着我们可以将ProcDump-pl 开关一起使用?如果有,是哪一个?你能提供示例代码来证明这个理论吗?
  • @Thomas 感谢您的赏金 ;-)
  • 不客气。感谢您跟进并积极努力。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-25
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
  • 2011-07-16
相关资源
最近更新 更多