forked from JeffCyr/ClrMD.Extensions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ClrMD_Dump.linq
68 lines (63 loc) · 2.85 KB
/
ClrMD_Dump.linq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<Query Kind="Program">
<Reference>C:\Code\GitHub\ClrMD.Extensions\ClrMD.Extensions\bin\Release\ClrMD.Extensions.dll</Reference>
<Reference>C:\Code\GitHub\ClrMD.Extensions\ClrMD.Extensions\bin\Release\Microsoft.Diagnostics.Runtime.dll</Reference>
<Namespace>ClrMD.Extensions</Namespace>
<Namespace>ClrMD.Extensions.LINQPad</Namespace>
<Namespace>Microsoft.Diagnostics.Runtime</Namespace>
</Query>
void Main()
{
// ClrMDSession is a singleton and is only created on the first query execution.
// Calling 'LoadCrashDump' again will return the already initialized ClrMDSession (if it's the same dump path).
ClrMDSession session = ClrMDSession.LoadCrashDump(@"C:\Dumps\YourDumpFile.dmp");
session.DumpThreads();
session.DumpHeapStatistics();
}
public static class LocalExtensions
{
public static void DumpThreads(this ClrMDSession session, bool includeThreadName = true)
{
// Get the thread names from the 'Thread' instances of the heap.
var threadsInfo = from o in session.EnumerateDynamicObjects("System.Threading.Thread")
select new
{
ManagedThreadId = (int)o.Dynamic.m_ManagedThreadId,
Name = (string)o.Dynamic.m_Name
};
( // Join the ClrThreads with their respective thread names
from t in session.Runtime.Threads
join info in threadsInfo on t.ManagedThreadId equals info.ManagedThreadId into infoGroup
let name = infoGroup.Select(item => item.Name).FirstOrDefault() ?? ""
select new
{
ManagedThreadId = t.ManagedThreadId,
Name = name,
StackTrace = t.GetStackTrace(),
Exception = t.CurrentException,
t.BlockingObjects
}
).Dump("Threads", depth:0);
}
public static void DumpHeapStatistics(this ClrMDSession session)
{
( // Start with all objects
from o in session.AllObjects
// Group by object type.
group o by o.Type into typeGroup
// Get the instance count of this type.
let count = typeGroup.Count()
// Get the memory usage of all instances of this type
let totalSize = typeGroup.Sum(item => (double)item.Size)
// Orderby to get objects with most instance count first
orderby count descending
select new
{
Type = typeGroup.Key.Name,
Count = count,
TotalSize = (totalSize / 1024 / 1024).ToString("0.## MB"),
// Get the first 100 instances of the type.
First100Objects = typeGroup.Take(100),
}
).Take(100).Dump("Heap statistics", depth:0);
}
}