One of these days Microsoft will release a version of .NET where we don’t have to worry about memory. HA! Who am I kidding!? All you worry about in a .NET application is the memory. Naturally, I personally never want Microsoft to come out with the memory worry free .NET because I’d be out of a job.
With SOS for .NET 4.5, there’s not a whole lot different but there are two differences that will be valuable. The first are two new options to the most important SOS command, !dumpheap. One of the big problems in dealing with those minidumps from production systems is trying to figure out which objects are rooted, meaning have references and cannot be garbage collected, and those objects that are ready for garbage collection. That problem is easy to solve with the new –live and –dead options. Get in the habit now of always passing –live when you first do that initial !dumpheap –stat because that’s all you care about!
Here’s an example output comparing the differences reported by –stat alone, -live, and –dead.
What I haven’t been able to figure out is that the total objects between live and dead objects never add up to the total shown when looking at all objects with just the –stat switch. Doing some experimentation the output for –live looks valid so I’m going to trust it for now. I’ll talk to the CLR team and see if this is a bug or there’s a real reason for the discrepancy. It’s not like an object could be alive and dead at the same time… unless it was a ZOMBIE! No matter, the –live switch looks fantastic and will save everyone a huge amount of time.
Since everyone is not moving over to .NET 4.5 immediately, I tried like crazy to see if I could get the .NET 4.5 SOS version working with minidumps from .NET 4.0. Nothing I tried and no amount of playing around with .cordll to load the MSCORDACWKS.DLL from .NET 4.0 would work. Do yourself a favor now and make sure you save off SOS.DLL, CLR.DLL, and MSCORDACWKS.DLL from a pure .NET 4.0 installation because .NET 4.5 is on top of .NET 4.0. I’ll keep working on trying more tricks to get !dumpheap –live working with .NET 4.0.
The second SOS command to get some development love is !clrstack. There’s a new experimental option –i, which uses the CLR Debugging API’s ICorDebug interface to walk stacks and show variable names very much like the !mk command in SOSEX. It’s very important that to use !clrstack –i you have the _NT_SYMBOL_PATH environment variable set to include the public Microsoft symbol server. SOS needs access to MSCORDBI.DLL through the symbol server download even though that DLL is in the framework directory along with SOS.DLL.
Running !clrstack –a –i will show output like the following snippet. What you can’t see is that the output is that it’s fully DML ready.
You are probably wondering where the actual values are. Just like !mk, when it’s JIT optimized code we can’t get the values. That doesn’t make !clrstack –i any less valuable because at least it shows you the types so you can use !dso, or !mdso from SOSEX, to look them up. To turn off the JIT optimizations, you’d have to either run the whole application with the COMPLUS_ZAPDISABLE environment variable or turn it off for an individual assembly with the INI file trick.
The new –live and –dead options for !dumpheap and the –i for !clrstack are the most important additions, but there are a few more worth mentioning. The !bpmd command now supports setting breakpoints on a source and line if you have the PDB file for the assembly loaded. If you’re doing heavy interop, the new !dumprcw, which dumps a Runtime Callable Wrapper, and !dumpccw, which dumps a COM Callable Wrapper, look helpful. The new SOS for .NET 4.5 is nice, but wait until you see the new version of SOSEX!
Microsoft Azure and Amazon Web Services (AWS) are two of the most popular cloud platforms.…
Cloud management is difficult to do manually, especially if you work with multiple cloud…
Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…
https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…
FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…
Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…
View Comments
Thanks for the update on SOS!
> "HA! Who am I kidding!? All you worry about in a .NET application is the memory."
Absolutely. That, and managing system resources. And performance. And threading. And... :)
Thanks for the info (and for the SOSEX shout-out).
This is good news. Unfortunately I have never seen the COMPLUS_ZAPDISABLE or ini file trick to work with Windbg. !ClrStack -p does never give me all variables no matter what I try. When I start NUnit e.g. under the debugger I can inspect all stack frames and locals but Windbg does not do it. I have hoped that I can attach Windbg to a running process and inspect all locals and method arguments but that did never work (.NET 4.5 Beta and 3.5).
The !ClrStack -i option sounds very promising if it would work (Windows 7 32 Bit .NET 3.5 SP1, VS2012 RC). Are there any other pitfalls I should be aware off?
Thanks John for this news! It will indeed save typing one extra command - the ObjSize -aggregate -stat command already tells us "how many" objects are rooted. The real value of -live will be if it can tell "which" objects.
Great post indeed. I really like that you are providing information on .NET for freshers , Being enrolled at http://www.wiziq.com/course/57-fresher-training-projects i found your information very helpful indeed. Thanks for it.