.net - What is the ClrMD equivalent to !DumpHeap -live? -


clrmd great tool inspect live executable or memory dump. dump managed heap objects summary can use

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

var stats = o in heap.enumerateobjects()             let t = heap.getobjecttype(o)             group o t 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); 

that works great , equivalent of !dumpheap -stat in windbg sos extension. regression testing desireable check after test if objects leaked. looks perfect fit code above unfortunately produces false positives because there may objects no longer rooted still reported in summary. can lead reported leaks although there none.

sos has mitigated issue addine !dumpheap -live switch. equivalent clrmd code live objects regression tests fail real reason?

i guess need use clrtype.enumeraterefsofobjectcarefully walk stack recursively until find root object (clrheap.enumerateroots) approach needs many temporary hashsets track recursive object graph. way or there somewhere inside ms correct , performing sample available (perfview source?).

i have found nice blog @ https://harshaprojects.wordpress.com/2015/12/29/clr-md-analyzing-live-process/#comment-32 contains after. completeness post code here.

the objectset class more memory efficient hashset because hashset caused ooms on authors machine. use enumeraterefsofobjectcarefully because same method perfview uses (for reason guess).

that part of open source wmemoryprofiler v.2.2

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

which lets choose windbg sos or clrmd automate analysis of processes.

    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)  // if heap corruption                     continue;                  type.enumeraterefsofobjectcarefully(obj, delegate(ulong child, int offset)                 {                     if (child != 0 && !considered.contains(child))                         eval.push(child);                 });             }              return considered;         }      class dumpdiffentry     {         public clrtype type;         public int count;         public long size;     }      class entry     {         public string name;         public int count;         public ulong size;     }     class objectset     {         struct entry         {             public ulong high;             public ulong low;             public int index;         }          public objectset(clrheap heap)         {             m_shift = intptr.size == 4 ? 3 : 4;             int count = heap.segments.count;              m_data = new bitarray[count];             m_entries = new entry[count]; #if debug             ulong last = 0; #endif              (int = 0; < count; ++i)             {                 var seg = heap.segments[i]; #if debug                 debug.assert(last < seg.start);                 last = seg.start; #endif                  m_data[i] = new bitarray(getbitoffset(seg.length));                 m_entries[i].low = seg.start;                 m_entries[i].high = seg.end;                 m_entries[i].index = i;             }         }          public void add(ulong value)         {             if (value == 0)             {                 m_zero = true;                 return;             }              int index = getindex(value);             if (index == -1)                 return;              int offset = getbitoffset(value - m_entries[index].low);              m_data[index].set(offset, true);         }          public bool contains(ulong value)         {             if (value == 0)                 return m_zero;               int index = getindex(value);             if (index == -1)                 return false;              int offset = getbitoffset(value - m_entries[index].low);              return m_data[index][offset];         }          public int count         {                         {                 // todo, nasty.                 int count = 0;                 foreach (var set in m_data)                     foreach (bool bit in set)                         if (bit) count++;                  return count;             }         }          private int getbitoffset(ulong offset)         {             debug.assert(offset < int.maxvalue);             return getbitoffset((int)offset);         }          private int getbitoffset(int offset)         {             return offset >> m_shift;         }          private int getindex(ulong value)         {             int low = 0;             int high = m_entries.length - 1;              while (low <= high)             {                 int mid = (low + high) >> 1;                 if (value < m_entries[mid].low)                     high = mid - 1;                 else if (value > m_entries[mid].high)                     low = mid + 1;                 else                     return mid;             }              // outside of heap.             return -1;         }          bitarray[] m_data;         entry[] m_entries;         int m_shift;         bool m_zero;     } 

Comments

Popular posts from this blog

javascript - jQuery: Add class depending on URL in the best way -

caching - How to check if a url path exists in the service worker cache -

Redirect to a HTTPS version using .htaccess -