首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ClrMD等同于!DumpHeap -live?

ClrMD等同于!DumpHeap -live?
EN

Stack Overflow用户
提问于 2016-02-08 11:35:46
回答 1查看 457关注 0票数 1

https://github.com/Microsoft/dotnetsamples/tree/master/Microsoft.Diagnostics.Runtime/CLRMD是检查活动可执行文件或内存转储的一个很好的工具。若要将所有托管堆对象转储为摘要,可以使用

https://blogs.msdn.microsoft.com/dotnet/2013/05/01/net-crash-dump-and-live-process-inspection/

代码语言:javascript
复制
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。对于回归测试,通常希望在测试之后检查对象是否泄漏。这看起来非常适合上面的代码,但不幸的是,它会产生假阳性,因为可能有一些对象不再有根,但它们仍然在摘要中报告。这可能会导致泄漏报告,尽管没有。

SOS通过添加到!DumpHeap -live交换机缓解了这一问题。什么是只获取活动对象的等效ClrMD代码,因此回归测试只会因为一个真正的原因而失败?

我想我需要使用ClrType.EnumerateRefsOfObjectCarefully递归地遍历堆栈,直到找到根对象(ClrHeap.EnumerateRoots),但是这种方法需要许多临时哈希集来跟踪递归对象图。这是唯一的方法,还是在MS中某个地方已经有了一个正确且性能良好的可用示例(PerfView源代码)。

EN

回答 1

Stack Overflow用户

发布于 2016-02-09 08:16:00

我在https://harshaprojects.wordpress.com/2015/12/29/clr-md-analyzing-live-process/#comment-32上找到了一些很好的博客,其中包含了我想要的东西。为了完整起见,我在这里发布了代码。

ObjectSet类是一个内存效率更高的HashSet,因为HashSet导致了作者机器上的OOM。我使用EnumerateRefsOfObjectCarefully,因为这是PerfView使用的相同方法(我想是出于某种原因)。

这也是我的开源WMemoryProfiler v.2.2的一部分。

https://wmemoryprofiler.codeplex.com/releases/view/619764

它允许您选择带有SOS或ClrMD的Windbg来自动分析进程。

代码语言:javascript
复制
    private static ObjectSet GetLiveObjects(ClrHeap heap)
        {
            ObjectSet considered = new ObjectSet(heap);
            Stack<ulong> eval = new Stack<ulong>();

            foreach (var root in heap.EnumerateRoots())
                eval.Push(root.Object);

            while (eval.Count > 0)
            {
                ulong obj = eval.Pop();
                if (considered.Contains(obj))
                    continue;

                considered.Add(obj);

                var type = heap.GetObjectType(obj);
                if (type == null)  // Only if heap corruption
                    continue;


            foreach (var child in heap.GetObject(obj).EnumerateReferences(carefully:true,considerDependantHandles:true))
            {
                if (!considered.Contains(child.Address))
                    eval.Push(child.Address);
            }
            

            return considered;
        }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35268695

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档