【发布时间】:2016-05-18 01:25:52
【问题描述】:
ClrMD 是检查实时可执行文件或内存转储的绝佳工具。要将所有托管堆对象转储为摘要,您可以使用
https://blogs.msdn.microsoft.com/dotnet/2013/05/01/net-crash-dump-and-live-process-inspection/
var stats = from o in heap.EnumerateObjects()
let t = heap.GetObjectType(o)
group o by t into g
let size = g.Sum(o => (uint)g.Key.GetSize(o))
orderby size
select new
{
Name = g.Key.Name,
Size = size,
Count = g.Count()
};
foreach (var item in stats)
Console.WriteLine("{0,12:n0} {1,12:n0} {2}", item.Size, item.Count, item.Name);
效果很好,相当于 Windbg 中带有 SOS 扩展的 !DumpHeap -stat。对于回归测试,通常希望在测试后检查对象是否泄漏。这看起来非常适合上面的代码,但不幸的是它会产生误报,因为可能有些对象不再是 root,但它们仍会在摘要中报告。尽管没有泄漏,但这可能会导致报告的泄漏。
SOS 已通过添加 !DumpHeap -live 开关来缓解此问题。什么是等效的 ClrMD 代码来仅获取活动对象,因此回归测试仅因真实原因而失败?
我想我需要使用 ClrType.EnumerateRefsOfObjectCarefully 递归地遍历堆栈,直到找到一个根对象 (ClrHeap.EnumerateRoots),但这种方法需要许多临时 Hashset跟踪递归对象图。这是唯一的方法,还是在 MS 内部某个地方已经有一个正确且性能良好的可用示例(PerfView 来源?)。
【问题讨论】: