WMemoryProfiler is Released
- by Alois Kraus
What is it? WMemoryProfiler is a managed profiling Api to aid integration testing. This free library can get managed heap statistics and memory usage for your own process (remember testing) and other processes as well. The best thing is that it does work from .NET 2.0 up to .NET 4.5 in x86 and x64. To make it more interesting it can attach to any running .NET process. The reason why I do mention this is that commercial profilers do support this functionality only for their professional editions. An normally only since .NET 4.0 since the profiling API only since then does support attaching to a running process. This thing does differ in many aspects from “normal” profilers because while profiling yourself you can get all objects from all managed heaps back as an object array. If you ever wanted to change the state of an object which does only exist a method local in another thread you can get your hands on it now … Enough theory. Show me some code /// <summary>
/// Show feature to not only get statisics out of a process but also the newly allocated
/// instances since the last call to MarkCurrentObjects.
/// GetNewObjects does return the newly allocated objects as object array
/// </summary>
static void InstanceTracking()
{
using (var dumper = new MemoryDumper()) // if you have problems use to see the debugger windows true,true))
{
dumper.MarkCurrentObjects();
Allocate();
ILookup<Type, object> newObjects = dumper.GetNewObjects()
.ToLookup( x => x.GetType() );
Console.WriteLine("New Strings:");
foreach (var newStr in newObjects[typeof(string)] )
{
Console.WriteLine("Str: {0}", newStr);
}
}
}
…
New Strings:
Str: qqd
Str: String data:
Str: String data: 0
Str: String data: 1
…
This is really hot stuff. Not only you can get heap statistics but you can directly examine the new objects and make queries upon them. When I do find more time I can reconstruct the object root graph from it from my own process. It this cool or what? You can also peek into the Finalization Queue to check if you did accidentally forget to dispose a whole bunch of objects …
/// <summary>
/// .NET 4.0 or above only. Get all finalizable objects which are ready for finalization and have no other object roots anymore.
/// </summary>
static void NotYetFinalizedObjects()
{
using (var dumper = new MemoryDumper())
{
object[] finalizable = dumper.GetObjectsReadyForFinalization();
Console.WriteLine("Currently {0} objects of types {1} are ready for finalization. Consider disposing them before.",
finalizable.Length,
String.Join(",", finalizable.ToLookup( x=> x.GetType() )
.Select( x=> x.Key.Name))
);
}
}
How does it work?
The W of WMemoryProfiler is a good hint. It does employ Windbg and SOS dll to do the heavy lifting and concentrates on an easy to use Api which does hide completely Windbg. If you do not want to see Windbg you will never see it. In my experience the most complex thing is actually to download Windbg from the Windows 8 Stanalone SDK. This is described in the Readme and the exception you are greeted with if it is missing in much greater detail. So I will not go into this here.
What Next?
Depending on the feedback I do get I can imagine some features which might be useful as well
Calculate first order GC Roots from the actual object graph
Identify global statics in Types in object graph
Support read out of finalization queue of .NET 2.0 as well.
Support Memory Dump analysis (again a feature only supported by commercial profilers in their professional editions if it is supported at all)
Deserialize objects from a memory dump into a live process back (this would need some more investigation but it is doable)
The last item needs some explanation. Why on earth would you want to do that? The basic idea is to store in your live process some logging/tracing data which can become quite big but since it is never written to it is very fast to generate. When your process crashes with a memory dump you could transfer this data structure back into a live viewer which can then nicely display your program state at the point it did crash. This is an advanced trouble shooting technique I have not seen anywhere yet but it could be quite useful. You can have here a look at the current feature list of WMemoryProfiler with some examples.
How To Get Started?
First I would download the released source package (it is tiny). And compile the complete project. Then you can compile the Example project (it has this name) and uncomment in the main method the scenario you want to check out. If you are greeted with an exception it is time to install the Windows 8 Standalone SDK which is described in great detail in the exception text.
Thats it for the first round. I have seen something more limited in the Java world some years ago (now I cannot find the link anymore) but anyway. Now we have something much better.