.NET Memory Profiler 5.5 Preview

SciTech Software is pleased to announce the first preview of .NET Memory Profiler 5.5. The major new features of .NET Memory Profiler 5.5 are:

Redesigned real-time presentation

The real-time data presentation has been redesigned. You can now:

  • Change how the real-time data is presented
  • Show recent data in better detail while still getting a good overview of older data
  • Add and remove series
  • Include data from additional sessions
  • Work with multiple real-time layouts

Recent data can be shown in more detail by selecting the "Show recent data" option.

Recent real-time data

Series settings are changed by clicking the legend icon. The legend icon can also be used to remove series from the real-time view. To add a series in an existing category, use the "Add" link, to add series from a new category, use the "Add series" link.

Real-time series settings

Compare real-time data between sessions

It is now possible to add multiple profiler sessions to the real-time graph. This makes it possible to compare the memory behavior against a previously stored session, e.g. to see how well an optimization worked.

The screencast below shows how to add a previously stored session to the real-time data.

Type and Filter details instances graph demo
Click on image to play demo.

Collect performance counter data

Data from the Windows performance counters can also be included in the real-time data. A performance counter can be added using the "Add series" link. For more information see the screencast below:

Type and Filter details instances graph demo
Click on image to play demo.

Significantly improved call stacks collection and presentation

The collection of allocation call stacks in the profiler has been re-implemented. The profiler is now able to collect much more detailed call stacks information, without truncating the call stacks. The screenshots below show the difference between a call stack in version 5.0 and a call stack in version 5.5.

Call stack from .NET Memory Profiler 5.0:
Call stack from .NET Memory Profiler 5.0

Same call stack from .NET Memory Profiler 5.5:
Call stack from .NET Memory Profiler 5.5

Of course it is still possible to use the user interface to reduce the call stack depth and select which methods to include.

By default, the methods tree now presents two values at the same time, both information about allocations performed by the method itself (exclusive) and allocations performed by the methods and all called methods (inclusive). How the values are presented and sorted can be selected using the "Show value" and "Sort by" fields.

Methods tree

To prevent that the call tree becomes very deep, the profiler will merge call stack frames with little or no unique information into a single node. Methods tree tooltip

Improved "inspection-only" attach to process and memory dump import

Inspection only attach (previously known as "Debugging tools attach") and memory dump import have been significantly improved. It no longer has a dependency on "Debugging Tools for Windows" or the "SOS" library. Attaching to a process and importing memory dumps is now faster and more reliable.

New profiler API functionality

The possibility to retrieve the memory usage information from within the profiled process has been added. The method MemProfiler.GetMemoryUsage can be used to investigate how memory has been used since a base snapshot. This includes information about live instances and allocations performed.

The code below shows how the memory usage can be retrieved:

    
public void TestMemoryUsage()
{
    // Collect a snapshot to use as the base when retrieving memory usage.
    var baseSnapshot = MemProfiler.FastSnapshot(true);

    // 
    MethodThatShouldBeTested();

    // Retrieve information about the memory usage (live instances and allocations) since the base snapshot
    var memUsage = MemProfiler.GetMemoryUsage(baseSnapshot);

    var instances = memUsage.GetLiveInstances();
    var allocs = memUsage.GetAllocationsInfo();

    Console.WriteLine("Number of new live instances: {0} (using {1} bytes)",
        instances.NewInstancesCount,
        instances.NewBytesCount );
    Console.WriteLine("Number of performed allocations: {0} ({1} bytes)",
        allocs.AllocatedInstancesCount,
        allocs.AllocatedBytesCount
    );

    // It is also possible to retrieve instances for a specific type
    var bitmapInstances = memUsage.GetLiveInstances( typeof( System.Drawing.Bitmap) );
    Console.WriteLine("Number of new bitmap instances: {}", 
        bitmapInstances.NewInstancesCount );

    // ... or for a set of types
    var typeSetInstances = memUsage.GetLiveInstances(TypeSet.Empty
        .AddNamespace( "System.Windows" )
        .Add( typeof( System.Drawing.Image ), true) );
    Console.WriteLine("Number of new instances in System.Windows namespace and derived from Image: {0}",
        bitmapInstances.NewInstancesCount);
}
    

The GetMemoryUsage method makes it possible to assert the memory usage in a more direct way compared to using an AssertionsDefinition (see example below). However, instances will not be marked as potential memory leaks when asserting memory usage using the MemoryUsage class.

MemoryUsage memUsage = MemProfiler.GetMemoryUsage(baseSnapshot);
TypeSet types = ...;
var instances = memUsage.GetLiveInstances( types );
var allocs = memUsage.GetAllocationsInfo( types );

Assert.LessOrEqual(1, instances.NewInstancesCount);
Assert.LessOrEqual(10, allocs.AllocatedInstancesCount);

Two more assertions have also been added to the AssertionsDefinition class: MaxAllocations and MaxAllocatedBytes (with the corresponding attributes MaxAllocationsAttribute, MaxAllocatedBytesAttribute).

For more information about the new API functionality, see the API reference in the installed documentation.

NOTE! The name of the profiler API library has changed to "MemProfilerAPI.dll" and there are some breaking changes. This includes a few name changes, e.g. FastSnapShot->FastSnapshot and MemSnapShot->MemSnapshot, but most importantly, the FastSnapshot method no longer stores the snapshot as a default base snapshot.

It is recommended that the base snapshot is always specified in API methods like MemProfiler.GetMemoryUsage and MemAssertion.Assert, but it is also possible to supply true as the storeAsBaseSnapshot parameter to MemProfiler.FastSnapshot.

Support for Universal Windows Apps and .NET Core

Universal Windows apps are now included in the list of apps when "Profile Windows app" is selected.

.NET Core profiling is supported by using "Profile application" and then specifying the "dotnet.exe" program and the working directory of the .NET Core application.

Known issues and additional features

This is a preview, so there can be bugs that can cause the profiler to crash and there are still features that are not included in this preview. Below you will find a list of things that are planned to be included in the final release of .NET Memory Profiler 5.5.

  • Performance improvements
  • Performance counter collection improvements
    Currently the .NET PerformanceCounter class is used to collect performance counter data. This doesn't work well when profiling 64-bit processes from within Visual Studio, and the performance of the PerformanceCounter class is bad when multiple performance counters are collected.
  • A dark theme for the profiler UI, matching the dark theme in Visual Studio
  • MemProfilerAPI and NmpCore will be made available as NuGet packages
    This will make it much easier to include memory testing in a build environment, e.g. when doing continuous integration.
  • The profiler API will provide per type information (allocations and instances).
  • Visual Studio 2017 integration

.NET Memory Profiler 5.5 requires .NET Framework 4.5 or later to be installed.

NmpCore 5.5 requires .NET Framework 3.0 or later to be installed.

If you have any comments, error reports, or suggestions related to .NET Memory Profiler 5.5, please send an e-mail to memprofiler@scitech.se

Preview release notes

Below is a summary of additions and changes to .NET Memory Profiler 5.0 Preview:

Version 5.5.13, released December 29, 2016

  • Fix: mscorlib (or rather System.Private.CoreLib) not correctly identified when profiling a .NET Core application.
  • Fix: Identification of static fields was incorrect when profiling a .NET Core application.

Version 5.5.11, released December 20, 2014

  • New: Initial .NET Memory Profiler 5.5 preview release.