Skip to content

How to achieve DumpHeap of SOS using ClrMD

Let us see how to use ClrMD to extract the same details as !sos.dumpheap command included in SOS extension available through Windbg. This has been an important command for troubleshooting memory and performance issues in .NET process or process memory dumps.

If you are unaware ClrMD 2.0 RTM is almost ready.

First step is to create a Console App, then add reference Microsoft.Diagnostics.Runtime (NuGet package) and copy paste the below code snippet. Keep in mind the below code expects the first parameter of the command line to be the path to memory dump you want to open.

First foreach loop takes care of all the Clr Runtimes in case there are more than one.

            using DataTarget dataTarget = DataTarget.LoadDump(args[0]);

            foreach (ClrInfo clr in dataTarget.ClrVersions)
            {
                using ClrRuntime runtime = clr.CreateRuntime();
                ClrHeap heap = runtime.Heap;

                // !sos.dumpheap
                Console.WriteLine("{0,16} {1,16} {2,8} {3}", "Object", "MethodTable", "Size", "Type");
                foreach (ClrObject obj in heap.EnumerateObjects())
                    Console.WriteLine(
                        $"{obj.Address:x16} {obj.Type.MethodTable:x16} {obj.Size,8:D} {obj.Type.Name}");

                // !sos.dumpheap -stat
                Console.WriteLine("\nStatistics:");
                var dumpheapstats = from obj in heap.EnumerateObjects()
                                    group obj by obj.Type into g
                                    let size = g.Sum(p => (long)p.Size)
                                    orderby size
                                    select new
                                    {
                                        g.Key.MethodTable,
                                        Count = g.Count(),
                                        Size = size,
                                        g.Key.Name
                                    };

                Console.WriteLine("{0,16} {1,12} {2,12}\t{3}", "MethodTable", "Count", "Size", "Type");
                foreach (var item in dumpheapstats)
                    Console.WriteLine(
                        $"{item.MethodTable:x16} {item.Count,12:D} {item.Size,12:D}\t{item.Name}");

                Console.WriteLine($"Total {dumpheapstats.Sum(x => x.Count):0} objects");

            }

How the output of the above code looks like

          Object MethodTable          Size Type
000001d1445a1000 000001d13e08bf90       24 Free
000001d1445a1018 000001d13e08bf90       24 Free
000001d1445a1030 000001d13e08bf90       24 Free
000001d1445a1048 00007ffb05430638      152 System.RuntimeType + RuntimeTypeCache
000001d1445a10e0 00007ffb0552eed0       56 System.RuntimeType + RuntimeTypeCache + MemberInfoCache < System.Reflection.RuntimeConstructorInfo >
000001d1445a1118 00007ffb0552ec60      104 System.Reflection.RuntimeConstructorInfo
000001d1445a1180 00007ffb0552f078       32 System.Reflection.RuntimeConstructorInfo[]
...
000001d5745a3030 000001d13e08bf90       32 Free
000001d5745a3050 00007ffb05316610     8184 System.Object[]

Statistics:
     MethodTable        Count         Size  Type
00007ffb0577d1f8            1           24  Microsoft.Extensions.Logging.Configuration.LoggerProviderConfigurationFactory
00007ffb05a26c00            1           24  Microsoft.Extensions.Options.OptionsCache < Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions >
00007ffb05a49c78            1           24  Microsoft.Extensions.Options.OptionsMonitor < Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions >
00007ffb05a49dc0            1           24  Microsoft.Extensions.Primitives.ChangeToken + ChangeTokenRegistration < System.String >
00007ffb05a49e70            1           24  Microsoft.Extensions.Primitives.ChangeToken + ChangeTokenRegistration < System.String >
00007ffb05a4be00            1           24  Microsoft.Extensions.Logging.NullExternalScopeProvider
00007ffb05a4cf90            1           24  Microsoft.Extensions.Configuration.ConfigurationBinder +<> c
00007ffb05a4cd80            1           24  Microsoft.Extensions.Configuration.BinderOptions...
00007ffb053ef090         2010       111364  System.Int32[]
00007ffb053d2aa8         2224       126352  System.SByte[]
00007ffb05413058         1297       260138  System.Char[]
00007ffb05316610         2160       331512  System.Object[]
00007ffb053d2360          841       558172  System.Byte[]
00007ffb053d1e18         8366       718666  System.String
Total 82567 objects

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: