Anda di halaman 1dari 229

1.

.NET Memory Profiler

by SciTech Software AB
This manual was produced using ComponentOne Doc-To-Help.
Contents
User Manual 1
Introduction...................................................................................................... 1
How to.............................................................................................................. 2
Profile a .NET Process ........................................................................ 2
Start Profiling an Application ............................................................ 4
Start Profiling ASP.NET ..................................................................... 4
Start Profiling a Windows Store App .................................................5
Start Profiling a .NET Core App ........................................................ 6
Start Profiling an ASP.NET Core App using IIS Express and .NET
Core.......................................................................................................7
Start Profiling a Silverlight Application ............................................ 8
Start Profiling a WPF Browser Application ...................................... 9
Start Profiling a Windows Service ..................................................... 9
Select Processes to Profile .................................................................. 9
Profile a Remote Process...................................................................10
Use the Memory Analyser ................................................................. 11
Find Memory Leaks ........................................................................... 12
View Real-time Heap Utilization ...................................................... 13
Work with a Previously Saved Session ............................................. 15
Find out Information about the Native Memory of a .NET
Process................................................................................................ 15
Perform Unit Testing together with the Profiler ............................. 16
Increase the Performance of the Profiler ......................................... 19
Attach to a Process............................................................................ 20
Import Memory Dump Files ............................................................. 21
Create or Load a Profiler Project ..................................................... 22
Start Profiling using a Profiler Project ............................................ 23
Compare Snapshots using the Profiler Projects Explorer.............. 24
Setup Native Stack Walks ................................................................ 24
Starting .NET Memory Profiler .................................................................... 25
Interactive Mode............................................................................... 25
Non-Interactive Mode ...................................................................... 25
Command Line Arguments .............................................................. 26
Available Command Line Arguments ..............................................27
Response Files .................................................................................. 30
Exit Codes........................................................................................... 31
Automatic Memory Analysis ......................................................................... 31
Issue Presentation ............................................................................ 33
Ignoring Analysis Issues .................................................................. 35
Modifying Ignored Issues..................................................................37
Analysis Issues List........................................................................... 39

.NET Memory Profiler Contents iii


Duplicate Instances Detection ......................................................... 47
Disposable Types Classification and Undisposed Instances .......... 51
Ignoring Framework Issues ............................................................. 52
Held and Reachable Instances ..................................................................... 53
Held by a Set of Instances ................................................................ 56
Instance Graph ...............................................................................................57
Graph Presentation ...........................................................................57
Root Paths in the Graph ................................................................... 60
Combined Instances Graph.............................................................. 63
Working with the Graph................................................................... 64
Graph Synchronization .................................................................... 67
Instance Graph Commands ............................................................. 68
Guided Profiling and the Tasks Window ..................................................... 70
Tasks Window ....................................................................................72
Instance and Allocation Filters .....................................................................72
Snapshot Filters .................................................................................75
Predefined Filters ..............................................................................75
Saving and Managing Filters ........................................................... 76
Peak Snapshots.............................................................................................. 78
Profiler Projects............................................................................................. 79
Comparing Project Snapshots ......................................................... 80
Adding and Removing Sessions....................................................... 80
Remote Profiling ........................................................................................... 80
Remote Profiling Security ................................................................ 82
The .NET Memory Profiler Window ............................................................ 83
Snapshot and Process Dropdown Lists ........................................... 84
Runtimes and AppDomains Selector .............................................. 85
Commands ........................................................................................ 86
Status Bar ........................................................................................... 91
Field Sets ........................................................................................... 92
Info Panel .......................................................................................... 93
Context Menus .................................................................................. 93
Copying Data to the Clipboard ........................................................ 93
Fast Column Filter ............................................................................ 94
Navigating Types, Resources, Filters, and Instances ..................... 94
Column Layout and Customization ................................................. 95
Preferences .................................................................................................... 96
Symbol File Locations ...................................................................... 98
Session Settings............................................................................................. 98
Profiling Level Settings Page ......................................................... 100
Instance Tracking Settings Page..................................................... 101
General Settings Page ..................................................................... 102
Launch Settings Page ..................................................................... 104
Snapshots Settings Page..................................................................105
Session File Settings Page ...............................................................107
Real-time Settings Page ................................................................. 108
Memory Leak Settings Page ........................................................... 109
Instance Data Collection Settings Page...........................................111
Call Stacks Settings Page ..................................................................111
Overview Page .............................................................................................. 113

iv Contents .NET Memory Profiler


Type/Resource/Filter Details Page............................................................. 119
Instances ......................................................................................... 120
Allocation Stacks..............................................................................123
Shortest root paths ..........................................................................123
Instances graph................................................................................ 127
Instances, Allocation Stack, Root Path, and Graph
Synchronization ............................................................................... 127
Static field values .............................................................................128
Instance Details Page ...................................................................................128
Instance graph .................................................................................129
Referenced by...................................................................................129
References/Wraps .......................................................................... 130
Field values ...................................................................................... 131
Wrapped by ......................................................................................134
Related resource instances..............................................................134
Root path .......................................................................................... 135
Instance creation .............................................................................136
Call Stacks/Methods Page ...........................................................................136
Methods View .................................................................................. 137
Call Stacks View ...............................................................................142
Details (allocated instances) ...........................................................145
Native Memory Page ....................................................................................146
Memory View ................................................................................... 147
Real-Time Page ............................................................................................ 151
Graph ................................................................................................ 152
A Comment on the Appearance of Total and Live Plots ............... 152
Settings and Series...........................................................................154
Real-time Types/Resources ............................................................164
Working with the Graph..................................................................165
Session Time Selector..................................................................... 168
Reducing Data..................................................................................169
Dispose Tracker............................................................................................169
Disposed Instances ..........................................................................170
Undisposed instances ...................................................................... 172
Heap Utilization Tracker ............................................................................. 172
Unreachable instances .................................................................... 174
Unmanaged Resources Tracker .................................................................. 174
Resource Tracker Limitations......................................................... 175
Creation Context .............................................................................. 175
AppDomains Tracker ................................................................................... 176
Call Stacks Reduction .................................................................................. 176
Limiting Call Stack Depth ............................................................... 177
Call Stack Reducer ........................................................................... 177
GC Handle Identification.............................................................................178
Visual Studio Integration............................................................................. 181
Start Profiling a Project ...................................................................182
Debug Profiling ................................................................................183
Profiling the Azure Compute Emulator ........................................ 184
Run Tests under the Profiler.......................................................... 184
Open a Previously Saved Session ...................................................185

.NET Memory Profiler Contents v


Access Profiler Settings ...................................................................185
Commands in Visual Studio............................................................185

The NmpCore Tool 191


Starting NmpCore............................................................................ 191
Command Line Examples ...............................................................193
NmpCore MSBuild Task..................................................................194

.NET Memory Profiler API 196


Retrieve Memory Usage Information............................................. 197
Use Assertions to Detect Memory Leaks........................................199
Using Wildcard to Perform Namespace Assertions ..................... 202
Memory Assertions Session ........................................................... 202
Performing Assertions using the AssertionsDefinition class....... 203
Specifying Types using TypeSets ................................................... 207
Declarative Memory Assertions..................................................... 208
Memory Assertions on Generic Types........................................... 210
Using Memory Assertions with Unit Testing................................ 210
How to Call the .NET Memory Profiler API Methods .................. 210
Adding Comments to the Real-time Graph ...................................212
Handling Failed Memory Assertions ..........................................................212
Viewing Failed Memory Assertions ................................................213

Appendix 215
Attach to Process using Profiling API ......................................................... 215
Support for Generics .................................................................................... 215
Generic Types................................................................................... 215
Generic Methods..............................................................................216
Known Issues................................................................................................216

Glossary of Terms 219

Index 221

vi Contents .NET Memory Profiler


User Manual

Introduction
.NET Memory Profiler is a tool for the .NET Common Language
Runtime that allows the user to retrieve information about all
instance allocations performed on the garbage collected heap (GC
heap) and all instances that reside on the GC heap. The retrieved
information is presented in real time, both numerically and
graphically.
The real-time information presented gives a good overview of the
activity and status of the GC heap, but by collecting snapshots of
the heap, very detailed information can be presented. Information
is provided about: all managed types, all instances of types, the call
stacks of the instance allocations, and the path to a root from each
instance. An instance graph can be presented for a set of instances
or a specific instance, giving a visual overview of how the instances
are used and how they are related to other instances.
It is possible to compare two snapshots, which is a very convenient
and efficient way of detecting memory leaks in a program. The
memory profiler also helps to locate sections of the program that
perform excessive allocations.
The automatic memory analyzer provides tips and warnings
regarding common memory usage issues, making it easier to locate
potential memory leaks and optimize memory and resources
usage.
The profiler contains a dispose tracker, which provides additional
data about disposable instances (i.e. instances of classes
implementing IDisposable), and a heap utilization tracker, which
gives information about how the heap memory is utilized.
In addition to presenting information about the GC heap, the
profiler also presents information about the native memory of the
profiled process or any other process running on the computer.

.NET Memory Profiler User Manual 1


An API is available that can be used to programmatically check for
memory leaks. Combined with the possibility to run the profiler
without a user interface, e.g. using the NmpCore tool or the
NmpCore task, this API can be used to perform fully automated
memory testing.
The professional edition of .NET Memory Profiler includes
additional features such as the unmanaged resources tracker, the
attach to function, the possibility to import memory dump files,
profiler projects, and peak snapshots.
The resource tracker allows the profiler to present detailed
information about unmanaged resources, such as heap memory,
bitmaps and windows.
The attach to function and the possibility to import memory
dump files make it much easier to investigate memory issues on
production systems where it might not be possible to use the
profiler directly.
A .NET Memory Profiler project allows all settings used to profile a
process to be saved, making it easier to use different settings for
different applications. It also keeps track of session files related to
the project, allowing the user to compare snapshots between
different sessions. This is particularly useful when doing
automated testing and the user wants to check whether the
memory usage has changed between different builds of a program.

How to...
This section describes how to perform some standard tasks with
.NET Memory Profiler.

Profile a .NET Process


Using .NET Memory Profiler, it is possible to profile the memory
of the following kinds of processes:
Stand-alone application
ASP.NET
Window Store App
Silverlight application
WPF Browser application
Windows Service
It is also possible to profile the memory of an already running
.NET process by using the attach to function.
To profile the memory of a process, perform the following steps:
1. Start the process you want to profile by following the
how to instructions for the desired kind of process:

2 User Manual .NET Memory Profiler


Start Profiling an Application on page 4.
Start Profiling ASP.NET on page 4.
Start Profiling a .NET Core App on page 6.
Start Profiling an ASP.NET Core App using IIS
Express and .NET Core on page 7.
Start Profiling a Silverlight Application on page 8.
Start Profiling a Windows Store App on page 5.
Start Profiling a WPF Browser Application on
page 9.
Start Profiling a Windows Service on page 9.

Or use the Attach to Process command to attach


to an already running process. For more information
see Attach to a Process on page 20.
2. When you have performed the necessary steps to start
profiling and the process is running, you can select the
Collect Heap Snapshot command to retrieve
information about the GC heap. This information
includes all classes that have had any allocated instance
and the call stacks of those allocations. The information
about all the classes is presented under the
Types/Resources page. Information about call stacks
and methods is presented on the Call
stacks/Methods page. Additionally, you can view
information about the native memory of the snapshot
under the Native memory page.
3. If automatic saving of snapshots is enabled, then the
snapshot will be saved in a temporary profiler session
file, allowing you to use the collected snapshot as a
comparison for subsequent snapshots. If automatic
saving of snapshots is not enabled, you will need to use
the Save snapshot command to be able use the
snapshot for later comparison. For more information
about automatically saving snapshots, see Session
Settings on page 98.
4. As long as the application is running, you can collect
additional heap snapshots. Each snapshot is
automatically compared with the previous one, but you
can compare any two snapshots by using the Show
snapshot and the Comparison snapshot dropdown
lists. This provides you with information about the
memory allocations performed between two snapshots.
5. When you are done profiling select the Stop command.
You will be given the opportunity to save the profiler
session to disk.

.NET Memory Profiler User Manual 3


Start Profiling an Application
To profile the memory of an application perform the following
steps:

1. Select the Profile Application command from


the menu or toolbar.
2. The Profile Application wizard appears.
3. Use the Browse button or the drop-down list to
select the executable file of the application you want to
profile.
4. If you want to supply program arguments, enter the
command line in the Command line arguments
field.
5. If you need to specify the working directory of the
application, you can do that using the Working
directory field.
6. If you want to profile using the default settings, click
Start to start the application.
7. Determine if you want to profile the started process, the
first .NET process, or the started process including all
child processes (enterprise only).
8. If you want to modify settings, you can use the Next
button to modify some common settings.
9. When you have decided on the settings, click Start to
start the application.

Start Profiling ASP.NET


An ASP.NET application can be profiled using IIS Express, the
Internet Information Services web server, or the development web
server (WebDev.WebServer). Normally, it is recommended that
the IIS Express server be used.
To profile the memory of an ASP.NET process, perform the
following steps.

1. Select the Profile ASP.NET command from the


menu or toolbar.
2. The Profile ASP.NET wizard appears.
3. Select how the ASP.NET application should be
launched:
Launch using IIS Express
Launch using Internet Information Services
Launch using WebDev.WebServer

4 User Manual .NET Memory Profiler


4. If IIS Express is selected, you can optionally choose an
IIS Express configuration file, and then select the web
site to profile. If no configuration file is specified, the
default IIS Express configuration file will be used.
5. If the development web server is used, use the Browse
button or the Web-site directory drop-down list to
define the directory where the web site is located.
6. In order to automatically start the ASP.NET
application, you can select a web page that should be
requested when the profiling is started. If you do not
want a page to be selected, select (none) in the request
page drop-down list.
7. Select the command Start.
If the IIS server is used, this will stop the IIS Services
(IIS Admin, World Wide Web Publishing, and any
other services that depend on IIS Admin). A number
of environment variables are set, and then the stopped
services are restarted.
If IIS Express or the development server is used, a new
instance of IISExpress or WebDev.WebServer will be
started.
8. If you want to profile using the default settings, click
Start to start the application.
9. If you want to modify settings, you can use the Next
button to modify some common settings.
10. When you have decided on the settings, click Start to
start the application.
11. If you did not define a page to request, you need to
force the start of the ASP.NET process by requesting an
ASP.NET page (e.g., an .aspx page) when you get the
Waiting for profiled process to start message.
12. When the Waiting for .NET runtime to be loaded
message has disappeared, you can start collecting heap
snapshots.

Start Profiling a Windows Store App


To start profiling the memory of a Windows Store app, perform the
following steps:

1. Select the Profile Windows Store App


command from the menu or toolbar.
2. The Profile Windows Store App wizard appears.
3. Select the Windows Store App to profile.

.NET Memory Profiler User Manual 5


4. If you want to profile using the default settings, click
Start to start the application.
5. If you want to modify settings, you can use the Next
button to modify some common settings.

NOTE! When profiling a Windows Store App, the snapshots will


only contain information about managed .NET instances and
optionally unmanaged resource instances (if the resource tracker is
enabled). No information will be provided about non-.NET
WinRT components.

Start Profiling a .NET Core App


.NET Core profiling is performed using the Profile application
command.

1. Select the Profile Application command from


the menu or toolbar.
2. The Profile Application wizard appears.
3. Enter dotnet.exe as the executable to profile. This will
use the .NET core executable available on the PATH. If
both 32-bit and 64-bit .NET Core are installed, or if
another launcher executable should be used, then use
the Browse button to select the executable file of the
.NET Core application.
4. Specify the .NET Core application to profile in n the
Command line arguments field.
5. Specify the directory of the .NET Core app using the
Working directory field.
6. Check that the Profile as .NET Core application is
selected. This will make sure that the .NET Core app
will be considered the primary process to profile, even
if another launcher process is used. If dotnet.exe is
specified as the executable, this option will
automatically be selected.
7. Determine if you want to profile the started process
(.NET Core), the first .NET process, or the started
process including all child processes (enterprise only).
8. If you want to profile using the default settings, click
Start to start the application.
9. If you want to modify settings, you can use the Next
button to modify some common settings.
10. When you have decided on the settings, click Start to
start the application.

6 User Manual .NET Memory Profiler


Start Profiling an ASP.NET Core App using IIS
Express and .NET Core
The easiest way of profiling a .NET Core ASP.NET Core application
is by starting the profiler from Visual Studio 2017, e.g. using the
command Profiler->Start memory profiler in Visual
Studio. For more information, see Start Profiling a Project on
page 182.
The IIS Express configuration of an ASP .NET Core application in
Visual Studio is based on environment variables in the IIS Express
application host configuration file, instead of a web.config file for
each build output. These environment variable are updated by
Visual Studio before launch, to reflect the currently selected build
output. Currently it is not possible to initialize these environment
variables using .NET Memory Profiler (except by using the
command Profiler->Start memory profiler in Visual
Studio), so the following procedure is necessary to
profile an ASP.NET Core application using the
standalone profiler.
1. Use Visual Studio to publish the ASP.NET Core
application to the file system. This will create a
runnable version of the ASP.NET Core app, including a
web.config file.
2. Add the location of the published web application as a
site in the IIS Express application host configuration
file (applicationhost.config). This can be the
configuration file for the Visual Studio solution (located
in the .vs directory of the solution), or the global IIS
Express configuration file (located under
C:\Users\<User>\Documents\IISExpress\config).
Below you will find an example of the site element.
Replace <id> and <path to .NET Core app
directory> with suitable values.
<sites>
...
<site name="PublishedWebApplication1" id="<id>">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="<path to .NET Core app directory>" />
</application>
<bindings>
<binding protocol="http" bindingInformation="*:53415:localhost" />
</bindings>
</site>
...
</sites>

1. In the profiler select Profile ASP.NET and then the


Launch using IIS Express option.
2. Specify the configuration to file to use in the IIS
Express config file field. This should be the
configuration to which the site information was
added.

.NET Memory Profiler User Manual 7


3. Select the site that was added to the configuration
file (e.g. PublishedWebApplication) in the Use
IIS Express web site field.
4. Make sure the Profile as .NET Core application
option is selected. This will make sure that the
primary process to profile will be the .NET Core
process, and not the IIS Express process.
5. Click Start to start profiling, or Next to specify
additional settings.

Start Profiling a Silverlight Application


To start profiling the memory of a Silverlight application, perform
the following steps:

1. Select the Profile Silverlight Application


command from the menu or toolbar.
2. The Profile Silverlight Application wizard appears.
3. Select how the Silverlight application should be started:
Start using Silverlight application package
Use this option profile a standalone Silverlight
package (XAP).
Start using ASP.NET application web page
Use this option if the Silverlight application is
hosted by an ASP.NET application.
Start using specific web page
Use this option is the Silverlight application is
hosted by a web server.
4. Define the additional options needed:
Full path to the Silverlight package and optionally
whether the application should run out-of-browser,
if Start using Silverlight application package
was selected.
WebDev.WebServer settings and page to request, if
Start using ASP.NET application web page was
selected.
URL or path to web page hosting the Silverlight
package, if Start using specific web page was
selected.
5. If you want to profile using the default settings, click
Start to start the application.
6. If you want to modify settings, you can use the Next
button to modify some common settings.

8 User Manual .NET Memory Profiler


7. When you have decided on the settings, click Start to
start the application.

Start Profiling a WPF Browser Application


To profile the memory of an application perform the following
steps:

1. Select the Profile WPF Browser Application


command from the menu or toolbar.
2. The Profile WPF Browser Application wizard appears.
3. Use the Browse button or the drop-down list to
select the WPF browser application you want to profile.
4. If you want to profile using the default settings, click
Start to start the application.
5. If you want to modify settings, you can use the Next
button to modify some common settings.
6. When you have decided on the settings, click Start to
start the application.

Start Profiling a Windows Service


To profile the memory of a .NET Windows Service process,
perform the following steps:

1. Select the Profile Service command from the


menu or toolbar.
2. Select the service you want to profile from the list of
services.
3. If you want to profile using the default settings, click
Start to start the application.
4. If you want to modify settings, you can use the Next
button to modify some common settings.
5. When you have decided on the settings, click Start to
start the application.
6. When the Waiting for profiled process to start
message has disappeared, you can start collecting heap
snapshots.

Select Processes to Profile


After starting the selected application or service, the profiler will
by default start profiling the first process that loads the .NET
runtime. This includes any child process that might have been
created by the launched process and sometimes this is not the
process you actually want to profile.

.NET Memory Profiler User Manual 9


To change this behaviour, you can use the Select processes to
profile field when selecting the executable or service to profile.

The following options are available:


Launched process
Only profiles the actual executable process specified
when profiling an application. This option is suitable if
the started application process might create .NET child
processes before it loads the .NET runtime.
First .NET process
Only profiles the first process that loads the .NET
runtime, either the started process or any of its created
child processes. This option is suitable if the specified
process is just a launcher application for the actual
process.
Enterprise only All .NET processes (including child
processes) Enterprise only
Profiles all processes that loads the .NET runtime.
This includes the started process and any child
processes it creates.

Profile a Remote Process


Enterprise only To profile a remote process you start profiling the same way as
with local profiling.
1. Start NmpCore on the remote machine, using the /ra
command line option, e.g. NmpCore /ra.

2. Select one of the start profiling options, e.g.


Profile Application, Profile ASP.NET, or
Profile Service.
3. On the process selection page, enter the name of the
remote machine, or use the Find button to browse for
remote profiling agents on the local network.
4. Select the application, service, or process to profile.
5. If you want to profile using the default settings, click
Start to start the application.

10 User Manual .NET Memory Profiler


6. If you want to modify settings, you can use the Next
button to modify some common settings.
7. When you have decided on the settings, click Start to
start the application.
For more information about remote profiling, see Remote
Profiling on page 80.

Use the Memory Analyser


Whenever a snapshot comparison has been performed, the
memory analyser will provide warnings, suggestions, and
information about common memory usage problems. Perform the
following steps to investigate issues identified by the memory
analyser:
1. Select snapshots to analyse (e.g. by collecting a
snapshot, or load a stored profiler session).
2. Wait for the comparison analyser to finish.
3. In the Overview view, use the info panel to view the
memory issues found. The most severe issues will be
listed first.
4. Select an issue to investigate further. Clicking the links
in the info panel will provide more detailed information
about the issue.
5. After reviewing the issue, it can be normally be decided
that it is:
a problem that needs to be solved (e.g. a left-over
event handler that could cause a memory leak)
a problem that could cause inefficient memory
usage (e.g. failing to dispose instances that release
unmanaged resources)
a problem that is caused by the .NET Framework or
third party code - should normally be ignored.
a falsely identified issue (e.g. EventHandlers and
delegates are common causes of memory leaks, but
holding instances only through an EventHandler
might also be perfectly legitimate) - should
normally be ignored.
an informational issue (e.g. an instance that resides
in the large object heap).
6. If it is decided that the issue should not be resolved or
that the information presented is not important, it is a
good idea to ignore the issue to make it easier to focus
on the more important issues. Issues are ignored by
clicking the Ignore... link next to the issue title. For

.NET Memory Profiler User Manual 11


more information, see Ignoring Analysis Issues on
page 35.
7. Repeat from step 4 until all relevant issues have been
reviewed.
For more information about the automatic memory analyzer, see
Automatic Memory Analysis on page 31

Find Memory Leaks


One way to find memory leaks is to look at a task that performs a
lot of memory allocations and keeps instances in memory, but
whose memory should be released after the task is finished.
Examples of such tasks are listed below:
Showing and closing a form
When creating a form, each control must be allocated,
and the instances of the form and controls are kept in
memory. When the form closes all used memory should
be garbage collected.
Opening and closing a document
In a document-oriented program the user should be
able to open a document, work with it and then close it
without increasing the memory used by the application.
Retrieving a set of pages using ASP.NET
When retrieving pages using ASP.NET, many
temporary instances may be created, but, except for
caching, all allocated instances should be released after
the pages have been retrieved and the session (if any)
has ended.

To find memory leaks of a selected task, you can click the


Investigate memory leaks guide on the Start page and follow the
steps in the guide. For more information, see Guided Profiling
and the Tasks Window on page 70.
To find the memory leak manually, you can perform the following
steps:

1. Start profiling the application, service, or ASP.NET


process using the procedure described under the
Profile a .NET Process section.
2. Perform the task you suspect are leaking memory (e.g.,
open a document, work with it, and then close it).
This will make sure that all static instances are created.
3. Collect a heap snapshot.
4. Repeat the task performed under step 2.
5. Collect another heap snapshot.

12 User Manual .NET Memory Profiler


6. Use the Show types drop-down list to select With
New or Removed Instances to show types whose set of
instances has changed between the two snapshots.
7. Select the Types page and try to locate a type that has
live instances that should have been collected.
If no memory leak exists, the instances shown in the
Types page should only be short-lived instances that
have not been garbage collected yet. If a memory leak
exists, you should be able to find a type with new
instances that should have been garbage collected. For
instance, if the task were opening and closing a
document and a type representing the document has
new instances, then there probably is a memory leak. If
you have types that have disposed instances, it may also
be an indication of a memory leak. For more
information, see Dispose Tracker on page 169. The
automatic memory analyser might also provide hints on
potential memory leaks. For more information, see
Automatic Memory Analysis on page 31
8. Double-click on the type that has live instances that
should have been collected.
9. In the Instances table, double-click on one of the new
instances (indicated by the symbol ).
10. In the Root path table you will get information about
why the selected instance was not garbage collected.
For more information on how to locate memory leaks, see the
.NET Memory Profiler tutorials at:
http://memprofiler.com/tutorials.

View Real-time Heap Utilization


The garbage collector is optimized for a scenario in which all
allocated instances are short-lived, except for instances that are
allocated at the beginning of the application. If the allocations and
instances lifetimes follow this scenario, the time used for garbage
collections will be minimized, and the heap utilization will be more
efficient. If they do not follow this scenario, it might result in more
time being spent garbage collecting and in less-efficient utilization
of memory.
To view how efficient the heap utilization is, the real-time data
collection feature of the profiler can be used. To view the heap
utilization, perform the following steps:
1. Make sure that real-time data are collected using the
Collect real-time data setting in the Profiler Settings
form.

.NET Memory Profiler User Manual 13


2. Start profiling the application, service, or ASP.NET
using the procedure described under the Profile a
.NET Process section.
3. Select the Real-time page and add plots for Total bytes
and Live bytes, by checking the checkboxes in the
Statistics view.
4. Now, you can view how the heap is utilized while the
profiled process is running.
5. Compare the real-time graph with the two graphs
below. Preferably, the real-time graph should be similar
to the first of the two graphs below. If it is similar to the
second graph, then an analysis of the lifetime of
instances is recommended.

This graph shows a scenario that is optimal for the


garbage collector; only generation #0 collects are
needed to keep the Total bytes close to the Live bytes,
and the heap utilization is very efficient. The overhead
is only about 200 Kbytes.

This graph shows a scenario that is far from optimal for


the garbage collector. Generation #0 and generation #1
collections fail to remove almost all instances on the
heap, even though the number of live instances is
almost constant. This forces time-consuming
generation #2 collects to be performed in order to
reduce the memory used. Additionally, the heap

14 User Manual .NET Memory Profiler


utilization is very bad, and only 10 Mbytes of memory
contain live (reachable) instances, while up to 30
Mbytes of memory are used by the heap.
Some things to avoid to reduce the lifetime of instances are:
Allocating large short-lived instances. If an instance is
placed in the large object heap, it will not be garbage
collected until a generation #2 collection is performed.
Referencing short-lived instances from long-lived
instances. If an instance is not going to be used
anymore, the reference should be set to null.
For more information about the real-time graph and real-time data
collection, see Real-Time Page on page 151.
For more information on how to optimize memory usage, see the
.NET Memory Profiler tutorials at:
http://memprofiler.com/tutorials.

Work with a Previously Saved Session


Whenever a profiler session is ended, you will get the opportunity
to save the profiling session. The snapshots in a saved session file
can be viewed by performing the following:
1. Select the Open Session command on the File menu
or toolbar.
2. Browse to the session file that you want to view and
press OK.
3. The snapshot dropdown lists will be filled with the
snapshots that were saved when running the selected
profiler session.
4. To view the different snapshots, use the snapshot
dropdown lists.

Find out Information about the Native Memory of


a .NET Process
To find out how the native memory is used by a .NET process, the
following steps should be performed:
Edit the session settings to enable the very low profiling level.
For more information, see Session Settings on page 98.
Start profiling the application, service, or ASP.NET using the
procedure described under the Profile a .NET Process section.

NOTE! In the professional and enterprise editions, it is also


possible to use the attach to function to find out native memory
information about the process. Since attaching the profiler to a
process does not affect the process at all, more accurate memory

.NET Memory Profiler User Manual 15


values can be presented. However, even though the presented
information is more accurate, it is not as detailed.

1. If possible, start another similar process (for an


application, simply run the .exe once more). Starting
two processes allows memory to be identified as shared
instead of only potentially shared.
2. Work with the process until you reach a state where you
want information about native memory.
3. Collect a generation #0 heap snapshot by using the
Collect Gen #0 Heap Snapshot command.
4. On the Native memory page, select Show memory
of snapshot and select the profiled process. The data
presented under the Physical memory view and the
Committed memory view, should give you a good
understanding how memory is used by the process. For
more information about the memory views, see Native
Memory Page on page 146.

NOTE! If the Physical memory view is to present the working set of


the process, then it is vital that there is enough physical memory
present on the computer to avoid memory being flushed to the
paging file.

Perform Unit Testing together with the Profiler


It may sometimes be useful to perform unit testing (e.g. using
NUnit) together with the profiler, especially when the .NET
Memory Profiler API is used.
There are a few different ways of running unit tests under the
profiler:
Start the unit test runner using the Profile application
command
Use NmpCore to start the unit test runner
Use the NmpCore task in MSBuild (and Visual Studio)
Use the Run tests under profiler command in
Visual Studio

Start the unit test runner using the Profile


application command
To run a unit test program under the profiler; you need to select
the program to run (e.g., NUnit-console.exe, if running NUnit) and
supply any necessary program arguments to the unit test runner.

16 User Manual .NET Memory Profiler


If using a test framework that may spawn separate test processes
(e.g. VSTest), it may be necessary to make sure that all created
processes are profiled (see screenshot) argument, or to prevent
separate process using the VSTest argument /NoIsolation.
Enterprise only Note that the possibility to profile all processes is only
available in the Enterprise edition.

Use NmpCore to start the unit test runner


The NmpCore tool is well suited to run automated memory unit
tests. The unit test runner can be started in the same way as when
using the Profile application command in .NET Memory Profiler,
i.e. by specifying the unit test runner and its arguments. The
following command line can, for instance, be used to start NUnit
under NmpCore:
NmpCore [path]\nunit-console.exe [arguments to NUnit]

If using a test framework that may spawn separate test processes


(e.g. VSTest), it may be necessary to make sure that all created
processes are profiled, using the /profileprocess argument, or to
prevent separate processes using the VSTest argument
/NoIsolation. For example:
NmpCore /profileprocess:all [path]\vstest.console.exe [arguments to
VSTest]

or

.NET Memory Profiler User Manual 17


NmpCore [path]\vstest.console.exe /NoIsolation [additional
arguments to VSTest]

NOTE. If multiple processes are included in a session, it can only


be opened using the Enterprise edition of .NET Memory Profiler.

For more information about command line arguments, see


Command Line Arguments on page 26.
Another option is to create a unit test project in .NET Memory
Profiler and then use that project to profiler the test runner.
1. Create a new profiler project in .NET Memory Profiler
(File->New profiler project)
2. Select Unit Tests as the process to profile.
3. Select the unit test framework to use (VS Test, NUnit,
XUnit, or .NET Core test).
4. It is recommended that the Tool path to the unit test
runner is specified. The profiler will try to locate VS
Test and .NET Core Test, but NUNit and XUnit will
only be found when using the NmpCore task in a
project where the unit test runner is added as a NuGet
package.
5. Specify any additional arguments needed for the test
runner.
6. Click Next to specify additional session settings, or
Finish to accept the default settings.
7. Save the project.
8. Use NmpCore to start profiling using the saved project.
For example by using the command:
NmpCore /project:[path]\TestProject.prfproj

It is also possible to start this project from .NET Memory Profiler,


e.g. by right-clicking the project and then select Start profiler
project.
The main advantage of using the Unit Test profiling type is that it
automatically profiles multiple processes (e.g. additional processes
created by the test runner) and that the created session files can be
opened by the Professional edition, even if it contains multiple
processes.

NOTE. Normally, .NET Memory Profiler keeps the debug symbols


file (.PDB) open when reading symbol information for an
assembly. However, this will prevent the unit tested assembly from
being recompiled while testing. To prevent this, the
/shadowsymbols command line argument can be used.

18 User Manual .NET Memory Profiler


Use the NmpCore task in MSBuild
The NmpCore MSBuild task can also be used to start profiling unit
tests. The NmpCore task is available as a NuGet package:
SciTech.NmpCore.Task. To automatically run a profiler project
after each build:
1. Add the SciTech.NmpCore.Task package to the
Visual Studio project.
2. Add a profiler project to a Visual Studio project. See
Use NmpCore to start the unit test runner for
information about how the create the profiler project.
3. Set the Build action to NmpCore for the profiler
project.
For more information about the NmpCore task, see NmpCore
MSBuild Task on page 194.

Use the Run tests under profiler command in


Visual Studio
Enterprise only In the Enterprise edition you can easily run unit tests under the
profiler by using the command Profiler->Run tests under the
Profiler in Visual Studio. For more information, see Run
Tests under the Profiler on page 184.

Increase the Performance of the Profiler


A lot of effort has been put into making the performance of the
profiler as good as possible, but, nonetheless, it is an intrusive
profiler. Most features of the profiler come with a performance
cost. This section contains information about the cost associated
with some features, most of which are enabled by default.
Disable inlining
Normally, inlining of methods is disabled, in order to present
more accurate allocation call stacks. This comes with a
performance cost. To further increase the performance of the
profiled process, do not disable inlining.
Dispose tracker
The dispose tracker adds very little overhead to the profiler.
Some extra code is injected into the Dispose and Finalize
methods of classes, but the code is very short and should not
affect the performance of the profiled process.
Track heap utilization
Tracking heap utilization has a performance cost when an
instance is garbage collected, and it also increases the memory
usage of the profiler and the profiled process. Heap utilization
tracking is an advanced feature that is disabled by default. You

.NET Memory Profiler User Manual 19


should only enable it when trying to optimize the memory
usage pattern of your application.
Collect instance data
Collecting instance data has no effect on the performance of
the profiled process, but collecting heap snapshots may take a
longer time and the snapshots will be larger. If the time it takes
to collect a heap snapshot is too long, try to reduce the number
size of the collected data, or disable instance data collection
completely. For more information about instance data
collection, see Instance Data Collection Settings Page on page
111
Unmanaged resources tracker
The resources tracker adds a significant overhead to the
profiled process. Unless unmanaged resources are actually
investigated, it is recommended that the resource tracker be
disabled.
All features are enabled and disabled using Session Settings.
Any changes in these settings do not affect any ongoing profiling
session. Changes for Instance data collection can be made on an
ongoing profiling session and will affect the next heap snapshot.

Attach to a Process
Professional and Instead of having the profiler launch the process to profile, it is
Enterprise only also possible to attach the profiler to an already running .NET
Process.
There are two ways of attaching to a process: Attach using
profiling API and Inspection only attach. Attach using
profiling API allows object instances to be tracked between
snapshots, which allows the profiler identify new and removed
instances, which makes it easier to identify memory leaks.
However, when using the profiler API, the profiler will be
loaded into the process and this will affect the performance and
memory usage of the profiler process. Inspection only
attach on the other hand, only inspects the profiled process by
investigating the memory in the process. This has the
advantage that the profiled process is not affected by the
profiler, but the profiler cannot track instances and how they
are moved by the garbage collector.
For more information about profiling API attach, see Attach to
Process using Profiling API on page 215.
The following steps should be performed to attach the profiler to a
running process:

1. Select the Attach to Process command from the File


menu or Attach Profiler to Process from the Profiler
menu if running under Visual Studio.
2. The Attach to wizard appears.

20 User Manual .NET Memory Profiler


3. Select the process you want to attach to from the list of .NET
processes and whether the process should be attached using
the profiling API or using inspection only attach.
4. If you want to profile using the default settings, click Start to
start the application.
5. If you want to modify settings, you can use the Next button
to modify some common settings.
6. When you have decided on the settings, click Start to attach to
the process.

Import Memory Dump Files


Professional and By using the Import Memory Dump command it is possible
Enterprise only to import memory dump files as snapshots into the profiler.
This is especially useful when troubleshooting memory
problems in a production application, e.g. when the problem
occurs on a customers computer and cannot be easily
reproduced.
The following steps should be performed to attach the profiler to a
running process:
1. Obtain one or more memory dump files for the process
you want to investigate. One way of obtaining a
memory dump file is to create a memory dump in the
Windows Task manager. A dump file can be created by
right-clicking on a process and select Create dump
file.
Another option is to use the ProcDump utility, which
can be downloaded from
https://technet.microsoft.com/en-
us/sysinternals/dd996900.aspx.
For example, the command
procdump -ma myapp.exe
will create memory dump files for all processes that are
named myapp.exe.

2. Select the Import Memory Dump command from


the File menu or the Profiler menu if running under
Visual Studio.
3. The Import Memory Dump wizard appears.
4. Use the Browse button or the drop-down list to
select the memory dump file to import.
5. If you want to import using the default instance data
collection settings, click Start to start importing the
dump file.

.NET Memory Profiler User Manual 21


6. Alternatively, you can click Next if you want to modify
the instance data collection settings.
7. When you have decided on the settings, click Start to
start importing the dump file.
8. The .NET runtime data access library (e.g.
mscordacwks.dll) is needed to import the memory
dump. If the correct version of the data access library
cannot be found on the computer, the dialog below will
be shown. If you have Internet access it is
recommended that the requested file be downloaded
from the Microsoft symbol store. This will make sure
that the correct version is available. Otherwise it is
possible to specify the data access library explicitly, e.g.
by copying it from the computer where the memory
dump was created.

Importing Additional Memory Dump Files


It is possible to import additional memory dump files into the
same session, which enables memory dumps to be compared with
each other. To import additional memory dump files, select the
Import Memory Dump command or the Collect Heap
Snapshot command before stopping the session. This will bring
up the Import Memory Dump wizard again, and the dump file
will be imported as an additional snapshot.

Create or Load a Profiler Project


Professional and A profiler project is used to define how you start profiling a
Enterprise only process and the settings to use when profiling. It also keeps
track of session files related to the project, allowing you to
compare snapshots between different sessions. For more
information about profiler projects, see Profiler Projects on
page 79.

22 User Manual .NET Memory Profiler


1. Select the New Profiler Project command from the File
menu or the Profiler->Project menu if running under Visual
Studio 2005.
2. The New Profiler Project wizard appears.
3. Follow the wizard to define the settings for the project.
4. Click Finish to create the project.
To load a previously saved project, use the Open->Profiler
Project under the File menu (or Load Profiler Project under
the Profiler->Project menu in Visual Studio 2005).
A newly created or loaded project can be accessed using the
Profiler Projects Explorer window. If it is not visible, the
Profiler Projects Explorer window can be shown using the
Profiler Projects Explorer command under the View menu (or
the View->Other Windows menu in Visual Studio 2005).

Start Profiling using a Profiler Project


Professional and When profiling is started using a profiler project, the settings in
Enterprise only the project will be used for the new profiling session, and the
session file will be associated with the project (if the session is
saved).
There are several ways to profile a process using a project:

Set a project as active using the Set Project as Active


command in the projects explorer. This will enable the
Start using Profiler Project command in the Profiler
menu.
Right click on a project in the projects explorer and select
Start using Profiler Project.
Start using the standard Profile Application, Profile
ASP.NET, Profile Server or Attach to Process. If a
profiler project is loaded, you will get the opportunity to
associate the session with a project.

NOTE! Associating a session with a project will override the launch


settings in the project.

If you are running the profiler under Visual Studio 2005 and a
profiler project is set as active, you can right click a project in
the Solution explorer and select Start using Profiler
Project as well.

.NET Memory Profiler User Manual 23


Compare Snapshots using the Profiler Projects
Explorer
Professional and The projects explorer can be used to select the snapshots to
Enterprise only compare in the main view.

Select a single snapshot and click Compare Snapshots.


This will cause the selected snapshot to be compared with the
Empty snapshot.
Select two snapshots from the same session (using the Ctrl or
Shift key) and click Compare Snapshots. The most recent
snapshot will be used as the primary snapshot, and the oldest
snapshot will be used as the comparison snapshot.
Select two snapshots from different sessions (using the Ctrl or
Shift key) and click Compare Snapshots. If one of the
snapshots is part of an active session, that snapshot will be
used as the primary snapshot and the other will be used as the
comparison snapshot. If none of the snapshots is part of an
active session, the last selected snapshot (the focused
snapshot) will be used as the primary snapshot.

NOTE! Unless running under Visual Studio, it is not possible to


use a snapshot from a different session as the primary snapshot
while an active profiling session is running. In Visual Studio a new
profiler window will be opened.

Setup Native Stack Walks


Professional and To get as detailed call stacks as possible when the unmanaged
Enterprise only resources tracker is enabled, it is recommended that native
stack walker is enabled. In order for the native stack walker to
work correctly, the symbols files must be available. To set up
the native stack walker and symbol file locations, perform the
following steps:
1. Open the Options window (using Tools->Options).
2. Make sure the unmanaged resources tracker is enabled on the
General page (native stacks walks are only available when the
unmanaged resources tracker is enabled).
3. Under the Call Stacks settings page, enable the Perform
native stack walk option. The stack walk depth can be
limited using the Max stack walk depth field.
4. In order for native stack walks to work correctly, native
symbols information must be available. On the Symbol File
Locations page, make sure that Retrieve debug symbols
from the Microsoft symbols store option is enabled. It is
also recommended that symbols files are cached on the local
drive.

24 User Manual .NET Memory Profiler


5. Now the native stack walker will provide detailed native call
stacks when profiling with the unmanaged resources tracker
enabled.

NOTE! The first time a stack frame is encountered by the native


stack walker, .NET Memory Profiler needs to retrieve information
about the frame from the debug symbols. This can take some time,
especially if the symbols need to be downloaded. However, the
symbol information will be cached by .NET Memory Profiler,
which will make subsequent stack walks very much faster.

Starting .NET Memory Profiler


.NET Memory Profiler is normally started by clicking on the .NET
Memory Profiler icon on the Start menu. This will bring up the
.NET Memory Profiler user interface. From this user interface, it is
possible to start new profiling sessions or work with previously
saved sessions.
Command line arguments can be provided when starting .NET
Memory Profiler. These command line arguments can be used to
load previously saved sessions or to change profiler settings and
automatically start a new profiling session. For more information
about the available command line arguments, see Command Line
Arguments on page 26.
The profiler can be run in two different modes: interactive mode,
which is the normal mode, and non-interactive mode, which is
suitable for automated testing.

Interactive Mode
When running the profiler in interactive mode, the standard user
interface of the profiler is shown when it is started.
Unless the console version of the profiler has been started, or the
command line argument /noui has been provided, the profiler
always runs in interactive mode.

Non-Interactive Mode
The non-interactive mode should only be used when doing
automated testing, for instance, as part of a script. In non-
interactive mode, no user interface window is shown, and it is not
possible to manually control the profiler. The profiler is started in
non-interactive mode by supplying the /noui argument on the
command line or by running the console version of the profiler
(NetMemProfilerConsole.exe).

NOTE! Normally the NmpCore tool should be used instead of


NetMemProfilerConsole.exe. NetMemProfilerConsole.exe is

.NET Memory Profiler User Manual 25


mainly available for historical reasons. For more information
about NmpCore, see The NmpCore Tool on page 191.

Command Line Arguments


There are two executable files that can be used to start .NET
Memory Profiler from the command prompt:
NetMemProfiler.exe and NetMemProfilerConsole.exe.
Both of these are located in the installation directory of .NET
Memory Profiler.
In addition to the .NET Memory Profiler application, the same
arguments are available for the NmpCore tool, except the
arguments /open and /noui. For information about arguments
that are only available to NmpCore, see The NmpCore Tool on
page 191.
By providing command line arguments to the executables, session
files can be opened, or profiler settings can be modified and a new
session started.
The command line should be written in the following form:
NetMemProfiler[Console].exe [options] [<process to profile>]
[<arguments for the profiled process>]
The options are used to change the profiler settings, to specify a
session file to open, and to specify the process to profile.
If no process to profile or session to open has been specified by the
options, then the first non-option argument is used as a path to an
executable to profile. For example, the command
NetMemProfiler.exe MemUser.exe
will start profiling the executable MemUser.exe using the standard
settings (defined using the Settings form) .
To modify the settings, it is possible to provide additional
arguments. For example
NetMemProfiler.exe /adt+ MemUser.exe
will start profiling the executable MemUser.exe with the
AppDomain tracker (specified by the /adt+ option).
It is not allowed to specify conflicting options on the command
line, e.g., /service (profile service) and /program (profile
executable) cannot be used at the same time.
The options may be specified using either a slash, /, or single
dash, -. It is not allowed to have extra spaces between a / or
and the name of the option.
Some options take an additional value. The value can be a boolean,
an integer, or a string.

26 User Manual .NET Memory Profiler


Boolean values are specified using the symbol 0 or - for false,
and 1 or + for true. If no value is supplied, then the value is set
to true.
Integer values and boolean values can be provided directly after
the argument, or they can be separated by a : or a space.
String values must be separated by a : or a space.

NOTE! The settings that are modified by the command line


options only affect the profiling session that is initialized by the
command line arguments. If that session is stopped and another
one is started, the settings from the standard profiler Settings
form are used. Consequently, it is not allowed to specify options
that modify settings without also specifying a process to profile.

Available Command Line Arguments


The following list presents all the arguments that can be provided
on the command line. Most arguments have a long form and a
short form. Both forms can be used, but the long form may be
more suitable in response files and the short for more suitable on
the command line. For more information about the settings that
can be changed using these options, see Session Settings on page
98.

NOTE. Considering the amount of options available, it is


recommended that a profiler project is used instead of providing
session settings on the command line. A profiler project can be
defined using the user interface in .NET Memory Profiler and then
provided on the command line using the /project argument.

Argument Short Description


form
/appdomaintracker[+/-] /adt Boolean option. Indicates whether AppDomain
tracking should be enabled.
/apppools /ap String option. Semicolon delimited list of
AppPool names that should be profiled, when
profiling IIS.
/asp /asp This option enables ASP.NET profiling. May
not be used with /program or /service.
/attach <pid> /a Attach to a running process using the profiling
/attach <process name> API. Specify the process using process id or
process name, e.g. /a 1234, or /a
SomeProcess.exe. Requires that the process
runs under .NET Framework 4.0 and has
concurrent GC disabled. For more information,
see Attach to Process using Profiling API on
page 215.
/attachtype <type> /at Specifies the attach type. Can be used together
with /attach to specify how the process should

.NET Memory Profiler User Manual 27


be attached. Overrides the /inspectionattach
argument. Available options: inspection, api.
/autocollect <interval> /ac Integer option. Enables automatic snapshot
collection and sets the collection time interval
(in minutes).
/callstacks[+/-] Boolean option. Enables or disables the
collection of allocation call stacks.
/collectandstop <count> /cs Integer option (optional). Collects the specified
number of snapshots and then stops the
profiler. The snapshot collection interval is
specified using the /autocollect argument. If
the /autocollect argument is not included, the
default collection interval of 10 minutes is used.
/collectrealtime[+/-] /cr Boolean option. Enables or disables the real-
time data collection. May not be used with
/delaycleanup.
/disableinlining[+/-] /di Boolean option. Enables or disables inlining of
methods. May not be used with
/nativeprofiling.
/disposetracker[+/-] /dt Boolean option. Enables or disables the dispose
tracker. May not be used with /nativeprofiling.
/heaputil[+/-] /hu Boolean option. Enables or disables the heap
utilization tracker.
/iisexpressconfig String path. Specifies the path to the IIS
Express config file.
/includeinstancedata[+/-] /iid Boolean option. Indicates whether instance
data should be included in the auto-saved heap
snapshots.
/inspectionattach <pid> /ia Attach to a running process using the
/inspectionattach <process inspection only attach. Specify the process
name> using process id or process name, e.g. /a 1234,
or /a SomeProcess.exe.
/instancetracking <level> /it
/maxgraphmemory <kbytes> /mg Integer option. Only used if collecting real-time
data. It defines the maximum amount of
memory (in kilobytes) to use for real-time data
for classes included in the real-time graph.
/maxnographmemory /mng Integer option. Only used if collecting real-time
<kbytes> data. It defines the maximum amount of
memory (in kilobytes) to use for real-time data
for classes not included in the real-time graph.
/maxsnapshots <count> /ms Integer option. Defines the maximum number
of software triggered heap snapshots.
/memleakcollect[+/-] /mlc Boolean option. Indicates whether a full heap
snapshot should be collected when a memory
leak is detected.
/memleakprompt[+/-] /mlp Boolean option. Indicates whether the user
should be prompted for an action when a
memory leak is detected.
/memleakstartui[+/-] /mlui Boolean option. Indicates whether the user
interface should be started when a memory leak
is detected.

28 User Manual .NET Memory Profiler


/memleakstopsession[+/-] /mlss Boolean option. Indicates whether the profiling
session should be stopped when a memory leak
is detected.
/memleaksuspend[+/-] /mlsu Boolean option. Indicates whether the profiled
process should be suspended while a detected
memory leak is being handled.
/noui /noui Runs the profiler in non-interactive mode. If
this option is used, a process to profile must
also be specified.
/open <file path> /open String option. Opens the previously saved
session file specified by the option value. This
option may not be used with any other options.
/passthrough[+/-] /pt Boolean option. If true, then the exit code of the
profiled process will be returned from the
profiler instead of the standard exit code.
/peaksnapshot[+/-] /ps Boolean option. Enables or disables peak
snapshot collection.
/peaksnapshotthreshold /pst Integer option. The threshold in percent for
collecting a peak memory snapshot.
/profileprocess /pp String option. Defines the processes that should
be profiled. Available option are: all, first,
started.
/profilingtype <type> String option. Specifies the profiling type. Can
be used instead of the specific profiling
arguments (such as /iis, /service, /attach).
Available options are: Application, Service, IIS,
WebDevServer, Silverlight, Attach,
WpfBrowserApplication, MemoryDumpImport,
IISExpress, WinStoreApp, UnitTest.
/program <file path> /p String option. The option value specifies the
path of a program to profile. This option must
be the last option, since subsequent arguments
are used as arguments for the profiled program.
This option is the default option, so it is
possible to specify the program to profile by
simply providing the path to the program
without the parameter name (/program or /p).
May not be used with /service or /asp.
/properties /prop String option. Semicolon delimited list of
properties that can be used by the profiler
project using MSBuild property notification.
E.g. the path to the executable to profile can be
specified using
/prop:ExePath=c:\Dev\SomeProject\bin\Som
eProject.exe and then be used in the profiler
project as $(ExePath.
/project <file path> /prj String option. The option value specifies the
path of a profiler project. The settings of the
project are used to start profiling a new session.
If a process to profile is specified using
/program, /service or /asp this will override the
launch settings in the profiler project.
/resourcetracker[+/-] /rt Boolean option. Indicates whether the
unmanaged resources tracker should be
enabled.

.NET Memory Profiler User Manual 29


/rootidentification[+/-] /ri Boolean option. Enables or disables root
identification. May not be used with
/nativeprofiling.
/saveproject[+/-] /sprj Boolean option. Indicates whether the project
specified by /project should be automatically
saved if a session has been added to it. The
default setting is to save the project; to avoid
saving provide the argument /saveproject.
This option only affects the profiler when
running in non-interactive mode.
/service <service name> /svc String option. The option value specifies the
name of a service to profile. May not be used
together with /program or /asp.
/sessionend <option> /se String option. Specifies the action to be
performed when the profiling session is ended.
The available options are: prompt, save,
savesnapshots, discard.
/sessionfile <file path> /sf String option. The option value defines the
name of the file to which auto-saved session
files should be saved. The file name can include
the strings %DATE% and %TIME%. These
strings will be replaced with the current date
and time when the session is saved.
/sessionfolder <folder path> /sfl String option. The option value defines the
folder in which auto-saved session files should
be saved. It is recommended that this argument
is avoided, instead use /sessionfile to specify
the full path of the session file
/sessionprompt[+/-] /sp Boolean option. Indicates whether the user
should be prompted for an action when a
session is ended.
/shadowsymbols[+/-] Boolean option, Indicates whether a shadow
copy should be made of the symbol files. To be
enable to recompile an assembly while profiling
(e.g. when running unit tests), this option must
be enabled. Note, this option affects all sessions
started by the profiler, not just the one started
first.
/snapshotselect[+/-] /ss Boolean option. Indicates whether the user
should be allowed to select which snapshots to
include when saving the profiling session.
/winstoreapp <app user model String option. Specifies the Windows store
id> application user model id.
/winstorepackage <package String option. Specifies the Windows store
id> application package to profile.
/workingdirectory <path> /wd String option. Specifies the working directory of
the profiled process.

Response Files
Response files can be used to provide command-line arguments to
the profiler. A response file is a text file with one command line
argument per line. A # symbol can be used to specify comments
in the response file.

30 User Manual .NET Memory Profiler


To provide a response file to the profiler, use the @ symbol
followed by the name of the response file.
Example:
Assume the file named MemUser.rsp contains the following text:
# MemUser.rsp
#
# Starts profiling the executable MemUser.exe in
# non-interactive mode. The dispose tracker is disabled
# and the session is automatically saved at the end.

/noui

/disposetracker-

/sessionprompt-
/sessionfile:MemUser.exe session %DATE% %TIME%.prfsession
/sessionfolder:C:\Autosaved sessions

# The program to profile must be the last argument.


MemUser.exe

To start the profiler using the response file above, the following
command should be used:
NetMemProfiler.exe @MemUser.rsp

Exit Codes
The .NET Memory Profiler executables return an exit code. This
exit code can be useful when doing automated testing in a script.
The following return codes are used:
Code Meaning
0 Success. The profiler was run normally.
1 Memory leak detected. A memory leak has been detected when
profiling.
2 Argument error. The arguments supplied contained an invalid
argument.
3 Unexpected error. The profiler exited because of an unexpected
error.
259 Returned if the /passthrough command line argument was
provided and no return value from the profiled process exists
(e.g. if the process was terminated). (The value 259 is defined as
STILL_ACTIVE. in the Windows SDK and is used by
GetExitCodeProcess to indicate that the exit code is not
available)
Any If the /passthrough command line arguments was provided, the
exit code of the profiled process is returned.

Automatic Memory Analysis


Whenever a new snapshot comparison has been performed, e.g.,
after collecting a snapshot or changing the selected or comparison
snapshot, .NET Memory Profiler will start analysing the memory
data. As soon as the analysis is finished, any found issues will be

.NET Memory Profiler User Manual 31


presented in info panels under the Types/Resources page, the
Type details page, and the Instance details page. An example
of summary issues presented in the info panel under the
Types/Resources page can be seen below.

The issues presented provide warnings, suggestions, and


information about common memory usage problems. The severity
of an issue is defined using the following levels:

Serious warning
A serious warning indicates an issue that could, with a high
probability, cause memory usage problems, such as memory or
resource leaks.

Warning
A warning indicates an issue that could cause memory usage
problems, such as memory or resource leaks.

Minor warning
A minor warning indicates an issue that could cause bad
memory or resource utilization, but it should not cause
problems like memory leaks.

Indirect warning
An indirect warning indicates an issue that is caused by
another warning issue. The issue will contain information
about the issue that causes the direct warning.

32 User Manual .NET Memory Profiler


Suggestion
A suggestion indicates an issue that, similar to the minor
warning, could cause bad memory or resource utilization.

Information
The information level indicates issues that provide information
about memory usage, but they are not directly related to a
memory usage problem.

Indirect information
The indirect information level indicates that an issue is a
consequence of another informational issue.

Pending issue
The pending issue level indicates that there is a possible issue,
but that further analysis has to be performed. This level is
currently only used for duplicate instances that are not fully
investigated. For more information, see Duplicate Instances
Detection on page 47.
An issue can be related to a specific instance (e.g. a potential
memory leak), a specific type (e.g. a type with undisposed
instances), or the full snapshot memory data (e.g. a summary of
the total ASP.NET cache usage).

NOTE! Only managed data is analysed for memory issues.


Currently, there is no automatic analysis for native memory and
resources.

Issue Presentation
As mentioned previously, issues are presented in the info panels of
the Types/Resources page, the Type details page, and the
Instance details page. Unless the info panel is expanded, only
the first, most important, issue is presented, and only the title is
included.

Full information about all issues is presented by expanding the


info panel. This can be done by hovering the mouse over the info
panel, or by using the "pin" button to the right.

.NET Memory Profiler User Manual 33


The full information includes a descriptive text for each issue and a
set of links for each issue, allowing navigation to more specific
issues or additional information. The (Show details) link will
show the details of the issue as an instance and allocation filter. All
instances and allocations that are associated with the issue will be
included in the filter.
Most issues will also have an (Ignore...) link. This link can be
used to ignore the issue, so that it will no longer be presented. For
more information about ignoring analysis issues, see Ignoring
Analysis Issues on page 35.

Overview page
In the Overview info panel, a summary for each issue is
presented.
For instance-specific issues, the summary will contain links to the
types that have instances related to the issue. For type-specific
issues, links to the types related to the issue will be listed. Further
information can be retrieved by clicking the provided links.
A tooltip will also be provided for each type with associated
analysis issues. The tooltip is shown by hovering over the analysis
icon for the type, and the information presented is the same as in
the Type/Filter details info panel (described below).

Type/Filter details info panel


In the Type details and Filter details info panels, information
about type and instance issues will be presented, together with
other type information.

34 User Manual .NET Memory Profiler


For instance-specific issues, the description will contain links to
the actual instances that are related to the issue. For type-specific
issues, links to further details or information might be provided.
The further details can, for instance, be the allocation stacks for
undisposed instances. The actual links available depend on the
issue.
A tooltip will also be provided for each instance with associated
analysis issues. The tooltip is shown in the Instances list, by
hovering over the analysis icon for the instance. The information
presented is the same as in the Instance details info panel
(described below).

Instance details page


In the Instance details info panel, information instance specific
issues will be presented, together with other instance information

Links to further details or information might be provided. The


further details can, for instance, be links to instances with "real"
warning issues from an instance with an indirect warning. The
actual links available depend on the issue.

Ignoring Analysis Issues


The issues that the memory analyser reports are not always
something that need to be corrected. For example, the analyser will
present issues related to instances that are only kept alive by
delegates. Even though this can indicate a memory problem that
can cause a memory leak, it can also be perfectly legitimate to have
instances that are only kept alive by a delegate. If the issue is not
an actual problem, if the information it presents is not needed, or
if the issue cannot be corrected for some reason (e.g. it is caused by

.NET Memory Profiler User Manual 35


the framework or third party code), it might be a good idea to
ignore the issue so that it will no longer be presented.
An issue is ignored by clicking the (Ignore...) link next to the
issue title, which will bring up the Ignore Analysis Issue
window. This window is used to define when the issue should be
ignored. The available options are:
Always ignore this issue
The issue will always be ignored, regardless of the type,
instance, or call stack associated with the issue.
Only ignore issue for the type <type name>
Only ignore issue for selected types
The issue will be ignored based on the type associated with the
issue. If no types are associated with the issue, this option is
not available. If more than one type is available, a type selector
will be included in the window.
Only ignore issue when root path contains selected
fields and methods
The issue will be ignored based on the root path of the
instance. If no instance is associated with the issue, this option
is not available. If this option is selected, a root path selector
will be included in the window. The root path selector can be
used to select fields and methods that must exist in a root path
in order for the issue to be ignored.
Only ignore issue when... (based on allocation)
The issue will be ignored based on the allocation call stack. If
no allocation call stack is associated with the issue, this option
is not available. If this option is selected, an allocation selector
will be included in the window. The allocation selector is
described below.
Only ignore for the instance #xxx
Only ignore for selected instances
The issue will only be ignored for specific instances. If more
than one instance is available an instance selector will be
included in the window
It is possible to select more than option, in which case all options
must be met for the issue to be ignored.
Allocation selector
The allocation selector is used to specify how an issue should be
ignored based on the allocation call stack. This selector is shown if
the Only ignore issue when... option is selected. The available
options are:
Allocated by <method name>
Allocated by selected methods
The issue will only be ignored if the selected method is at the
top of the allocation call stack. If more than one method is
available, a method selector will be included in the window.

36 User Manual .NET Memory Profiler


Allocated by selected call stack methods
The issue will only be ignored if the selected methods is at the
top of the allocation call stack. If this option is selected, a call
stacks methods selector will be included in the window. The
call stacks methods selector can be used to select a call stack
and then one or more methods at the top of the call stack.
Allocation stack contains selected methods
The issue will only be ignored if the allocation call stack
contains the selected methods. If this option is selected, a call
stacks methods selector will be included in the window. The
call stacks methods selector can be used to select a call stack
and then one or more methods within the call stack.

Ignore issue in
The Ignore issue in dropdown list is used to define where the
information about the ignored issue should be stored. The
available options are:
All sessions
The ignored issue will be stored as a default ignored issue. It
will be ignored in all profiling sessions.
Profiler project (Professional and Enterprise only)
The ignored issue will be stored in the profiler project
associated with the session. It will be ignored in all profiling
sessions associated with the same project. This option is only
available if the session is associated with a profiler project.
Current session
The ignored issue will be stored in the current profiler session.
It will only be ignored in this session.

Modifying Ignored Issues

To show and modify issues that have been ignored, the


Manage Ignored Issues command can be used. This will open
the Ignored Analysis Issue window. This window allows issues to
be removed from the list of ignored issues, which will include them
in the memory analysis again. It also provides the possibility to
change the location of the ignored issues, e.g. change Session to
Default ignored issues.
The main part of this window is a table containing the ignored
issues. The actual ignored issues included depend on the Show
ignored issues setting (see below).
The following information is presented in the ignored issues table:
Issue level
This column shows an icon representing the severity
level of the issue.

.NET Memory Profiler User Manual 37


Analysis issue
This column shows the title of the ignored analysis
issue.
Criteria
This column shows the criteria used when ignoring the
issue (as defined in the Ignore Analysis Issue
window). Only a short description is provided in the
table. A more detailed description is presented in a
tooltip when hovering with the mouse over the short
description.
Ignored in
This column shows where the ignored issue is stored.
This is the only column that can be modified. To change
the location used the dropdown list to select any of:
Session: <session name>, Project: <project
name>, or Default ignored issues.
Show ignored issues
This dropdown list defines what issues should be presented in the
ignored issues table. The available options are:
(All ignored issues)
This option will include all issues in all loaded or active
sessions, all issues in all loaded profiler projects, and
the default ignored issues.
(Combined ignored session issues)
This option will include all issues that will be ignored in
the current session. It is a combination of the issues
ignored in the current session, the issues ignored in the
associated project, and the default ignored issues.
Default ignored issues
This option will only include the issues that ignored in
all sessions.
Session: <session name>
This option will only include issues in the selected
session. There will be one session item available for
each loaded or active session.
Project: <project name>
This option will only include issues in the selected
profiler project. There will be one project item available
for each loaded project.
Remove ignored issue(s)
This button is used to remove the issues selected in the issues table
from the list of ignored issues. This will include them in the
memory analysis again.

38 User Manual .NET Memory Profiler


Reset default ignored issues
This button is used to remove any user modifications from the list
of default ignored issues, and restore the ignored issues from the
.NET Memory Profiler installation.

Analysis Issues List


The following issues are currently detected by the memory
analyser. Additional issues will be added in updates of .NET
Memory Profiler. Suggestions for additional issues that should be
detected by the memory analyser can be sent to
memprofiler@scitech.se.

Error
WPF binding source memory leak
An instance that is the source of a WPF binding where
the instance class does not implement
INotifyPropertyChanged has been detected. The target
of the binding is reachable from the source instance,
which will cause a memory leak. To fix this issue,
INotifyPropertyChanged should be implemented for
the type, or the binding should be changed to a
OneTime binding. To find out how the source and
target are connected, use the Expand path link in the
issue information. For more information, see Microsoft
KB938416.
WPF binding target memory leak
Same as WPF binding source memory leak but
this issue is assigned to the target of the binding.

Serious warning
Potential memory leak
An instance has been detected as a potential memory
leak by a memory assertion. For more information
about memory assertions, see Use Assertions to Detect
Memory Leaks on page 199. This issue cannot be
ignored. To remove this issue, either correct the
memory leak, or, if it is a falsely identified memory
leak, modify the memory assertion so that the instance
is not included.
Disposed instance with direct EventHandler
roots
A disposed instance is directly rooted by an
EventHandler, i.e., the instance is only used as the
target of an EventHandler and it cannot be reached
from any other root without passing through a delegate.
Since a disposed instance should no longer be used and

.NET Memory Profiler User Manual 39


EventHandlers are a common cause of memory leaks,
this issue is a strong indication of a memory leak.
Disposed instance with EventHandler roots via
closure
Same as Disposed instance with direct EventHandler
roots, but the instance is held by a closure instance, and
it is the closure instance that has a direct EventHandler
root. This can occur when adding an EventHandler
using an anonymous method (e.g. when using a lambda
expression).
Disposed instance with direct delegate roots
A disposed instance is directly rooted by a delegate, i.e.,
the instance is only used as the target of a delegate, and
it cannot be reached from any other root without
passing through a delegate. Since a disposed instance
should no longer be used and delegates s are a common
cause of memory leaks, this issue is a strong indication
of a memory leak.
Disposed instance with delegate roots via
closure
Same as Disposed instance with delegate roots via
closure, but the instance is held by a closure instance,
and it is the closure instance that has a direct delegate
root. This can occur when adding a delegate using an
anonymous method (e.g. when using a lambda
expression).
Undisposed instances (release resource, no
finalizer)
A disposable instance has been garbage collected
without being properly disposed. Based on the
classification of disposable types, disposing the instance
might have released an unmanaged resource. The type
of the instance has no finalizer, so failing to dispose the
instance can cause an unmanaged resource leak. For
more information about disposable types classification
and undisposed instances, see Disposable Types
Classification and Undisposed Instances on page 51.
Instances queued for finalization (excessive
finalization or finalizer stuck)
An instance was queued for finalization at the start of
the snapshot and has not been finalized at the time the
snapshot collection finished. This can indicate that too
many instances are being finalized, that the finalizers
take too long time to execute, or that a finalizer is stuck
(e.g. a dead-lock). This issue can also occur if an
instance is being re-registered for finalization without
assigning a strong reference to it.

40 User Manual .NET Memory Profiler


Warning
Potential WPF binding source memory leak
An instance that is the source of a WPF binding where
the instance class does not implement
INotifyPropertyChanged has been detected. The target
of the binding is reachable from the source instance,
which may cause a memory leak. The target and/or
source instance are reachable from other instances, so
this is not a memory leak. However, unless the binding
is removed before the references to the target and
source are removed, this will become a memory leak.
To fix this issue, INotifyPropertyChanged should be
implemented for the type, or the binding should be
changed to a OneTime binding. To find out how the
source and target are connected, use the Expand path
link in the issue information. For more information, see
Microsoft KB938416.
Potential WPF binding target memory leak
Same as Potential WPF binding source memory
leak but this issue is assigned to the target of the
binding.
Direct EventHandler roots
An instance is directly rooted by an EventHandler, i.e.,
the instance is only used as the target of an
EventHandler and it cannot be reached from any other
root without passing through an EventHandler. Since
EventHandlers are a common cause of memory leaks,
this issue can indicate a memory leak. Investigate the
instance and the EventHandler instance to find out
whether the instance is unintentionally held by the
EventHandler, or if the issue can be ignored.
EventHandler roots via closure
Same as Direct EventHandler roots, but the
instance is held by a closure instance, and it is the
closure instance that has a direct EventHandler root.
This can occur when adding an EventHandler using an
anonymous method (e.g. when using a lambda
expression).
Disposed instance
An instance is disposed but still reachable from one or
more roots. Since a disposed instance should normally
no longer be used, this can indicate a memory leak.
Investigate the instance to find out whether the
instance is unintentionally kept alive, or if the issue can
be ignored.

.NET Memory Profiler User Manual 41


Undisposed instances (release resource and
remove external references)
A disposable instance has been garbage collected
without being properly disposed. Based on the
classification of disposable types, disposing the instance
might have released an unmanaged resource and
removed external references to the instance. Failing to
dispose instances of this type can cause bad resource
and memory utilization, and even memory leaks. For
more information about disposable types classification
and undisposed instances, see Disposable Types
Classification and Undisposed Instances on page 51.
Undisposed instances (release resource)
A disposable instance has been garbage collected
without being properly disposed. Based on the
classification of disposable types, disposing the instance
might have released an unmanaged resource. Failing to
dispose instances of this type can cause bad resource
utilization. For more information about disposable
types classification and undisposed instances, see
Disposable Types Classification and Undisposed
Instances on page 51.
Undisposed instances (remove external
references)
A disposable instance has been garbage collected
without being properly disposed. Based on the
classification of disposable types, disposing the instance
might have removed external references to the instance.
Failing to dispose instances of this type can cause bad
memory utilization, and even memory leaks. For more
information about disposable types classification and
undisposed instances, see Disposable Types
Classification and Undisposed Instances on page 51.

Minor warning
Direct delegate roots
An instance is directly rooted by a delegate, i.e., the
instance is only used as the target of a delegate and it
cannot be reached from any other root without passing
through a delegate. Since delegates are a common cause
of memory leaks, this issue can indicate a memory leak.
Investigate the instance and the delegate instance to
find out whether the instance is unintentionally held by
the delegate, or if the issue can be ignored.
Delegate roots via closure
Same as Direct delegate roots, but the instance is
held by a closure instance, and it is the closure instance
that has a direct delegate root. This can occur when

42 User Manual .NET Memory Profiler


adding an EventHandler using an anonymous method
(e.g. when using a lambda expression).
Pinned instance
An instance is pinned in memory. Pinning instances
prevents the garbage collector from moving the
instance and will affect the efficiency of the garbage
collector. If possible, pinning instances should be
avoided. If it is not possible, then the instance should
be pinned for as short period of time as possible.
Instances queued for finalization
An instance is in the finalization queue when the
snapshot is being collected. This can indicate that there
is a problem with slow finalization, but it can also occur
during normal operation.
This issue is only reported when the profiler has not
been able to wait for finalizers to run, e.g. when
importing a memory dump. Normally the profiler will
try to wait for finalizers to finish and report the warning
issue Instances queued for finalization
(excessive finalization or finalizer stuck) or the
informational issue Instances queued for
finalization (pending finalizer) instead.
Resurrected instances
An instance has been resurrected by a call to
ReRegisterForFinalize after the instance has been
finalized (normally ReRegisterForFinalize is called in
the finalizer).

Indirect warning
Disposed instance with indirect EventHandler
roots
A disposed instance is held by another instance that is
directly rooted by an EventHandler. A link will be
provided to the he instance that is directly rooted by the
EventHandler instance. Investigate the directly rooted
instance to resolve this issue.
Indirect EventHandler roots
An instance is held by another instance that is directly
rooted by an EventHandler. A link will be provided to
the he instance that is directly rooted by the
EventHandler. Investigate the directly rooted instance
to resolve this issue.
Disposed instance with indirect delegate roots
A disposed instance is held by another instance that is
directly rooted by a delegate. A link will be provided to
the he instance that is directly rooted by the delegate.

.NET Memory Profiler User Manual 43


Investigate the directly rooted instance to resolve this
issue.
Indirect delegate roots
An instance is held by another instance that is directly
rooted by a delegate. A link will be provided to the he
instance that is directly rooted by the delegate.
Investigate the directly rooted instance to resolve this
issue.
Instance indirectly rooted by finalizer queue
An instance is held by another instance that is rooted by
the finalizer queue. A link will be provided to the he
instance that is directly rooted by the finalizer queue.
Investigate the directly rooted instance to resolve this
issue.

Suggestion
WPF binding target with source that does not
implement INotifyPropertyChanged
An instance, which is the source of a WPF binding
where the instance class does not implement
INotifyPropertyChanged, has been detected. This
delays the garbage collection of the involved instances
and increases the risk of a memory leak.
To fix this issue, INotifyPropertyChanged should be
implemented for the type, or the binding should be
changed to a OneTime binding. For more information,
see Microsoft KB938416.
WPF bindings with source that does not
implement INotifyPropertyChanged
Same as WPF binding target with source that
does not implement INotifyPropertyChanged
but this issue is assigned to the target of the binding.
Undisposed instances (perform action)
A disposable instance has been garbage collected
without being properly disposed. Based on the
classification of disposable types, disposing the instance
might have performed some exit or cleanup operation.
This operation can for instance be flushing data to a
file, committing or reverting a transaction, clearing
security buffers, or deleting temporary files. For more
information about disposable types classification and
undisposed instances, see Disposable Types
Classification and Undisposed Instances on page 51.
Undisposed instances (memory/resource
utilization)
A disposable instance has been garbage collected
without being properly disposed. Based on the

44 User Manual .NET Memory Profiler


classification of disposable types, disposing the instance
might dispose other instances, release COM interfaces,
and suppress finalization. Failing to dispose instances
of this type can cause bad memory and resource
utilization. For more information about disposable
types classification and undisposed instances, see
Disposable Types Classification and Undisposed
Instances on page 51.

Information
ASP.NET session state summary
This issue presents summary information about
ASP.NET session states. This includes information
about how many session state instances exists, how
many instances are held by the session state, and how
many bytes are used by the held session state instances.
Links are provided to the session state types, and all
other types that have instances stored as session state.
ASP.NET session key
An instance is used as, or is part of, an ASP.NET
session state key.
ASP.NET session value
An instance is used as, or is part of, an ASP.NET
session state value.
ASP.NET session state instance
An instance acts as a session state container. This is
normally an instance of the InProcSessionState
class.
ASP.NET cache summary
This issue presents summary information about
ASP.NET cache. This includes information about how
many instances are held by the cache and how many
bytes are used by the held cache instances. Links are
provided to the types that have instances stored in the
cache.
ASP.NET cache key
An instance is used as, or is part of, an ASP.NET cache
key.
ASP.NET cache value
An instance is used as, or is part of, an ASP.NET cache
value.
Duplicate instances
An instance is part of a set of duplicate instances.
For more information, see Duplicate Instances
Detection on page 47.
FixedAddressValueType instance

.NET Memory Profiler User Manual 45


An instance is pinned in memory using the
System.Runtime.CompilerServicesFixedAddre
ssValueTypeAttribute attribute. Pinning instances
prevents the garbage collector from moving the
instance and will affect the efficiency of the garbage
collector.
Large instance
An instance is stored in the large object heap.
Undisposed instances (clear references)
A disposable instance has been garbage collected
without being properly disposed. Based on the
classification of disposable types, disposing the instance
might clear references to other instances, but no
additional operation will be performed. Since a
disposed instance should normally no longer be used,
clearing references from the instance should not affect
the memory usage. Failing to dispose instances of this
type will therefore not cause any performance or
memory penalty. For more information about
disposable types classification and undisposed
instances, Disposable Types Classification and
Undisposed Instances on page 51.
Undisposed instances (no action)
A disposable instance has been garbage collected
without being properly disposed. Based on the
classification of disposable types, disposing the instance
will not cause any action to be performed. Failing to
dispose instances of this type will therefore not cause
any performance or memory penalty. For more
information about disposable types classification and
undisposed instances, see Disposable Types
Classification and Undisposed Instances on page 51.
Undisposed instances (unclassified)
A disposable instance has been garbage collected
without being properly disposed. No information about
the type of the instance is available, so the importance
of disposing the instance cannot be determined.
However, it is recommended that all disposable
instances are properly disposed. For more information
about disposable types classification and undisposed
instances, see Disposable Types Classification and
Undisposed Instances on page 51.
Instances queued for finalization (pending
finalizer)
An instance was queued for finalization when the
snapshot was collected. Even though the instance is still
queued for finalization, it will most likely be finalized
soon.

46 User Manual .NET Memory Profiler


Indirect information
Held duplicate instances
An instance is part of a set of duplicate instances that is
held by another set of duplicate instances. For more
information, see Duplicate Instances Detection on
page 47.

Pending issue
Possible duplicate instances
A set of instances are possibly duplicates of each other,
but a full analysis of the instance graphs has not been
performed. To get information about whether the
instances are actually duplicates, use the Detect
duplicates link. For more information, see
Duplicate Instances Detection on page 47.

Duplicate Instances Detection


The automatic memory analyzer will detect duplicate instances in a
heap snapshot. Since duplicate instances can cause unnecessary
memory usage, this information can help to better optimize the
memory consumption.
Duplicate instances are detected by comparing the full instance
graph of two instances. Two instances are trivial duplicates if they
do not have any references to other instances, and all field values
are equal. However, as soon as the instances have any reference to
another instance, the full graph of reachable instances must be
analyzed in order to determine whether they are duplicates.
Two instances are duplicates if each instance in the reachability
graph of the first instance has a unique matching instance in the
other instance graph. For an instance to match another instance,
all value (non-reference) fields must be equal.

#3 #4 #5 #6
value: 6 value: 7 value: 6 value: 7

m_field1 m_field2 m_field1 m_field2

#1 #2
value: 5 value: 5

In the graph above, instance #1 and instance #2 are duplicates,


since it is possible to find a unique matching instance in both
instance graphs. Instance #1 corresponds to #2, #3 to #5, and #4
to #6.

.NET Memory Profiler User Manual 47


m_field2

#3 #4 #5
value: 6 value: 7 value: 6

m_field1 m_field2 m_field1

#1 #2
value: 5 value: 5

In the graph above, instance #1 and instance #2 are also


duplicates. Instance #4 is reachable from both origin instances and
will be matched with itself.

#3
value: 7
m_field2 m_field2

m_owner
#1 #2
value: 5 value: 5

In the graph above, instance #1 is not a duplicate of instance #2,


even though the instance data of instance #2 is identical to
instance #1 (value is 5 and all references are equal). Instance #1 is
initially matched with instance #2. However, when instance #1 is
reached through the m_owner field of instance #3, it will be
matched with itself (as in the previous example). Since instance #1
does not have a unique match in both graphs, the instances are not
duplicates.

Duplicate Instances Additional Bytes


In order to provide a metric for how much memory duplicate
instances consume, the profiler will calculate an additional bytes
value for each set of duplicate instances.
Consider the following three duplicate instances (#1, #2, and #3):

48 User Manual .NET Memory Profiler


#7 #8
value: 7 value: 7

#4 #5 #6
value: 6 m_field2 value: 6 value: 6
m_field2
m_field2

m_field1 m_field1 m_field1

#1 #2 #3
value: 5 value: 5 value: 5

To calculate the number of additional bytes consumed by the


duplicates, the profiler will merge the duplicate instance graphs
into a single instance graph. Any instance not needed in the
merged graph is considered an additional instance. In this
example graph, instance #2 and #3 can be replaced with #1,
instance #5 and #6 can be replaced with #4, and instance #8 can
be replaced with #7 (as can be seen below).

#7 #8
value: 7 value: 7

#4 #5 #6
value: 6 m_field2 value: 6 value: 6
m_field2
m_field2

m_field1 m_field1 m_field1

#1 #2 #3
value: 5 value: 5 value: 5

The instances #2, #3, #5, #6, and #8 are considered additional
instances, and the sum of the instance sizes will be presented as
the additional bytes value for this set.

Held Duplicates
If a set of duplicates are found, it is often the case the duplicate
instances have references to other duplicate instances. For
instance, a duplicate List<> instance will have a reference to a
duplicate array instance (that contains the actual list data). When
investing a duplicate like this, it is usually better to focus on the
duplicated List<> instance and not the array, since the
duplication of the array is just a side effect.
In an attempt to identify these side effects, the profiler will provide
information about duplicate sets that are fully held by another
duplicate set. A set is fully held by another set if it is not possible to
reach any instance in the second set without passing through an
instance in the first set.

.NET Memory Profiler User Manual 49


In the instance graph below, the set containing instances #4, #5,
and #6 is fully held by the set containing instances #1, #2, and #3.
On the other hand, the set containing instance #7 and #8 is not,
since instance #8 can be reached from a root without passing
through instance #1, #2, or #3.

#7 #8
value: 7 value: 7

#4 #5 #6
value: 6 m_field2 value: 6 value: 6
m_field2 m_field2
m_owner m_owner m_owner
m_field1 m_field1 m_field1

#1 #2 #3
value: 5 value: 5 value: 5

Root #3 Root #3 Root #3 Root #3

The presentation of held duplicates will contain a link to the


duplicate set that is holding on to the held duplicates. This set is
most likely a better candidate to investigate when trying to
minimize the duplication.

Possible Duplicate Instances


To detect whether a set of instances are duplicates of each other,
the profiler needs to investigate the full graph of reachable
instances for each instance in the set. This investigation can take a
long time for a complex memory snapshot. Therefore, the profiler
will only detect trivial duplicates by default.
If a type has at least one set of instances that are not fully
investigated, but can be duplicates, the profiler will add a Possible
duplicate instances issue for this type. The Detect duplicates
link can then be used to force the detection of all duplicates of the
type.

If there are any possible duplicates in the snapshot, a Possible


duplicate instances issue will also be added to the Overview
page. The Detect duplicates link of this issue, and the Profiler-
>Detect duplicates command, can be used to initiate detection

50 User Manual .NET Memory Profiler


of all duplicate instances. However, in a complex snapshot this can
take a long time.

As mentioned previously, the profiler will by default only detect


trivial duplicates automatically. It is possible to change this
behavior by using the Profiler->Auto-detect duplicates
command. The available options are:
None
No duplicates will be detected automatically. Use the
Detect duplicates links or command to initiate
duplicates detection.
Only trivial
Only trivial duplicates will be detected automatically. Use
the Detect duplicates links or command to detect non-
trivial duplicates.
All
All duplicates will be detected automatically. This setting
can cause the duplicates detection of the automatic
memory analyzer to take a long time.

Disposable Types Classification and


Undisposed Instances
When presenting analysis issues regarding undisposed instances,
.NET Memory Profiler needs information about what would have
been performed if the instance was correctly disposed. This
information is provided by classifying the actions that are
performed when disposing instances of the type. The actions are
classified as:
Release resource
Disposing instances of this type might release
unmanaged resource instances.
Detach events

.NET Memory Profiler User Manual 51


Disposing instances of this type might detach event
handlers from external instances. If the external
instance has a longer lifetime than the disposable
instance, failing to dispose the disposable instance can
cause a memory leak.
Remove external references
Disposing instances of this type might remove
references to the disposable instance from external
instances. If the external instance has a longer lifetime
than the disposable instance, then failing to dispose the
disposable instance can cause a memory leak.
Dispose other instances
Disposing instances of this type might cause other
instances to be disposed.
Release COM interfaces
Disposing instances of this type might cause COM
interface wrappers (CCWs and RCWs) to be released.
Perform cleanup/exit action
Disposing instances of this type might cause some
cleanup or exit action to be performed. This action can
for instance be flushing data to a file, committing or
reverting a transaction, clearing security buffers, or
deleting temporary files.
Suppress finalization
Disposing instances of this type will suppress the
finalization of the instance (i.e.
GC.SuppressFinalize will be called).
Clear references
Disposing instances of this type might clear references
to other instances.
.NET Memory Profiler provides classifications for all disposable
types that are included in .NET Framework 2.0/3.0/3.5. The
classifications have only been partially updated for .NET
Framework 4.0 and later.
If a classification for a specific disposable type cannot be found,
.NET Memory Profiler will search for a base type with dispose
classification for. If base type classification is used, the text
(inherited) will be appended to the type when presented by the
profiler.

Ignoring Framework Issues


It is possible that the memory analyzer will present issues that are
caused by the .NET Framework itself. As they are caused by the
framework, there is often nothing that can be used to resolve them.
The only thing that can be done to remove the issues is to ignore
them. .NET Memory Profiler includes information about a set of

52 User Manual .NET Memory Profiler


known framework issues. To ignore all known framework issues,
the Ignore Framework Issues command can be used.
Additional known framework issues will be included in updates of
.NET Memory Profiler. Suggestions for issues that should be
included as framework issues can be sent to
memprofiler@scitech.se.

Held and Reachable Instances


Several views in .NET Memory Profiler present information about
held and reachable instances, e.g., the instances list under Type
details and the instance references tree. Below is an explanation of
the terms reachable and held instances.
Reachable instances includes all instances that are reachable
from a base instance, including the base instance itself.
Consequently, reachable bytes is the number of bytes used by
the reachable instances.
Held instances, on the other hand, only include instances that
are uniquely reachable from the base instance. If a reachable
instance can be reached from another root, without passing
through the base instance, then it will not be counted as reachable.
Consider the following instance graph:

In the graph above, instance #1 references two child instances,


plus some other instances. The child instances (#4 and #5) have a
reference back to their parent. This is a very common scenario in
hierarchical structures (e.g. controls in a Windows Forms
application).

.NET Memory Profiler User Manual 53


Reachable from instance #1
In the graph below, the instances that are reachable from instance
#1 have been colored green. Compare this with the next graph.

Held by instance #1
In the graph below, the instances that are held by instance #1 are
colored red.

As can be seen, instance #6 is not colored, even though it is


reachable from instance #1. The reason for this is that instance #6
is not uniquely reachable from instance #1. It can also be reached
from root #2, via instance #2, without passing through instance
#1.

54 User Manual .NET Memory Profiler


Reachable from instance #5
In the graph below, the instances that are reachable from instance
#5 have been colored green.

It can be noted that the reachable instances are the same as the
reachable instances from instance #1. This happens because
instance #5 references instance #1. If two instances have
references to each other, the reachable instances will by definition
be the same. Compare this with the next graph.
Held by instance #5
In the graph below, the instances that are held by instance #5 are
colored red.

Since instance #1 can be reached from a root without passing


through instance #5, it will not be considered to be held by
instance #5.

.NET Memory Profiler User Manual 55


From the example above, it can be seen that held instances (and
bytes) provides a better metric for the total memory usage of an
instance than the reachable instances. The reachable instances
metric will include too many instances to be meaningful in a
scenario like this parent-child relationship.
Unfortunately, none of the metrics is perfect, since the held
instances metric will not count the memory usage of shared
instances. Instance #6 in the example is not held by any instance
(except itself), since it is shared by both instance #1 and #2.

Held by a Set of Instances


The concept of held instances can be extended to sets of instances
as well. In the graph below, the instances that are held by the
instance set containing instance #1 and instance #2 are colored
red.

#6 #7 #8
#4 #5 m_parent
m_parent

m_commonData
m_data m_child1 m_commonData
m_child1
m_data

m_data2 #1 #2 #3

m_commonData

Root #1 Root #2 Root #3

It can be noticed that instance #6 is neither held by instance #1


alone, nor by instance #2 alone. However, if instance #1 and #2
are considered simultaneously, instance #6 will be held, since it is
not reachable from any root without passing through instance #1
or #2.
Information about the number of instances (and bytes) held by a
set of instances can be a useful metric of the total memory usage of
the instances.
Under the Overview page, information about held bytes for each
type and filter is presented by default. This gives a better idea
about the total memory usage of a specific type or filter.

56 User Manual .NET Memory Profiler


Instance Graph
The instance graph gives a visual overview of how a managed
instance is being used, how it is related to other instances, and,
maybe most importantly, how roots are preventing it from being
garbage collected.
It is available under the type and filters details view and type
instance details view, where it will present the instance graph for
the currently selected instances.
The graph can include all instances that are related to the selected
instance. This includes instances and roots that can reach the
selected instance, and instances that are reachable from the
selected instance. By default, only root path instances and held
instances are included in the graph, i.e. the instances and roots
that are preventing the selected instance from being garbage
collected and the instances that are uniquely reachable from the
selected instance. For more information about reachable and held
instances, see Held and Reachable Instances on page 53. For
more information about root paths in the graph, see Root Paths in
the Graph on page 60

Graph Presentation
The instance graph is presented as a directed graph, where each
instance and root is represented as a node, and the references
between the instances are represented by directed edges. The table
below presents the symbols that are used to present different types
of instances and roots.

Selected instance

Shortest root-path instance


An instance that is part of a shortest
root-path.

Reachable shortest root-path instance


An instance that is part of a shortest
root-path and it is reachable from the
selected instance.

Non-shortest root-path instance


An instance that is part of a non-
shortest root-path.

Reachable non-shortest root-path


instance
An instance that is part of a non-

.NET Memory Profiler User Manual 57


shortest root-path and it is reachable
from the selected instance.

Held instance
An instance that is held by the selected
instance.

Reachable instance
An instance that is reachable from the
selected instance, but it is not held.

Referrer instance
An instance that has a path of
references to the selected instance, but
it has not been identified as a root-
path instance.

Held referrer instance


An instance that is held by the selected
instances and it has a path of
references back to the selected
instance.

Reachable referrer instance


An instance that is reachable from the
selected instance and it has a path of
references back to the selected
instance, but it is not held.

Root
A root that is preventing the selected
instance from being garbage
collected.

The symbols can also be emphasized by adding an outline to the


graph elements.
Primary item
This outline indicates a primary or target
element of an operation. For instance,
instances that have been extracted from a
combined node will be marked as primary
instances.

Secondary item
This outline indicates a secondary element
of an operation. For instance, instances that
contain left-over instances from an expand
operation will be marked as secondary
instances.

58 User Manual .NET Memory Profiler


Highlighted path
Root paths can be highlighted using the
center or highlight root path command, or
by the graph synchronization.

Large Instance Graph Reduction


An instance graph can easily become much larger than can be
conveniently presented visually. To avoid presenting too large
graphs, .NET Memory Profiler will reduce the graph by combining
groups of instances and roots into single graph nodes. The profiler
tries to select groups so that the overall structure of the graph is
affected as little as possible. The example below shows how
instances are combined in a graph that contains a long linked list:

Original instance graph

.NET Memory Profiler User Manual 59


Instance graph with combined instances
Combined instances in the graph are indicated by using the
following three symbols:

Indicates that instances have been


combined horizontally. All
instances have the same shortest-
path distance to the selected
instance.

Indicates that instances have been


combined vertically. All instances
have different shortest-path
distance to the selected instance.

Indicates that instances have been


combined horizontally and
vertically.

Combined instances can be expanded by using the Expand


command that is available in the popup window and right-click
menu of the combined instances and combined references. The
expand options depend on how the instances and references have
been combined. Typically they include options for expanding a
specific type, a field, or just a number of instances.

Root Paths in the Graph


There are two types of root paths, shortest and non-shortest. A
shortest root path includes the minimum number of instances
from a root to the selected instance. A non-shortest root path is an
alternate, longer path, which also prevents the instance from being
garbage collected. A non-shortest path is closely related to a hot-

60 User Manual .NET Memory Profiler


path reference. Each hot-path reference and non-shortest path is
assigned a level, but for simplicity, level 1 paths are first explained.
Hot-path references

Consider the root path above. It depicts a Label instance (#433)


that is prevented from being GCed by the static field
Application._current. This graph indicates that it would be
possible to break the root path by removing the _rootViusal
reference between the App instance and the MainPage instance
(by setting the MainPage._rootVisual field to null). A
reference that breaks all root paths for an instance (like the
_rootVisual reference) is identified as a level 1 "hot-path
reference", and is colored red in the instance graph.
Non-shortest root paths
In the previous graph it also appears like it would be possible to
break the root path by removing the label2 reference between
the MainPage instance and the Label instance (by setting the
MainPage.label2 field to null). However, this is it not the case,
there are actually other, longer root paths that prevents the Label
instance from being GCed. This can be seen in the graph below.

.NET Memory Profiler User Manual 61


In this graph, non-shortest root paths at level 1 are also included.
Clearly, there exists an additional path between the MainPage
instance and the Label instance, namely a path through the Grid
used as LayoutRoot. Even if the label2 reference was removed,
the Label instance will still not be garbage collected, due to the
additional non-shortest root path.
Higher level hot-path references and non-shortest paths
The concept of hot-path references and non-shortest paths are
extended to higher levels. If it is possible to break all root paths to
an instance by removing two references from the root graph, then
these two references will be marked as hot-path references at level
2. If removing the two references reveals additional non-shortest
root paths instead, these non-shortest root paths will be marked as
level 2 non-shortest paths. This analysis then continues with
higher levels, by trying to find 3 references that can be removed to
break the root path, and then 4, and so on.
A hot-path reference at level 2 is colored orange in the instance
graph. Higher level hot-path references are presented in an
increasingly darker orange color.

62 User Manual .NET Memory Profiler


For each level the number of combinations of references will
increase substantially, which can make higher level analysis take
very long time. If the analysis takes too long, it can be cancelled
using the Cancel button at the bottom left of instance graph.

Combined Instances Graph


The instance graph available under the Type/Filter details page
will present a graph with multiple selected instances. The
instances are selected by using the Instances list, by selecting a
Shortest root path, or by selecting an Allocation stack.
Instances list
It is possible to select a single instance, multiple instances
(using Ctrl- and Shift- click), or one or more Types (when
grouping by type).
Shortest root path
When selecting a root path in the root paths browser, the
combined instances graph will include all instances that are
rooted by the root path. Note that the shortest root paths
browser only includes the root path to the closest root, but
the instances graph will include the shortest root paths to
all roots.
Allocation stack
When selecting an allocation stack in the allocation stacks
browser, the combined instances graph will include all
instances that are allocated by the selected stack, and the
shortest root paths of these instances.
If all the instances of currently selected root path or allocation
stack are not selected in the instances graph, a Sync button will be
visible. This button can be used to force the graph to be
synchronized with the root path or allocation stack.

.NET Memory Profiler User Manual 63


NOTE! To keep the complexity of the combined instances graph at
a reasonable level, the combined graph only includes shortest root
paths and held instances. It is not possible to include non-shortest
root paths, other reachable instances, or referrer instances.

Selected Instances Navigator


When more than one instance is selected for the instances graph,
and more than one graph node is needed to represent the selected
instances, then an instance navigator becomes available in the
graph toolbar (see screenshot below).

Working with the Graph


The graph is usually larger than can fit in the window. As soon as
the graph does not fit, an overview pane is visible in the lower right
corner. Within the overview pane, the active graph area is
presented as a blue rectangle. To select the part of the graph that
should be visible, click and hold down the left mouse button on the
graph window and move the graph area with the mouse. The active

64 User Manual .NET Memory Profiler


area rectangle within the overview pane can also be moved by
holding down the left mouse button.
Zooming can be performed with the mouse-wheel, or by selecting
the zoom factor in the toolbar. As soon as a the zoom factor is less
than 100%, an interactive magnifier will be activated (either a
magnifying glass or a balloon magnifier).

Instance and Reference Info Window


When the mouse is moved over a graph element, (i.e. an instance,
root, or reference), a blue arrow button will appear. Hovering
with the mouse over the button or clicking the button will bring up
the info window.

The info window will present information about the element. The
actual information presented depends on the type of the element.
For example, for a single instance element includes a subset of the

.NET Memory Profiler User Manual 65


information presented in the Type instance details view, e.g.
analysis issues, the allocation call stack, and field information. In
addition information about the
The info window also provides access to commands related to the
element, such as Show instance details and Highlight root
path. For elements that represent combined instances or roots, a
set of Expand commands are also included.
The commands in the info window are also available on the right-
click context menu. For more information about the available
commands, see Instance Graph Commands on page 68.

Defining Items to Include


The set of instances and references related to a selected instance
can be rather significant, and analyzing higher level non-shortest
root paths and hot references can be very time consuming. To
improve the performance and to reduce clutter, it is possible to
define the level of information to present in the graph. By default,
shortest-root paths and non-shortest root paths up to level two are
presented, as well as instances held by the selected instance. The
include menu can be used to select the non-shortest
root path level to include, and whether other related instances that
are not part of the root paths should be included. Related instances
that are not part of any root path, i.e. the other reachable
instances, other referrer instances, and held instances, are always
combined to reduce the graph size.
Note that a single instance can be classified as more than one type,
e.g. a reachable instance can also be a root path instance. Root
path instances always have precedence over other related
instances, so if an instance is both a root path instance and a
reachable instance, it will be presented together with the other root
paths instances, and possibly combined with other root path
instances. It will not be combined with the other reachable
instances.
If related instances like other reachable instances and other
referrer instances are included, the number of references between
them and other root path instances can become significant.
Including all these references in the graph can make the graph
harder to follow. Therefore it is possible to reduce the number of
included edges by using the command Reduce edges. If edges
are reduced, less important reference edges are not included in the
graph. However, this can also cause instance nodes to become
disconnected (see screenshot below).

66 User Manual .NET Memory Profiler


Investigating Root-paths in a Large Graph
In a large instance graph, it can be hard to locate specific root
paths. In this case the Highlight root path or Align root path
commands are useful. These commands are available from the
popup window of each instance, root, and reference in the graph,
as well as from the right click menu. When selected, it will find the
shortest root path that passes through the instance, root, or
reference, highlight the root path. If Align root path is used, the
root path instances will be aligned vertically as well. Root paths
can also be selected using the navigation buttons that are provided
on the sides of the graph.

Graph Synchronization
The instance graph is synchronized with the References,
Referenced by and Root paths views under the Type instance
details page. This is a one-way synchronization that synchronizes
changes in the other views with the graph. The following
synchronizations are performed:
Root path highlighting
When a root path is selected in the Root paths view, the
same root path is highlight in the graph
Selection tracking
When an instance is selected in the References tree or
the Referenced by tree, it is also highlighted as a
primary element in the graph (if it is included in the
graph).
Expand tracking
When an instance reference is expanded in the
References tree or the Referenced by tree, the same
instance is expanded in the graph (if it is part of a
combined instance node).

.NET Memory Profiler User Manual 67


As mentioned in the section Combined Instances Graph, the
selected instances under the Type/Filter details page are
synchronized with the selection in the Instances list, the
Shortest root paths browser, and the Allocation stacks
browser.

Instance Graph Commands


The following commands are available in the instance graph, either
in the toolbar for the graph, or in the info popup windows and
context menus.

Refresh layout Performs a full layout of the instance


graph. Operations like Expand will
only layout the affected elements to
avoid rearranging the graph too much,
which can lead to sub-optimal layout.
A full layout will consider whole graph
when performing the layout.
Reset expanded Resets the graph to its initial state,
items resetting any manually expanded
items.
Undo expand Undoes the last expand operation

Redo expand Redoes a previously undone expand


operation
Clear highlight Removes any highlights from the
graph, e.g. highlighted root paths, or
primary or secondary element
highlights.
Include This submenu is used to define the
instance to include in the graph.
Include->Non Defines the non-shortest path
shortest paths instances and references that should
be included in the graph. For more
information, see Defining Items to
Include.
Include->Held Toggles whether held instances should
instances be included in the graph. For more
information, see Defining Items to
Include.
Include->Other Toggles whether additional reachable
reachable instances should be included in the
instances graph. For more information, see
Defining Items to Include.
Include->Other Toggles whether additional referrer
referrer instances should be included in the
instances graph. For more information, see
Defining Items to Include.

68 User Manual .NET Memory Profiler


Field names Defines how field names should be
presented. The options are:
None
In node
At edge
If In node is selected, the field name
will only be presented if only a single
reference field exists.
Reduce edges Toggles whether reference edges is the
graph should be reduced. Reducing
edges will reduce the clutter, but will
not show all references. For more
information, see Defining Items to
Include.
Magnifying glass Selects the magnifying glass to be used
when the zoom factor is less than
100%. The balloon magnifier will
magnify the graph under the mouse up
to 100%. It will obscure the parts of
the underlying graph that are beneath
the magnifier but outside the
magnified area.
Balloon Selects the balloon magnifier to be
magnifier used when the zoom factor is less than
100%. The balloon magnifier will
magnify the graph under the mouse up
to 100% by stretching the graph. This
magnifier will not obscure the
underlying graph.
Zoom factor Changes the zoom factor of the
instance graph (between 50% and
100%). If the zoom factory is less than
100%, a magnifier will be active.
Align highlighted If a root path is highlighted, the
path instances that are part of the root path
will be aligned vertically.
Expand If a root path is highlighted and the
highlighted path root path contains combined nodes,
this command will expand the
combined nodes so that they only
contain instances that are part of the
root path.
Sync with other Toggles whether graph
views synchronization should be enabled or
not. For more information, see Graph
Synchronization on page 67.
Legend Shows a legend window, with a short
explanation of the graph symbols.

.NET Memory Profiler User Manual 69


Expand Only available in the info window and
context menu of nodes and edges in
the graph. Provides options for
expanding nodes that contains
combined instances or roots. The
actual options available depends on
the graph element, but typically they
include options for expanding a
specific type, a field, or just a number
of instances.
Show instance Only available in the info window and
details context menu of nodes and edges in
the graph. Shows the instance details
of the active node. If the node contains
combined instances, the details of all
instances will be shown as an instance
filter.
Highlight root Only available in the info window and
path context menu of nodes and edges in
the graph. Highlights the shortest root
path that passes through the selected
element.
Align root path Only available in the info window and
context menu of nodes and edges in
the graph. Highlights the shortest root
path that passes through the selected
element. The instances that are part of
the root path will be aligned vertically.

Guided Profiling and the Tasks Window


On the Start page, a set of profiling guides are available. The
profiling guides provide interactive step-by-step instructions that
will help you with common memory profiling tasks, such as
memory leak investigations.

70 User Manual .NET Memory Profiler


Use the Investigate links to start profiling with the help of a
guide. This will open the start guide wizard that allows the process
to profile to be selected. The start guide wizard will not give access
to other session settings, unlike the other start profiling wizards,
since the guide will initialize the appropriate settings.
Once the profiling has started, the step-by-step instructions are
presented in the Tasks window (normally to the right).

.NET Memory Profiler User Manual 71


Even though the guides are designed to be stepped through
sequentially, it is often possible to skip or repeat some steps. The
next recommended step is highlighted using bold, steps that are
not available are grayed out. A tool tip window is used to provide
additional information about the step.
A step might require user interaction (e.g. with the profiled
process); in this case the step should be clicked to inform the guide
that the interaction has been performed. In other cases clicking the
step will actually perform a profiler action (e.g. Collect base
snapshot). The info window of the step will tell the actual
meaning of clicking the step.

Tasks Window
The Tasks window is mainly used to provide access to the profiling
guides.
If profiling has been started using a guide, the selected guide is
automatically expanded and activated in the Tasks window. Other
available guides are also presented, but they are collapsed and
inactive. A profiling guide can be activated by using the drop-down
button to expand it. This will stop any active guide, and activate
the new one. Only a single guide can be active at the time.
Above the guides, quick access to common profiling commands is
available. The commands include: Collect snapshot, Stop
profiling, and Show real-time data.

Instance and Allocation Filters


The instance and allocation filters are used to present information
about instances and allocations that share a common
characteristic, e.g. all allocations and instances that are derived
from a specific type, all instances that are directly referenced by a
root, or all allocations performed by a specific method.
Additionally, by combining filters, very specialized information is
available, e.g. all instances of a specific type that are directly
referenced by a root and allocated by methods in a specific
assembly.
Instance and allocation filters are presented below the Types and
Resources list on the Overview page. The information
presented for each filter is similar to the information presented for
a Type. However, depending on the filter, only a subset of the
information might be available. For instance, a filter that depends
on the state of specific instances (e.g. the Directly rooted instances
filter), cannot provide information about allocations per second.

72 User Manual .NET Memory Profiler


Initially, there is a set of predefined filters included in the filters
list. To get more detailed information about the instances and
allocations that are included by the filter, you can double-click the
filter to bring up the Filter details view. This details view is the
same as the Type details view, with the addition that the
instances list can include instances of several types. For more
information, see Type/Resource/Filter Details Page on page 119.
New filters are easily created on-the-fly by using the Show
details command that is available in many locations in the
snapshot views. For example, clicking Show details on an
assembly in the methods view will create a filter that includes
information about all allocations performed by that assembly.

A filter can also be created for the instances that are part of an
analysis issue by using the Show details link next to the issue
title.

.NET Memory Profiler User Manual 73


Another type of filter is the derived from filter. It will include all
instances and allocations of types that are derived from a common
base type. To define a derived from filter, a type needs to be
selected in the Type details view. After the type has been selected,
the Show derived button can be used to create the filter.

NOTE. It is possible to enter a Type name in the type name list


under the Type details view, even if it is not included among the
types in the Overview types list. For instance, a base class that
has had no allocations will not be included in the Overview list, but
it still possible to use it as a base type for the derived from filter
(see screenshots below).

74 User Manual .NET Memory Profiler


Snapshot Filters
An instance and allocation filter can also be used as a snapshot
filter. A snapshot filter is used as a base filter for all snapshot
views: Overview, Type/Filter details, Instance details, and
Call stacks/Methods.

An instance and allocation filter is used as a snapshot filter by


clicking the Use as snapshot filter button in the Filter details
view. After clicking Use as snapshot filter, an indication of the
used filter will be shown at the top of the profiler widow, and the
snapshot views will only include information about instances and
allocations included by the filter (note this only applies to
managed instances, native resource instances are not affected by
the filter).

To remove the snapshot filter, the remove snapshot filter button


can be used.

Predefined Filters
In addition to the filters that can be created by Show details and
Show derived there is a set of predefined filters. Most of them are
included in the filters list on the Overview page. The Manage filters
command can be used to define the filters that should be included
on the Overview page. For more information, see Saving and
Managing Filters on page 76.
The following predefined filters are available:
Directly rooted instances
All instances and allocations

.NET Memory Profiler User Manual 75


Array instances and allocations
Boxed instances and allocations
Gen #0 instances (not included by default)
Gen #1 instances (not included by default)
Gen #2 instances
Large instances
Undisposed instances (not included by default)
Disposed instances
Potential memory leak instances
Instances and allocations of types with source
Instances allocated by methods with source
Event handler instances and allocations
Delegate instances and allocations

Saving and Managing Filters


Filters that are created on-the-fly are not included in the Filters
list on the Overview page by default. In order for the filter to be
included in the list, it has to be saved using the Save filter button.
This will bring up the Save Filter window, which can be used to
assign a name to the filter and define how it should be saved. The
filter can be saved in:
Default filters
The filter will be available in all sessions.
Profiler project: <Project name>
The filter will be available in all sessions that are
included in the project.
Current session
The filter will only be available in the current session.

The filters list can be managed by using the Manage filters


command. This will bring up a window where you can remove
filters, add predefined filters, or reset the filters list to the default.
It also provides the possibility to change the location of the filters
issues, e.g. change Current session to Default filters.
The top part of this window is a table containing the current filters.
The actual filters included depend on the Show filters setting
(see below).
The following information is presented in the ignored issues table:
Filter
This column shows the name of the filter.

76 User Manual .NET Memory Profiler


Saved in
This column shows where the filter is stored. This is the
only column that can be modified. To change the
location used the dropdown list to select any of:
Session: <session name>, Project: <project
name>,or Default filters.

Show ignored issues


This dropdown list defines what filters should be presented in the
filters table. The available options are:
(All filters)
This option will include all filters in all loaded or active
sessions, all issues in all loaded profiler projects, and
the default ignored issues.
(Combined session filters)
This option will include all filters that will be included
in the current session. It is a combination of the filters
in the current session, the filters in the associated
project, and the default filters.
Default filters
This option will only include the filters that are
included in all sessions.
Session: <session name>
This option will only include filters from the selected
session. There will be one session item available for
each loaded or active session.
Project: <project name>
This option will only include filters in the selected
profiler project. There will be one project item available
for each loaded project.

Remove filter(s)
This button is used to remove the filters selected in the filters
table.

Reset to default filters


This button is used to remove any user modifications of the filters,
and restore the filters from the .NET Memory Profiler installation.

Add predefined filters


The Add predefined filters list used to add additional predefined
filters to the filters list, or to re-add a previously removed pre-
defined filter. To add predefined filters, select one or more filters
to add, use the Add filter to drop-down list to select where the filter

.NET Memory Profiler User Manual 77


should be stored, and the click the Add filters button. For more
information about the predefined filters, see Predefined Filters
on page 75.

Peak Snapshots

Professional and The peak memory usage of an application is a useful metric to


Enterprise only find out the memory requirements of the application. Peak
memory information is also available in the real-time view,
which will present the total number of bytes used by managed
instances. However, no details will be provided about the actual
memory usage at the time of the peak.
Using peak snapshots, much more detailed information about the
peak memory usage will be available. If peak snapshots are
enabled, the profiler will, at each garbage collection, check whether
the total managed memory usage has reached a peak. If a peak has
been reached, all information about the managed memory usage,
and unmanaged resources usage, is stored temporarily. When the
profiling session is ended, the information about the highest peak
is collected as a snapshot by the profiler. The peak snapshot
includes additional information, such as the total number of
instances and bytes before the garbage collection, the number of
instances and bytes collected, and the number of instances and
bytes that are unreachable but still exist on the GC heap. This
information is presented as additional columns and fields on the
Overview page and the Type details page.
The following toolbar commands are available to control peak
snapshot collection:
Enable peak Enables and disables peak snapshot
snapshot collection. When enabled, temporary
collection snapshot information will be stored
each time a new peak has been
detected and a peak snapshot will be
collected when the session ends.
Collect peak Collects the current peak snapshot. If a
snapshot higher peak is detected after the
current peak has been collected, an
additional peak snapshot will be
collected when the session ends.
Reset peak Resets the current peak snapshot. New
peak snapshot information will be
collected at the next garbage
collection.

As mentioned previously, peak snapshot collection can be used to


get information about the total memory needed by an application,
simply by running the application under the profiler and then
investigate the peak snapshot. It can also be used to investigate the

78 User Manual .NET Memory Profiler


memory usage of a certain task, e.g. opening and closing a
document:
1. Reset any existing peak information using Reset peak
snapshot.
2. Perform the task, e.g. opening and closing a document.
3. Collect the resulting peak snapshot using Collect peak
snapshot.
The profiler guides Investigate program peak memory usage and
Investigate operation peak memory usage can be used to get
step-by-step instructions on to analyze peak memory usage.

Profiler Projects
Professional and A .NET Memory Profiler project is used to define the process to
Enterprise only profile and to specify the session settings, making it easier to
use different settings for different applications. It also keeps
track of session files related to the project, allowing you to
compare snapshots between different sessions. This is
particularly useful when doing automated testing and you want
to check whether the memory usage has changed between
different builds of a program.
Profiler projects are created using the New Profiler project
command and loaded using the Open->Profiler Project
command. For more information see the How to topic Create
or Load a Profiler Project on page 22.
All created and loaded profiler projects are included in the
Profiler Projects Explorer window.

.NET Memory Profiler User Manual 79


If not visible, the Profiler Projects Explorer window can be
shown using the Profiler Projects Explorer command under
the View menu (or the View->Other Windows menu in Visual
Studio 2005).
It is possible to set one of the projects in the projects explorer to
active using the Set Project as Active command. When a
project is active it is possible to start a new profiling session based
on the settings in the project. For more information see the How
to topic Start Profiling using a Profiler Project on page 23. To
remove the active state of a project, click the Remove Project
as Active command.
The set of projects in the projects explorer and the active project
are saved when the profiler exits, and it is reloaded the next time
.NET Memory Profiler is run. When running .NET Memory
Profiler under Visual Studio, the information about profiler
projects is saved in the user settings of the active solution.
To unload a project from the projects explorer, use the Remove
command in the explorer window.

Comparing Project Snapshots


The profiler projects explorer can be used to compare any two
snapshots that are included in any of sessions in the loaded
projects. For more information, see the How to topic Compare
Snapshots using the Profiler Projects Explorer on page 24.

Adding and Removing Sessions


Each project contains a list of associated session files. Session files
are automatically added to this list when the sessions are started
using the project. External session files can also be manually added
to a project, making it possible to group related session files in a
project.
Snapshots from different sessions can only be compared with each
other using the projects explorer. Adding external sessions to a
project makes it possible to compare snapshots from any two
sessions.

A session is added to a project using the Add Session


command in the projects explorer. The Remove command in the
projects explorer window can be used to remove a session from a
project.

Remote Profiling
Enterprise only Remote profiling allows you to use a development computer to
profile a process running on a computer where you do not want

80 User Manual .NET Memory Profiler


to or cannot install the full profiler. It is available for all
profiling types, except memory dump import.
Remote profiling is started the same way as local profiling, using
one of the start profiling commands, e.g. Profile application,
Profile ASP.NET, or Attach to process. When selecting the
application or process to profile, there is a field available where the
Machine name can be selected.

By default no remote machine is selected, and profiling will be


performed on the local machine. A remote machine can be entered
or selected using the drop-down list. The Find button can be
used to locate a machine on the local network.
After a remote machine connection has been selected, the profiler
will check that the current user has permissions to perform
profiling on the remote computer. If not, the profiler will prompt
for new credentials. It is also possible to change the credentials
manually by clicking Change user. For more information, see
Remote Profiling Security on page 82.
If a remote machine has been selected, the Browse button will
bring up a file or folder browser for the remote machine. If
profiling a service or a Windows Store app, or attaching to process,
the selection list will present services, apps, and processes on the
remote machine.
To provide remote profiling access on the remote computer, the
NmpCore tool is used. This tool is included in the installation
folder of the profiler and can also be downloaded from
http://memprofiler.com/nmpcore.aspx.
The NmpCore tool is started on the remote computer in remote
profiling mode by using the command line argument
"/remoteagent" (short form "/ra") on the remote computer:
NmpCore /remoteagent

.NET Memory Profiler User Manual 81


By default the port 35650 is used for remote profiling. This can be
overridden by using the argument "/remoteagentport" (short form
/rap"). For example:
NmpCore /ra /rap:25000

NOTE! If the remote profiling port is overridden, the port number


must be included in the machine name, after a :. For instance,

Remote Profiling Security


The user that performs remote profiling must be the same as the
one that started NmpCore on the remote computer, or the user
must be an administrator on the remote computer. If the user
running the full profiler does not have remote profiling access, the
Authentication Required window is shown.

By the default the profiler tries to use the credentials of the current
Windows account, but this window provides the possibility to
enter the credentials of an alternate user. To enter the name of a
user on a separate domain, use the format <domain>\<user
name>.

82 User Manual .NET Memory Profiler


The .NET Memory Profiler Window
The .NET Memory Profiler window contains a menu, a toolbar, a
status bar, and one or more session documents.

The menu and the toolbar provide access to all the available
commands.
Each session document includes a process and snapshot selector at
the top and a set of tab pages. The tab pages are used to present
different views of the contents of the GC heap, both snapshot
information and real-time information. Additionally, information
about call stacks and native memory is presented. The available
tab pages are:
Start
The Start page provides quick access to common
tasks, such as starting a profiling session, starting
guided profiling, and opening a previous session
file. It will be hidden as soon as an active session is
started or a session is loaded. Use the New session
command to get back to the Start page.
Overview (For more information, see Overview Page on
page 113.)
Type/Resource/Filter details (For more information,
see Type/Resource/Filter Details Page on page 119.)
Instance details (For more information, see Instance
Details Page on page 128.)
Call stacks/methods (For more information, see Call
Stacks/Methods Page on page 136.)
Native memory (For more information, see Native
Memory Page on page 146.)

.NET Memory Profiler User Manual 83


Real-time (For more information, see Real-Time Page
on page 151.)
Additionally, a Tasks tool window is available when there is an
active profiling session. The Tasks window provides access to the
profiling guides and common profiling commands. For more
information, see Guided Profiling and the Tasks Window on page
70.

NOTE! Multiple session documents are only available in the


Enterprise edition. In the Professional and Standard edition it is
only possible to work with one session at the time.

Snapshot and Process Dropdown Lists


There are two dropdown lists that are used to select the snapshots
to be presented by the profiler.
Enterprise only If more than one process is being profiled in the same session,
then a dropdown list for process selection is also available
(profiling more than one process per session is only available in
the Enterprise edition). The process selector is used to select
from which process the memory usage data should be
presented.
The Show snapshot list is used to select the primary snapshot.
The data about live instances are retrieved from this snapshot, and
thus all instances presented in the Type/Resource/Filter
details page and the Instance details page are part of this
snapshot. This snapshot is referred to as the primary snapshot in
this manual. This list contains all snapshots that have been saved.
The Comparison snapshot list is used to select the snapshot to
be used as a reference snapshot. All data that are compared against
some other data use this snapshot for comparison. This includes:
New instances (normal and disposed)
Removed instances (normal and disposed)
Delta instances (normal, disposed, undisposed, and
memory leaks)
New, removed, and delta bytes
Allocs/sec (or Allocs) and Bytes/sec (or Bytes alloced)
Allocs/sec (or Allocs) in generation #0, #1, #2 and
Large heap
This list always contains at least one entry called Empty. This is
an empty snapshot that can be used when no comparison snapshot
is wanted. This allows you to view all allocations that have been
performed since the start of the profiler session.

84 User Manual .NET Memory Profiler


NOTE! The snapshots presented in the Comparison snapshot
list have always been collected prior to the snapshot selected in
the Show snapshot list.

The snapshot selected using the Comparison snapshot


dropdown list is referred to as the comparison snapshot in this
manual.
This document also uses the term between snapshots, which
refers to the allocations and memory usage changes that have
occurred between the snapshot selected in the Show snapshot
list and the snapshot selected in the Comparison snapshot list.

Runtimes and AppDomains Selector


The Runtimes and AppDomains selector is only visible when
AppDomains tracking has been enabled or when the profiled
process contains more than one .NET runtime.

This selector is used to select the runtime and/or AppDomain that


should be included when presenting snapshot data.
The selector is made available by clicking
Runtimes/AppDomains. This will show two additional
dropdown lists:
Runtime
This list is used to select the active runtime. Only
allocations that have been performed in the selected
runtime will be included in the snapshot views. To
include allocations from all runtimes, the (all) entry
should be selected.
AppDomain
This list is used to select the active AppDomain. Only
allocations that have been performed in the selected
AppDomain will be included in the snapshot views. To
include allocations from all AppDomains, the (all)
entry should be selected.
The list includes all AppDomains that exist, or have
existed, in the profiled process at the time of the
selected snapshot. AppDomains that have no memory
information between the selected snapshot and the
comparison snapshot (i.e., no instances and no
allocations) will be greyed out in the list.
For more information about the AppDomains tracker, see
AppDomains Tracker" on page 176.

.NET Memory Profiler User Manual 85


NOTE! Using the Runtimes and AppDomains selector will only
affect the snapshots views and the real-time view. The Native
memory view is not affected by the selector.

Commands
Commands on the File menu:

Clear session Prepares the active session document


for a new profiling session. Will
unload any current session and show
the Start page.
New session Creates a new empty session
(Enterprise only) document and shows the Start page.
New profiler Starts a wizard that allows you to
project create a new profiler project. For more
(Professional and information, see Profiler Projects on
Enterprise only)
page 79 and the How to topic
Create or Load a Profiler Project on
page 22.
Open->Profiler Opens a profiler project and includes it
project in the projects explorer window. For
(Professional and more information, see Profiler
Enterprise only)
Projects on page 79 and the How
to topic Create or Load a Profiler
Project on page 22.
Open->Session Opens a previously saved session file.
For more information, see Work with
a Previously Saved Session on page
15.
Save session as Saves the current profiler session to a
session file. Allows you to select which
snapshots to include in the session file.
Save Saves the current profiler session to a
session file.
Save project Saves the project that is currently
(Professional and selected in the projects explorer.
Enterprise only)
Save project as Saves the project that is currently
(Professional and selected in the projects explorer to a
Enterprise only) new file.
Profile Starts a wizard that helps you profile a
application stand-alone application. For more
information, see Start Profiling an
Application on page 4.

86 User Manual .NET Memory Profiler


Profile WPF Starts profiling a WPF browser
browser application with the help of a wizard.
application For more information, see Start
Profiling a WPF Browser Application
on page 9.
Profile Windows Starts profiling a Windows Store App
Store App with the help of a wizard. For more
information, see Start Profiling a
Windows Store App on page 5.
Profile ASP.NET Starts a wizard that helps you profile
an ASP.NET application. For more
information, see Start Profiling
ASP.NET on page 4.
Profile Silverlight Start profiling a Silverlight application
application with the help of a wizard. For more
information, see Start Profiling a
Silverlight Application on page 8.
Profile Windows Starts a wizard that allows you to
service profile a Windows Service. For more
information, see Start Profiling a
Windows Service on page 9.
Attach to process Starts a wizard that allows you to
(Professional and attach the profiler to a running .NET
Enterprise only) process. For more information, see
Attach to a Process on page 20.
Import memory Starts a wizard that allows you to
dump import memory dump files as heap
(Professional and snapshots. For more information, see
Enterprise only)
Import Memory Dump Files on page
21.
Recent profiled Contains a list of recently profiled
applications applications, allowing you to quickly
select an application to profile. The
selection also includes the program
arguments of the application.
Recent sessions Contains a list of recently opened
profiler session files, allowing you to
quickly open a previous session file.
Exit Exits .NET Memory Profiler.

Commands on the Edit menu:


Copy Copies data from the selected item in
the currently selected control to the
clipboard. For more information, see
Copying Data to the Clipboard on
page 93.
Copy All Copies all data from the currently
selected control to the clipboard. For
more information, see Copying Data
to the Clipboard on page 93.

.NET Memory Profiler User Manual 87


Commands on the View menu:
Show allocs and This command affects all columns and
bytes per second fields that present the number of
allocations performed and bytes
allocated. If this command is checked
then the values of those fields and
columns will be divided by the elapsed
time between the snapshots.
Otherwise, the actual allocation- and
byte-count will be presented.
Show heap This command affects all columns and
utilization as fields that present information about
percent the heap utilization. If this command
is checked, those fields and numbers
will be presented as a percentage of
the total number of allocations
performed between snapshots.
Otherwise the way they are presented
is determined by the Show Allocs
and Bytes per Second setting. This
command is only available if heap
utilization tracking is enabled. For
more information, see Heap
Utilization Tracker on page 172.
Show [Field set] Allows you to select how the heap
information should be presented. It
will affect which columns are shown in
the tables and how the fields in the
info panels are presented. For more
information, see Field Sets on page
92.
Back Steps back to the previously shown
details information. This can, for
instance, be useful if you want to look
at the details of a referrer of an
instance, and then you want to get
back to the original instance.
Forward Steps forward through details
information previously left using
Back.
Show failed If at least one memory assertion has
memory failed, this command will bring up a
assertions dialog that allows you to view
information about the failed memory
assertions.

88 User Manual .NET Memory Profiler


Show instance Shows details about the selected
details instance or function. If the selected
- item is an instance, the instance
Show source details page will be shown. If the
selected item is a method (in a call
stack), the profiler is running within
Visual Studio and source file
information is available, then this
command will be named Show
source and will show the source of
the method when selected.
Show Shows details about the type or
Type/Resource resource of the selected item.
details
Call stack Defines which functions/methods
functions should be included when viewing call
stacks. The available options are:
Source, Publically visible, and All.
Profiler projects Shows the Profiler Projects Explorer
explorer window. For more information, see
(Professional and Profiler Projects on page 79.
Enterprise only)
Session Property If the main profiler window is active
Pages and contains an active session, then
Project Property the Session Property Pages dialog is
Pages shown. If a profiler project is selected
(Professional and in the profiler projects explorer, then
Enterprise only) the Project Property Pages dialog is
shown. For more information, see
Session Settings on page 98.
Show conditional Enables or disables conditional
formatting formatting in the Overview page.
Conditional formatting indicates how
a presented cell value relates to the
total (or max) value of a column, and
whether the value has increased or
decreased since the comparison
snapshot.
Use totals for Determines if the total value of a
conditional column should be used for conditional
formatting formatting. If not selected, the
maximum value is used instead.
Layout->Column Opens the column chooser window.
chooser For more information, see Column
Layout and Customization on page
95.
Layout->Auto- Toggles auto-adjustment of table
adjust column columns. For more information, see
widths Column Layout and Customization
on page 95.

.NET Memory Profiler User Manual 89


Layout->Reset Resets the layout of columns and tool
layout windows. For more information, see
Column Layout and Customization
on page 95.

Commands on the Profiler menu:


Start using Starts profiling using the settings from
profiler project the currently active profiler project.
(Professional and For more information, see Profiler
Enterprise only)
Projects on page 79 and the How
to topic Start Profiling using a
Profiler Project on page 23.
Start Restarts a profiler session. This
command is only available after an
active session has been stopped.
Stop Stops the currently active profiler
session.
Collect Heap Collects a snapshot of the GC heap and
Snapshot native memory. The results will be
presented under the snapshot pages.
Collect Gen #0 Collects a snapshot of the GC heap and
Heap Snapshot native memory by only doing a
generation #0 garbage collect. This
command is only available if heap
utilization tracking or low-impact
profiling is enabled. For more
information, see Heap Utilization
Tracker on page 172.
Collect peak Collects the current peak snapshot. If a
snapshot higher peak is detected after the
(Professional and current peak has been collected, an
Enterprise only)
additional peak snapshot will be
collected when the session ends. For
more information, see Peak
Snapshots on page 78.
Reset peak Resets the current peak snapshot. New
(Professional and peak snapshot information will be
Enterprise only) collected at the next garbage
collection. For more information, see
Peak Snapshots on page 78.
Track peak Enables and disables peak snapshot
snapshots collection. When enabled, temporary
(Professional and snapshot information will be stored
Enterprise only)
each time a new peak has been
detected and a peak snapshot will be
collected when the session ends. For
more information, see Peak
Snapshots on page 78.

90 User Manual .NET Memory Profiler


Manage ignored Opens the Ignored Analysis Issue
analysis issues window, which can be used to view
and modify the ignored analysis
issues. For more information, see
Modifying Ignored Issues on page
37.
Ignore Ignores analysis issues that are caused
framework issues by the .NET Framework. For more
information, see Ignoring Framework
Issues on page 52.
Auto-detect Defines how duplicates should be
duplicates automatically detected by the memory
analyser. The options are: None,
Only trivial and All. For more
information, see Duplicate Instances
Detection on page 47.
Detect duplicates Starts investigation of all duplicate
instances. For more information, see
Duplicate Instances Detection on
page 47.
Manage filters Opens the Manage filters window. For
more information, see Saving and
Managing Filters on page 76.
Rename Renames a previously saved snapshot.
snapshot

Commands on the Tools menu:


Options Opens the Default Property Pages
dialog. For more information, see
Session Settings on page 98.

Commands on the Help menu:


Contents Opens a help window and shows the
contents of the help.
.NET Memory Opens a help window showing the
Profiler API .NET Memory Profiler API reference.
reference
Show PDF Opens Acrobat Reader (if installed)
manual and shows the manual.
View license Shows the license information
information window. This window allows you to
view and modify the license
information.
About Shows information about .NET
Memory Profiler.

Status Bar

.NET Memory Profiler User Manual 91


The status bar indicates whether a filter has been applied in the
Overview page and shows the total number of live instances in the
selected heap snapshot and the total number of bytes occupied by
the live instances. The number inside the parentheses shows the
change between the selected snapshot and the comparison
snapshot. The status bar also shows the number of bytes used by
collected instance data.

Field Sets
The Show [Field set] command in the toolbar or menu allows
you to select how information should be presented.
A field set defines which columns are included in the types list
(snapshot and real time), how call stacks and root paths can be
sorted, and how the fields are presented in the info panels.
Four different sets are available:
Standard
The information presented using this set consists of the
basic information about instances, e.g. number of
instances, instance sizes and the number of allocations
performed.
This is the only field set that is available when attaching
to a process or when comparing snapshots from
different sessions.
Dispose Info
This field set should be used to present information
collected by the dispose tracker. When using this set,
the instance size and allocation information presented
by the standard set is replaced with information about
disposed and undisposed instances. This set is only
available if the dispose tracker is enabled. For more
information, see Dispose Tracker on page 169.
Heap Utilization
This field set is used to present information about the
heap utilization. When using this set, the instance size
information presented by the standard set is replaced
by information about the distribution of allocations
over the different GC heaps (generation #0, #1, #2 and
the large heap). For more information, see Heap
Utilization Tracker on page 172.
Memory Leaks
This field set is only available if a memory assertion has
failed. It is used to present information about instances
that have been identified as potential memory leaks by
a memory assertion. When using this set, the instance
size and allocation information presented by the
standard set are replaced with information about the
potential memory leak instances.

92 User Manual .NET Memory Profiler


Info Panel

Info panels are used to present information about an item. The


item can be a type, an unmanaged resource, an instance, a root
path or an allocation call stack.
An info panel presents all information that is available for the
item, but the way it presents the information is dependent on the
selected field set. If the memory analyser has found any issues for
the item, these issues will also be presented in the info panel.
The panel consists of two parts; the top part presents the
information most closely related to the selected field set and, if any
analysis issue has been found, the first analysis issue. The bottom
part presents all the remaining information. The top part is always
visible, whereas the bottom one is usually hidden. To view the
bottom part, use the mouse to place the pointer over the panel.
You can also pin the panel by clicking the pin button. This will
make the info panel always fully visible.
If not pinned, the bottom part will auto hide as soon as the mouse
is moved out of the panel.

Context Menus

Context menus are available for most controls in the profiler by


clicking the right mouse button or pressing the context menu
button. The context menus for the different tables allow you to
copy data to the clipboard and show details or source for the
selected item. The context menus for the info panels and the native
memory tree allow you to copy data to the clipboard.

Copying Data to the Clipboard


All data presented about a snapshot can be copied to the clipboard
using the Copy and Copy All commands. The Copy command is
available for all tables and info panels.

.NET Memory Profiler User Manual 93


Data in tables containing root paths and allocation stacks
can only be copied completely to the clipboard using the
Copy command.
Data in tables containing types, resources, instances and
methods can be copied completely or partially to the
clipboard. By using the Copy All command, all data in the
table are copied to the clipboard. If the Copy command is
used, only the selected items are copied.

Fast Column Filter


Most tables in the profiler contain a column filter in the top row
that can be used to quickly filter the entries presented in the table.
It is possible to filter entries based on text columns, such as the
Namespace/System and Name/Resource columns under the
Overview page. It is also possible to filter entries based on state
columns, such as the Unmanaged resource/Managed type
column, or the New, Disposed and Memory leak columns
under the Type/Resource/Filter details page. A text column
filter is defined by simply entering the text in the edit control
above the column. The filter is updated at every key press. State
column filters are defined by simply clicking the edit field above
the column to toggle the filter state.

Navigating Types, Resources, Filters, and


Instances
In the Type/Resource/Filter details view and the Instance details
view, there are navigation buttons available at the top right. These
buttons can be used to navigate through the items that were active
when showing the details.
If several items were selected when showing the details (e.g., by
right-clicking and selecting Show instance details), then all
selected items will be included in the navigation. If only one item
was selected in a list when showing details, all items in the list will
be included in the navigation.
This is a convenient way of investigating items from a filtered list.
For instance, to investigate all new instances of a type perform the
following:

94 User Manual .NET Memory Profiler


1. Show the details of the type being investigated.
2. Use the top row filter in the Instances list to only show new
instances.
3. Double click on any instance in the list.
4. The navigation buttons in the Instance details view can
now be used to navigate all new instances of the type.

Column Layout and Customization


For most of the tables used in the profiler, it is possible to
customize the layout and choose the columns that should be
included (all columns are not included by default).
The customization is accessed by using the commands in the
View->Layout menu or by using the context menu for the
column headers. The available commands are described below.
Some customization can also be performed by using the mouse
directly on the columns. It is possible to change the size of the
column, rearrange the order of the columns, or remove a column
by using drag and drop on the column headers. Sorting is defined
by clicking the column headers; to sort on multiple columns the
Shift or Ctrl key can be used.

Column Chooser
This command brings up the column Customization window.
Using this window it is possible to drag and drop columns (and
bands) to and from the column header.

.NET Memory Profiler User Manual 95


It is also possible to remove columns by simply dragging them
away from the column header.

Auto-adjust Column Widths


This command toggles whether the column widths should be
adjusted to fit the table width exactly, or if the columns can be
sized freely. If the columns widths are not automatically adjusted,
a horizontal scroll bar will be included when necessary, and the
most important columns will be pinned to the left side of the table.

Reset layout
This command can be used to restore the layout to the default
layout defined in the .NET Memory Profiler installation. This will
affect all column layouts, and the positioning of tool windows like
the Project explorer.

Preferences
The Preferences page is used to edit settings related to the user
interface of .NET Memory Profiler. The preferences are edited by
clicking Options under the Tools menu. This will bring up the
Options dialog, which is used to edit preferences and default
session settings. For more information about session settings, see
the next section.
Field values presentation style
This setting indicates how field values should be presented in the
Instance details view. The available options are:
Visual Studio

96 User Manual .NET Memory Profiler


Fields are presented in a hierarchical way, grouped by
the type they are defined in. This style is modelled after
the Visual Studio style of presenting field values.
Flat
Fields are presented as they are declared in the
metadata, with the top-level type fields first.
For more information about field value presentation, see Field
values on page 131.
Instance graph animation
The instance graph makes heavy use of animations, mainly to
make it easier for the user to see how the graph changes due to an
operation. However, the animation is very graphics intensive, and
is often not suitable when running on a remote desktop. The
Instance graph animation setting is used to define when instance
graph animation is allowed. The available options are:
Always
The graph is always animated.
When not running under remote desktop
The graph is only animated when the profiler is run on
a normal desktop; if a remote desktop is used, no
animations will be performed.
Never
The graph is never animated.
Always run AnyCPU applications as 32-bit when Debug
profiling
This option is only available when running within Visual Studio.
When debugging a 64-bit process Visual Studio will use the remote
debugger and this will limit the functionality of debug profiling. If
possible it is recommended that debug profiling is performed on
32-bit processes. Selecting this option will cause applications
targeting AnyCPU to be run as 32-bit, even on a 64-bit system.

.NET Memory Profiler User Manual 97


Symbol File Locations

The Symbol File Locations page is used to define how native


symbol files should be located. The symbol files are needed when
performing native stack walks. For more information about native
stacks, see Call Stacks Settings Page" on page 111.
Retrieve debug symbols from the Microsoft symbol store
This option allows debug symbols to be loaded from the Microsoft
symbol store. Unless the Microsoft symbols are downloaded and
installed manually, it is recommended that this option is enabled,
as that will make sure that the native stack walker can investigate
frames within the OS and .NET runtime.
Cache files from symbol store in this directory
This setting specifies the folder where the downloaded symbol files
should be cached. If no folder is specified, they will be cached in
the .NET Memory Profiler user data folder.
Additional symbols file locations
This list can be used to specify additional locations for symbols
files. To add a new a folder, click on the top row and use the
button to browse for the folder. Folders can be removed using the
button.

Session Settings
When a new profiling session is started, the settings for the session
are retrieved either from the associated project or from the default
settings if the session is not associated with a project. An active

98 User Manual .NET Memory Profiler


session keeps its own copy of the settings, so changing the project
or default settings will not affect an active session.
Default settings are edited using the Options dialog
under the Tool menu. These settings are used for new
sessions that are started without being associated with
a profiler project.
Project settings that apply to all sessions that are
started using a project are edited by selecting the
project node in the projects explorer and clicking the
Project Property Pages command in the projects
explorer or under the View menu.
Settings for an active session can be viewed by selecting
the profiler window and clicking the Session
Property Pages command under the View menu.
The settings are viewed and edited using a property pages dialog.
The dialog contains the following pages:
Profiling Level
(read-only for active sessions)
Instance Tracking
(read-only for active sessions)
General
(read-only for active sessions)
Launch
(not included when editing the default settings, read-
only for active sessions)
Snapshots
Session File
Real-time
(read-only for active sessions)
Memory Leak
Instance Data Collection
Call Stacks
(read-only for active sessions)

.NET Memory Profiler User Manual 99


Profiling Level Settings Page

The profiling levels are used to easily define session setting, based
on the amount of information to collect from the profiled
application versus the performance of the profiler. The Medium
profiling provides a good balance between the amount of data
collected and the performance impact of the profiler. When
profiling a very complex and memory consuming application, the
Low or Very low level might be more appropriate, as the memory
and performance overhead is much lower. To get full memory
information, including heap utilization, use the High level.
The profiling level is actually not a session setting itself, changing
the profiling level will just initialize a set of other session settings,
namely: Instance tracking level, Enable dispose tracker,
Collect allocation call stacks, Collect real-time data,
Enable heap utilization tracking, and Disable inlining. For
more information about these settings, see Instance Tracking
Settings Page on page 101 and General Settings Page on page
102.
The following levels are available:
Very low
No instance tracking, no dispose tracker, no allocation
call stacks collection, no real-time date, no heap
utilization, inlining not disabled.
Low
Limited instance tracking, no dispose tracker, limited
allocation call stacks collection (no instance specific call
stacks), limited real-time data (no total instances
information, just allocs/sec and live instances
information), no heap utilization.
Medium
Full instance tracking, dispose tracker enabled, full
allocation call stack information, real-time data
collection, no heap utilization.
High
Full instance tracking, dispose tracker enabled, full
allocation call stack information, real-time data
collection, heap utilization tracking enabled.

100 User Manual .NET Memory Profiler


Instance Tracking Settings Page

The instance tracking level defines how managed instances should


be tracked. In order to record instance specific data, such as
allocation call stacks, the profiler needs to track the instances as
they are moved in memory by the garbage collector. This tracking
consumes significant amounts of memory and will affect the
performance of the profiled process. However, unless this causes a
serious memory or performance problem, it is still recommended
that full instance tracking is enabled. If there is a serious memory
or performance problem, the instance tracking level can be
lowered to mitigate the problem. The following levels are available:
Full
The profiler will track full instance information as the
instances are moved by the garbage collector. If an
instance exists in multiple snapshots, it will keep its
instance number.
Limited
The profiler will only keep information about new and
removed instances as the instances are moved by the
garbage collector. Instance numbers will be reassigned
for each snapshot.
None
The profiler will not track instances as they are moved
by the garbage collector. No information about new and
removed instance will be available, only accumulated
delta values. Instance numbers will be reassigned for
each snapshot.

.NET Memory Profiler User Manual 101


General Settings Page

Collect allocation call stacks


This setting enables allocation call stack collection. Allocation call
stacks provide essential information, so unless there is a specific
reason, such as performance or memory problems; it is
recommended that allocation call stacks are collected.
Additional call stacks settings are available under the Call stacks
page. For more information, see Call Stacks Settings Page on
page 111.
Collect real-time data
This setting allows real-time collection to be enabled. If real-time
collection is enabled, the Real-time page on the main form will
become available, and managed memory information will be
presented in real time on that page. If real-time collection is not
enabled, the Real-time page will be hidden.
Additional real-time data settings are available under the Real-
time page. For more information, see Real-time Settings Page on
page 108.
Enable dispose tracker
This setting enables the dispose tracker, which allows information
about disposable instances to be collected. Code will be injected in
certain methods to allow the instances to be tracked. However, the
performance penalty is very low and no additional memory is used,
so it is recommended that the dispose tracker is enabled.

NOTE! The dispose tracker cannot be enabled unless full instance


tracking is enabled.

102 User Manual .NET Memory Profiler


For more information about the dispose tracker, see Dispose
Tracker on page 169.
Enable heap utilization tracking
This setting allows heap utilization tracking to be enabled.
Enabling heap utilization tracking will cause information about
how the generational and large object heaps are used by the
allocated instances. For more information, see Heap Utilization
Tracker on page 172.
Enable AppDomains tracker
This setting determines whether the AppDomains tracker should
be enabled. For more information, see AppDomains Tracker on
page 176.
Enable unmanaged resources tracker
(Professional and Enterprise only)
If this option is checked, then the unmanaged resource tracker will
be enabled, and information about unmanaged resources will be
presented in the snapshot views and the real-time view.
For more information about the unmanaged resources tracker, see
Unmanaged Resources Tracker on page 174.
Enable root identification
This setting enables identification of root referrers, e.g., static
fields, local variables, and method arguments that reference
instances. By identifying root referrers, the profiler can present the
exact reason why an instance has not been garbage collected. It
does this by showing a path from the instance to a root. If root
referrer identification is disabled, all roots will be presented as
<root>, with no further information about the type of root.
Disable inlining
This setting determines whether method inlining should be
disabled. The default behaviour is to disable inlining in order to
present accurate allocation call stacks; however, this has
implications on the performance of the profiled process. If the
performance of the profiled process is too low, you can try to clear
this setting.

.NET Memory Profiler User Manual 103


Launch Settings Page

The Launch page is used to define the process that should be


profiled (or that is being profiled if an active session is selected).
Select type of process to launch
This drop-down list is used to select the type of process that should
be profiled. The following options are available:
Stand-alone application
Windows app
Silverlight application
ASP.NET application
WPF Browser application
Windows Service
Unit tests
Start-up target of current Visual Studio solution
Stand-alone application
The following options are available if Stand-alone application is
selected as process type:
Full path to executable
Defines the path of the application executable
Command line arguments
Optional command line arguments that will be supplied
when starting the application.
Working directory
Optional working directory that will be set when
starting the application.

104 User Manual .NET Memory Profiler


ASP.NET application
If an ASP.NET application should be profiled, the web server to
use must be defined.
Launch using IIS Express
Launch using Internet Information Services
This option indicates that IIS should be used when
profiling the application.
Launch using WebDev.WebServer
This option indicates that the web development server
(WebDev.WebServer) should be used to profile the
application. The Browse button or the Web-site
directory drop-down list should be used to define the
path of the directory where the web site is located. The
Virtual path field can be used to define the virtual
path of the ASP.NET application. If the web server
should listen to a specific port, the port number can be
specified using the Port field. The default port setting
is (auto), which indicates that the port number should
be automatically assigned.
The Select page to request to start ASP.NET application
field can be used to select a web page that should be requested
when the profiling is started. If (none) is selected in the request
page drop-down list, no page will be automatically requested.
WPF Browser application
Only one option is available if WPF Browser application is
selected as process type:
Full path to WPF browser application
Defines the path of the WPF browser application.
Windows Service
If Windows Service is selected as the process type, a list of
available services will be shown. This list should be used to define
the service that should be profiled.

Snapshots Settings Page

.NET Memory Profiler User Manual 105


Collect peak memory snapshot
(Professional and Enterprise only)
This setting determines whether peak snapshot data should be
collected while profiling. If enabled, memory usage data will be
temporarily collected each time a peak has been detected during a
garbage collection. For more information, see Peak Snapshots on
page 78.
Peak memory threshold
(Professional and Enterprise only)
This setting is used to reduce the number of peak snapshot
collected. The threshold value defines how much higher the
memory usage must be for a new peak snapshot to be collected.
For example, if a peak using 1,000,000 bytes of memory has been
collected and the threshold value is 10%, a subsequent peak must
use at least 1,100,000 bytes, otherwise the peak is ignored.
This value is only used to prevent peak snapshots to be collected
too frequently. If there has been a long delay since the previous
peak snapshot, the threshold value is ignored and the new peak is
always collected.
Automatically collect a snapshot every
This option can be used to perform automatic snapshot collections
at a pre-defined interval. The field below is used to define the
collection interval in minutes.
Automatically stop session after
This option can be used to automatically stop the session after
collecting a pre-defined number of snapshots. The field below is
used to define how many snapshots to collect before stopping the
session.
Maximum number of triggered heap snapshots
This setting is used to limit the number of snapshot collections
triggered by the profiled process or by automatic snapshot
collection. A snapshot is triggered when the profiled process calls

106 User Manual .NET Memory Profiler


the MemProfiler.FullSnapshot method or when a memory
assertion has failed. Each snapshot consumes a considerable
amount of memory, so collecting too many snapshots may cause
the performance of the profiler and the system to degrade.

Session File Settings Page

The Session file page is used to decide how session files should be
created.
Ask user if session file should be created
If this option is selected, a dialog will be shown, allowing the user
to decide whether the session should be saved or discarded
If the When saving session, allow the user to select
snapshots to save setting is checked, a dialog allowing the user
to select snapshots to include will appear when saving the session.
This is useful especially when Automatically save heap
snapshots is enabled, since more snapshots than necessary might
have been saved to the temporary file.
Save session
If this option is selected, no user interaction is needed and the
session file will be saved to a pre-defined location. The location is
defined by the Save to folder textbox and the Session file
name textbox. Clicking the Browse button will bring up a folder
browser, which can be used to select the save to folder. The file
name can include the strings %DATE% and %TIME%. These
strings will be replaced with the current date and time when the
session is saved.
Note that the session will only be saved if at least one snapshot has
been collected or if real-time data have been collected
Do not save session
If this option is selected, then all information collected by the
session will be discarded.

.NET Memory Profiler User Manual 107


Real-time Settings Page
The real-time page is used to define collection settings for real-
time data, and to define the layouts used in the real-time view.

Settings

These settings allow real-time data collection limits to be specified.


The Maximum memory to use for global statistics and
types in graph field and the Maximum memory to use for
types not in graph field are used to limit the amount of
memory used for real-time data.

108 User Manual .NET Memory Profiler


Layouts

The layouts page is used to define the real-time layouts in the


profiled session. This is similar to the Settings and series pane
used under the real-time page, except that no live real-time data is
included.

For more information, see Real-Time Page on page 151.

Memory Leak Settings Page

.NET Memory Profiler User Manual 109


The Memory Leak page contains settings that define how memory
leaks detected using the.NET Memory Profiler API should be
handled.
When a memory leak is detected
This setting is used to define what to perform when a memory leak
is detected by a memory assertion. If Ask user about action to
perform is selected, a dialog will appear when a memory leak is
detected. To avoid user interaction, the Perform actions option
can be used.
The following actions are available:
Collect a full heap snapshot
If this action is selected, a full heap snapshot will be
collected and saved. This allows the user to analyze the
instances that have been identified as potential memory
leaks.
Note that the number of snapshots collected is limited
by the Maximum number of triggered heap
snapshots setting under the Snapshots page.
Start the graphical user interface
If this action is selected and the profiler is currently
running in non-interactive mode, the user interface will
be started.
Stop the profiling session
If this action is selected, the profiling session will be
ended, and the profiled process will be terminated.
If more than one action is selected, they will all be performed,
starting with the top one.
Suspend thread until memory leak is handled
This setting decides whether the thread detecting the memory leak
should be suspended until the selected actions have been
performed. If this setting is not enabled, the thread that detected
the memory leak will keep running until an additional memory
leak is detected or until a heap snapshot is triggered by a call to
MemProfiler.FullSnapShot.

110 User Manual .NET Memory Profiler


Instance Data Collection Settings Page

The Instance Data Collection page is used to define whether


instance data should be collected.
Collect instance data at snapshots
If this setting is selected, then instance data will be collected when
a heap snapshot is collected. Instance data is collected for all
instances, but in order to reduce the amount of memory used for
instance data it is possible to limit the size of string and array
instances.
Maximum size of string instance data
Defines the maximum number of bytes to collect for a
string instance. Strings that are larger than this limit
will be truncated.
Maximum size of array instance data
Defines the maximum number of bytes to collect for an
array instance. Arrays that are larger than this limit will
be truncated. This limit does not include memory used
for references, since references are stored separately
and are needed by the profiler to present instance
graphs and root paths.

Call Stacks Settings Page


The Call Stacks settings page is used to define how call stacks
should be collected and reduced. The call stacks settings are
divided into three pages: General, Managed, and Native
(Professional and Enterprise only).

.NET Memory Profiler User Manual 111


The following settings are available under the Call stacks page:
Max skippable call tree nodes
Defines the total number of stack call tree nodes that are allowed
in for call stacks, before the call stack reducer tries to remove
nodes.
Max call stack depth
Call stacks can no longer be limited to a maximum depth. This is
something that may be re-implemented in a future version of .NET
Memory Profiler, if deemed necessary.
Perform native stack walk
This option is used to select whether native stack walks should be
performed. By enabling native stack walks, detailed information
can be retrieved about unmanaged resource creation. However, the
stack walks will slow down the profiled process and the profiler
needs to have access to the symbol files of the native libraries in
the call stack. The symbol file locations are defined using the
Symbol File Locations preferences page.

NOTE! The first time a frame is encountered by the native stack


walker, .NET Memory Profiler needs to retrieve information about
the frame from the debug symbols. This can take some time,
especially if the symbols need to be downloaded. However, the
symbol information will be cached by .NET Memory Profiler,
which will make subsequent stack walks very much faster.

Max stack walk depth


Defines how many frames the native stack walker should
investigate during a stack walk (this includes both frames that will
be included in the stack and frames that are skipped based on the
Include native functions settings). To remove the stack walk depth
limit, press Ctrl-0 (zero).

112 User Manual .NET Memory Profiler


Perform stack walk on managed entry
Defines whether a native stack walk should be performed when a
managed method is entered. Enabling this option will include
additional call stack frames during native to manage transitions
(i.e. native stack information will be presented between the
[Managed to native transition] and [Native to managed transition]
frames) and thread start methods (e.g. the Main method). The
additional information provided by these frames is often not very
important, so unless needed it is recommended that this option be
disabled.

Overview Page
The Overview page is the main snapshot view. After a heap
snapshot has been collected, it shows information about all
managed types and unmanaged resources in the profiled
application. If more than one snapshot has been collected,
information about the changes between snapshots will also be
presented in this view.
You can use the Show snapshot and Comparison snapshot
dropdown lists to select which snapshots to view.
Show hierarchical
If the Show hierarchical check box is checked, the types and
resources are presented hierarchically in the Types/Resources
table, based on assembly/module and namespace. Otherwise, the
types and resources will be presented in a flat list.
Show types/resources
The Show types/resources dropdown list can be used to filter
the type and resources that should be included in the table below.
The following options are available:
All
With new or removed instances
With live and/or allocated instances
With live instances
With allocated instances
With disposed and/or undisposed instances
Types/Resources Table
The Types/Resources table presents a list of types and resources in
the profiled process. The items can be sorted by clicking on the
column headers and filtered using the column filter at the top row
and the Show types/resources dropdown list.

.NET Memory Profiler User Manual 113


The details of a type or resource can be viewed by double-clicking
an item in the list or selecting the Show details command. This
will bring up the Type/Resource details page.
Filters Table
The Filters table presents a list of saved instance and allocation
filters. Just as with the Types/Resources table, the details of a filter
can be viewed by double-clicking or selecting the Show details
command, which will bring up the Filter details view. For more
information about instance and allocation filters, see Instance and
Allocation Filters on page 72.
Table Columns
The information presented for each item depends on the selected
field set and information available in the current snapshot
comparison. The included columns can also be customized using
column customization.
The following information is available in the Types/Resources
table:
Type/Resource indicator
The left-most column contains an indicator of whether
the item is a managed type or an unmanaged resource
using the following symbols:
Managed type
Unmanaged resource
This column is only available in the Types/Resource
table
Analysis issue
Indicates if the memory analyser has found an issue
related to the item. Further information about the issue
is presented in the tooltip of the issue icon. For more
information about analysis issues, see Automatic
Memory Analysis on page 31.
This column is only available in the Types/Resources
table
Namespace/System
If the item is a managed type, this column shows the
namespace name of the type. If the item is a resource,
this column shows the System of the resource (e.g., a
Windows subsystem, such as Gdi or User).
This column is only available in the Types/Resource
table
Name/Resource
If the item is a managed type, this column shows the
name of the type. If the item is an unmanaged resource,
this column shows the name of the resource. If the item

114 User Manual .NET Memory Profiler


is a filter, this column is merged with the Namespace
column, and shows the name of the filter.
The following columns are available for most types, resources, and
filters:

Live instances Total


This column shows the total number of live instances of
the type or resource. Instances of a managed type are
only considered to be live if they are reachable from
any root.
Live instances New
This column shows the number of new instances. A new
instance is a live instance that did not exist at the time
of the comparison snapshot. If the comparison
snapshot is Empty, this value will be the same as the
Live instances - Total value, since there are no
previous instances.
Live instances Removed
This column shows the number of removed instances. A
removed instance is an instance that existed at the time
of the comparison snapshot and is not a live instance at
the time of the selected snapshot.
Live instances Delta
This column shows the difference between New
Instances and Removed Instances.
Live instances Held
This column shows the total number of instances held
by all live instances of the type or filter. For more
information about held bytes, see Held and Reachable
Instances on page 53.
Live bytes - Total
This column shows the total number of bytes used by
all live instances of the type or resource. If the item is
an unmanaged resource and no size information is
available, then this column will be empty.
Live bytes - New
This column shows the total number of bytes used by
all new live instances of the type or resource. If the item
is an unmanaged resource and no size information is
available, then this column will be empty.
Live bytes - Max
This column shows the maximum bytes used by a single
live instance of the type or resource. If the item is an
unmanaged resource and no size information is
available, then this column will be empty.

.NET Memory Profiler User Manual 115


Live bytes Delta
This column shows the difference between the total
instances size for the current heap snapshot and the
total instances size for the previous snapshot. If the
comparison snapshot is Empty, this value will be the
same as the Live bytes - Total value, since there are
no previous instances. If the item is an unmanaged
resource and no size information is available, this
column will be empty.
Live bytes - Held
This column shows the total number of bytes held by all
live instances of the type or filter. For more information
about held bytes, see Held and Reachable Instances
on page 53.
Allocs/sec (or Allocs)
This column shows either the number of allocations per
second or the number of allocations that were
performed between the selected snapshot and the
comparison snapshot, depending on whether the /sec
toggle is checked.
Bytes/sec (or Alloced bytes)
This column shows either the number of bytes allocated
per second or the number of bytes allocated between
the selected snapshot and the comparison snapshot,
depending on whether the /sec toggle is checked.
If a type is disposable, or a filter includes disposable instances, the
following information is also available:
Disposed instances - Total
This column shows the number of instances that have
been disposed but are still reachable. The numbers
presented in the Disposed instances column should
usually be zero. If they are not, it might indicate a
memory leak. For more information, see Dispose
Tracker on page 169. If the item is an unmanaged
resource, this column will be empty.
Disposed instances - New
This column shows the number of new disposed
instances. A new disposed instance is a disposed
instance that did not exist at the time of the comparison
snapshot. If the comparison snapshot is Empty, this
value will be the same as the Disposed instances -
Total value, since there are no previous instances. If
the item is an unmanaged resource, this column will be
empty.
Disposed instances - Removed
This column shows the number of removed disposed
instances. A removed disposed instance is an instance

116 User Manual .NET Memory Profiler


that was disposed and reachable at the time of the
comparison snapshot and is no longer reachable at the
time of the selected snapshot. If the item is an
unmanaged resource, this column will be empty.
Disposed instances Delta
This column shows the difference between New and
Removed disposed instances. If the item is an
unmanaged resource, this column will be empty.
Undisposed instances - Total
This column shows the number of instances that have
been garbage collected without being properly
disposed. For more information, see Dispose Tracker
on page 169. If the item is an unmanaged resource, this
column will be empty.
Undisposed instances - Delta
This column shows the number of instances, between
the selected snapshot and the comparison snapshot,
that have been garbage collected without being properly
disposed,. If the item is an unmanaged resource, this
column will be empty.
If heap utilization tracking is enabled, the following additional
information is available:
Gen #0 - Allocs/sec (or Allocs)
Gen #1 - Allocs/sec (or Allocs)
Gen #2 - Allocs/sec (or Allocs)
Large - Allocs/sec (or Allocs)
These columns show which heap the instances allocated
between snapshots ended up in. If Show heap
utilization as percent is selected, the numbers are
presented as a percentage of the total number of
allocations performed. Otherwise, they will show as
Allocs or Allocs/sec, depending on whether the /sec is
checked. For more information, see Heap Utilization
Tracker on page 172. If the item is an unmanaged
resource, this column will be empty.
Unreachable instances information is available when a gen #0
snapshot collection has been performed, when attaching to a
process using the inspection only attach, when importing a
memory dump, or when viewing a peak snapshot. It is presented
using the following columns:
Unreachable Instances
This column shows the number of instances that exist
on the garbage collected heap without being reachable
from a root. If the heap snapshot was collected using
the standard Collect Heap Snapshot command, then
the values presented in this column will always be zero,
since a full garbage collection has been performed. On

.NET Memory Profiler User Manual 117


the other hand, if the snapshot was collected using the
Collect Gen #0 Heap Snapshot command, or if the
snapshot comes from an attached process or imported
memory dump, then there might be unreachable
instances on the heap since a full garbage collection has
not been performed. For more information see, Heap
Utilization Tracker on page 172. If the item is an
unmanaged resource, this column will be empty.
Unreachable Bytes
This column shows the number of bytes used by
instances that exist on the garbage collected heap
without being reachable from a root.
When viewing a peak snapshot, information about instances that
existed at time the garbage collection was initiated is presented in
the following columns:
Collected Instances
This column shows the number of instances that were
collected by the garbage collection.
Collected Bytes
This column shows the number bytes used by instances
that were collected by the garbage collection.
Total (before GC) Instances
This column show the number of instances that existed
on the managed heap, before the garbage collection.
This number is the sum of Live instances, Unreachable
instances, and Collected instances.
Total (before GC) Bytes
This column show the number bytes that existed on the
managed heap, before the garbage collection. This
number is the sum of Live bytes, Unreachable bytes,
and Collected bytes.
The following columns provide information about potential
memory leaks detected by using the .NET Memory Profiler API.
They are included by default if the Memory Leaks field set is
selected.
Total - Memory leak instances
This column shows the total number of instances that
have been identified as potential memory leaks by a
failed memory assertion. If the item is an unmanaged
resource, this column will be empty.
Delta - Memory leak instances
This column shows the difference between the total
number of memory leak instances of the current
snapshot and the comparison snapshot. If the item is an
unmanaged resource, this column will be empty.

118 User Manual .NET Memory Profiler


The following columns are not included by default in any of the
field sets. They can be included by customizing the columns.
Live bytes Removed
This column shows the total number of bytes used by
the removed live instances of the type or resource. If the
item is an unmanaged resource and no size information
is available, then this column will be empty.
Live bytes - Min
This column shows the minimum bytes used by a live
instance of the type or resource. If the item is an
unmanaged resource and no size information is
available, then this column will be empty.
Finalized instances Total
This column shows the number of instances that have
been queued for finalization. If the item is an
unmanaged resource, this column will be empty.
Finalized instances Delta
This column shows the number of instances, between
the selected snapshot and the comparison snapshot,
that have been queued for finalization. If the item is an
unmanaged resource, this column will be empty.

Type/Resource/Filter Details Page


The Type/Resource/Filter details page shows the details of a
selected type, resource, or filter. The type, resource, or filter can be
selected either by double-clicking on an entry under the Over view
page, by using a Show details command, or by selecting it using
the dropdown lists at the top of the details page. The left-most
drop-down list is used to select whether Type, Resource, or Filter
details should be shown. The other is used to select the specific
item (type, resource, or filter). The item can also be selected by
typing (with auto-complete), making it easier to select a specific
type.
The navigation buttons can also be used to navigate among the
selected types or resources. For more information about the
navigation buttons, see Navigating Types, Resources, Filters, and
Instances on page 94.
Below the drop-down lists, all information about the selected item
is presented in an info panel. The info panel will also include
information about any issues discovered by the memory analyser.
The information presented is the same as the information
presented for each entry under the Overview page. The way it is
presented depends on the selected field set. For more information

.NET Memory Profiler User Manual 119


about analysis issues, see Automatic Memory Analysis on page
31.

Instances
The Instances panel contains a list of the instances related to the
selected item is shown.
The details of an instance can be viewed by double-clicking an
entry in the Instances table or using the Show details
command.
The list can be sorted by clicking on the column headers. The
following information is presented in the instance table:
Analysis issue
Indicates if the memory analyser has found an issue
related to the instance. Further information about the
issue is presented in the tooltip of the issue icon. For
more information about analysis issues, see Automatic
Memory Analysis on page 31.

New instance
This column indicates whether the instance is new, i.e.,
the instance did not exist in the comparison snapshot.
If the new instance symbol is shown, then this instance
is new; otherwise, it existed in the comparison snapshot
as well.

Disposed instance
This column is only included for disposable types and
indicates whether the instance has been disposed. If the
disposed instance symbol is shown, then this instance
has been disposed.

Memory leak instance


This column is only included for managed types and
indicates whether the instance has been identified as a
potential memory leak instance using the .NET
Memory Profiler API. If the memory leak symbol is
shown, then this instance has been identified as a
potential memory leak. For more information about
memory leak detection, see .NET Memory Profiler
API on page 196.
Creation context
This column is only included for unmanaged resources
and indicates the creation context of the instance using
the following symbols:
Managed runtime
Unmanaged interop

120 User Manual .NET Memory Profiler


Other unmanaged
For more information about creation contexts, see
Creation Context on page 175.
Instance
This column shows the instance number. This number
is unique for an instance during the profiler session.
Root kind
If the selected type is the <GCHandle> pseudo type,
this column shows the kind of the GCHandle. For more
information about runtime GC handles, see GC Handle
Identification on page 178.
Referenced by (count)
This column is only included for managed types and
shows the number of referrers to this instance. A
referrer is a field, variable, or parameter that references
this instance.
Wrapped by (count)
This column is only included for unmanaged resources
and shows the number of managed instances that wrap
this instance (i.e., contain a field that contains the
resource instance identifier). For more information
about wrapped instances, see Wrapped by on page
134.
Instance bytes
This column shows the number of bytes used by the
instance.
Held instances
This column shows the number of instances that are
held by the instance. This column is not included by
default, but can be included by customizing the
columns.
Held bytes
This column shows the number of bytes that are used
by instances that are held by the instance.
Reachable instances
This column shows the number of instances that are
reachable from the instance. This column is not
included by default, but can be included by customizing
the columns.
Reachable bytes
This column shows the number of bytes that are used
by instances that are reachable from the instance. This
column is not included by default, but can be included
by customizing the columns.
Age

.NET Memory Profiler User Manual 121


This column is only included for managed types and
shows the age of the instance. The age is increased by
one each time the instance survives a garbage collect.
Identifier
This column is only included for unmanaged resources
and shows the unmanaged resource identifier value of
the instance (e.g., a HANDLE value).
Value
This column shows the value of the instance. The value
of the instance is only available if the instance is a
string, primitive type, or a value type.
Array usage
This column shows the array usage in percent. It is only
available if the instance is an array instance.
Total array slots, Unused array slots, Used
array slots
These columns provide additional information about an
array instance. They are only available for array
instances, and are not included by default. They can be
included by customizing the columns.
If the selected details item is a filter, then the instances are, by
default, grouped by type. The grouped types contain additional
summary information. The following columns are used by the
grouped types:

Type
This column shows the name of the grouped type.
Live instances
This column shows the total number of live instances of
the grouped type.
Live bytes
This column shows the total number of bytes used by
the live instances of the grouped type.
Max held instances
This column shows the maximum number of held
instances by any instance of the grouped type. This
column is not included by default, but can be included
by customizing the columns.
Max held bytes
This column shows the maximum number of held bytes
by any instance of the grouped type.
Max reachable instances
This column shows the maximum number of reachable
instances by any instance of the grouped type. This

122 User Manual .NET Memory Profiler


column is not included by default, but can be included
by customizing the columns.
Max reachable bytes
This column shows the maximum number of reachable
bytes by any instance of the grouped type.
Array usage
This column shows the accumulated array usage of all
instances of the grouped type, in percent. It is only
available if the grouped type is an array type.
Total array slots, Unused array slots, Used
array slots
These columns provide additional information about
array instances. The values are accumulated for all
instances of the grouped type. They are only available
for array instances, and are not included by default.
They can be included by customizing the columns.
Finalized instances
This column shows the total number of finalized
instances of the grouped type.
For more information about held and reachable instances, see
Held and Reachable Instances on page 53.

NOTE! The held and reachable values need to be calculated for


each instance in the list. This calculation may take a while, and the
columns will be empty while the calculation is in progress.

Group by type
The group by type check box is available under the filter instances
list. If selected the filter instances will be grouped by type.

Allocation Stacks
Under the Allocation stacks panel, the allocation call stacks
related to the type or resource are shown. The call stacks are
presented in the same way as under the Call Stacks/Methods page,
with the difference that only call stacks related to the selected type,
resource, or filter are presented. For more information about call
stacks presentation, see Call Stacks View on page 142.
Show details
This button can be used to show the details for the selected call
stack. The details are shown as an instance and allocation filter.

Shortest root paths


Under the Shortest root paths panel, information about the
shortest root paths for all live instances is presented. The shortest
root paths page is not available for unmanaged resources.

.NET Memory Profiler User Manual 123


The root paths presented here combine the shortest root path of
each instance by only looking at the types that are part of the root
path, not the actual instances.
Example:
Assume that two instances of the type ItemClass (#123
and #141) exist and that they have the following shortest
root paths (where ContainerClass.allContainers is a static
field).
ItemClass (#123) ItemClass (#141)
ContainerClass (#456) ContainerClass (#560)
ArrayList (#193) ArrayList (#193)
ContainerClass.allContainers
ContainerClass.allContain
ers
Since only managed type information is used, these two
root paths can be combined into one:
ItemClass
ContainerClass
ArrayList
ContainerClass.allContainers
This combined root path will have two live instances when
presented under shortest root paths.
For more information about root paths, see Root path on page
135.
Sort root paths by
The Sort root paths by field is used to define the order of the
root paths. Below is a list of all the possible options; however, the
available options depend on the selected field set and whether the
type is a disposable class.
The options are:
Live instances
Shows the root paths with the most live instances first.
New live instances
Shows the root paths with the most new live instances
first.
Live bytes
Shows the root paths with the most live bytes first.
New live bytes
Shows the root paths with the most new live bytes first.
Disposed instances

124 User Manual .NET Memory Profiler


Shows the root paths with the most disposed instances
first.
Memory leak instances
Shows the root paths with the most memory leak
instances first.
Hide root paths with zero sort value
If this checkbox is checked, then all root paths for which the sort
value is zero will be hidden.
Truncate root paths
It is possible to truncate the root paths at a specific depth. This
provides the possibility of combining the instance information
from several root paths into a single root path. If root paths are
truncated, the Depth field specifies the maximum depth of the
root path. The following ways of truncating the root paths are
available:
At root
A root path will be truncated when the depth counted
from the instance has reached the maximum value. The
truncated root path will not contain the actual root,
since it will end with a [Truncated] entry.
In the middle
A root path will be truncated in the middle when the
depth counted from both the instance and the root has
reached the maximum value. The truncated root path
will contain both the actual root and the entry closest to
the instance. A [Truncated] entry will be added in the
middle.
At instance
A root path will be truncated when the depth counted
from the root has reached the maximum value. The
truncated root path will not contain the entries closest
to the instance, since it will start with a [Truncated]
entry.
Example:
Consider the following instance root paths.
ItemClass (#123) ItemClass (#141)
ContainerClass (#456) ContainerClass (#560)
AnotherClass (#129) AnotherClass (#443)
ArrayList (#193) ContainerClass (#543)
ContainerClass.allContainers ArrayList (#193)
ContainerClass.allContai
ners

.NET Memory Profiler User Manual 125


If the root paths are truncated at a depth of two, then both root
paths can be combined into one (regardless of how the roots are
truncated). Below is an example of how the roots are combined
depending on the truncation.
At instance: [Truncated]
ArrayList
ContainerClass.allContainer
s
In the middle: ItemClass
[Truncated]
ContainerClass.allContainer
s
At root: ItemClass
ContainerClass
[Truncated]
On the other hand, if the root path depth is set to three, the root
paths cannot be combined if At instance is selected:
At instance (1): [Truncated]
AnotherClass
ArrayList
ContainerClass.allContai
ners
At instance (2): [Truncated]
ContainerClass
ArrayList
ContainerClass.allContai
ners

NOTE! Even though the actual fields that contains the reference
from one instance to another is presented in the root path, the
field is not considered when looking for root paths to combine. But
when two root paths are combined, the fields will also be
combined.

Prioritize static fields


The Prioritize static fields checkbox can be used to give higher
priority to root paths that start with a static field. That is, if a static
field keeps an instance alive, then the root path starting at the field
will be used, even if there another root path starting with a
GCHandle or method that is shorter.
Root path
The Root path group box is used to present a single root path.
The navigator buttons above the root path can be used to select
which root path to show.

126 User Manual .NET Memory Profiler


Below the root path, an info panel is used to present information
about the instances referenced by the root path. The fields
presented include:
Live instances
New live instances
Live bytes
New live bytes
Disposed instances
Memory leak instances
Each field corresponds to one of the columns presented under the
Types/Resources page.
The actual fields included in the info panel and the way they are
presented depend on the selected field set and whether the
selected class is a disposable class.
Show details
This button can be used to show the details for the selected root
path. The details are shown as an instance and allocation filter.

Instances graph
The Instances graph panel is used to present a graph of the
instances selected in the Instances list, the instances of the
selected Shortest root path, or the instances of the selected
Allocation stack. For more information about the instance
graph, see Instance Graph on page 57.

Instances, Allocation Stack, Root Path, and


Graph Synchronization
The selected items in the three sub views (Instances, Allocation
stack, and Root path) are synchronized with each other, and the
combined instances graph. Whenever an instance is selected in the
Instances table, the corresponding allocation call stack and root
path is selected in the other views. This also occurs when multiple
instances are selected, but only if all instances have a common
allocation call stack or root path. If the selected instances do not
have a common call stack or root path, then none is selected and
the message "More than one call stack exists for the selected
instances" or "More than one shortest root path exists for the
selected instances" is shown.
If the allocation stacks or root paths are sorted by something else
than Live instances and the Hide item with zero sort value
option is selected, then it is possible that no matching call stack or
root path can be found. In this case the message "Allocation stack
is hidden for the selected instance(s)" or "Shortest root path is

.NET Memory Profiler User Manual 127


hidden for the selected instance(s)" is shown. To show the
corresponding stack or item, either sort by Live instances, or clear
the Hide item with zero sort value option.
The synchronization also goes the other direction. Whenever an
allocation call stack or root path is selected, the corresponding live
instances (if any) will also be selected in the Instances list, and the
instance graph will be updated to show the instances related to the
selected call stack or root path.

Static field values


If a type is selected and it has any static fields, the Static field
values tree will present all static fields of the type, grouped by
AppDomain (for normal static fields), or by thread (for thread
static fields).
For more information about field values presentation, see Field
values on page 131.

Instance Details Page


The Instance Details page shows the details of a selected instance.
The instance can be selected either by double-clicking an instance,
or using the Show Instance Details command, in any of the
tables showing an instance list (e.g., the Instances in the
Type/Resource/Filter Details page, the Referenced by table on
the Instance Details page, or the Root path table on the Instance
Details page). It can also be selected by selecting a type or resource
and an instance using the dropdown lists at the top of the page.
The navigation buttons can also be used to navigate the selected
instances. For more information about the navigation buttons, see
Navigating Types, Resources, Filters, and Instances on page 94.
Below the Type/Resource and Instance dropdown lists, an info
panel is used to present summary information about the instance.
The info panel will also include information about any issues
discovered by the memory analyser.
For a type instance, the summary includes information such as:
Instance bytes (the number of bytes used by the instance itself),
Held instances, Held bytes, Reachable instances, Reachable bytes,
Age, and Array usage (for an array instance). For an unmanaged
resource instance, the summary information includes the resource
identifier and, if available, the size of the instance.
The info panel also includes symbols that indicate whether the
instance is new, disposed, or a potential memory leak, as well as
the creation context for an unmanaged resource instance.
For more information about the held and reachable values, see
Held and Reachable Instances on page 53. For more information

128 User Manual .NET Memory Profiler


about analysis issues, see Automatic Memory Analysis on page
31.
Six panels are used to present additional information about a
managed type instance: Referenced by, References/Wraps,
Field values, Allocation call stack, and Instance graph.
Three other panels are used to present additional information
about an unmanaged resource instance: Wrapped by, Related
resource instances, and Function.

Instance graph
The Instance graph panel is used to present a graph of the
selected instance, and its related instances and roots. For more
information about the instance graph, see Instance Graph on
page 57.

Referenced by
The Referenced by panel is only available for managed type
instances and shows a tree containing all the instances, static
fields, and other roots that references the selected instance, also
called referrers in this manual. The details of an instance
referencing the selected instance can be viewed by double-clicking
the corresponding entry in this list or by selecting Show
Instance Details from the menu. The items can be sorted by
clicking on the column headers. The following information is
presented for each entry in this list:
Type
This column shows the type name of the instance or
type that references the selected instance. If the
reference is an unidentified root, this column will
contain the text: <root>.
Instance/Field/Method
This column shows different information depending on
the type of the referrer:
If the referrer is an instance, this column shows the
instance number of that instance, followed by the
name of the field (or item in an array) containing
the reference will be appended at the end (e.g.,
#89,123.m_referenceField or #12,890[5]).
If the referrer is a static field root, this column
shows the name of the static field
If the referrer is a local variable or method
argument root referrer, the name of the method is
presented in this column.
If the referrer is a <GCHandle>, this column will
present the instance number of the <GCHandle>,

.NET Memory Profiler User Manual 129


together with any additional GC handle
information, such as Weak or Pinned.
It is possible to expand each instance in the Referenced by tree,
to get information about the next level of referrers.

NOTE! If a WeakReference (or a weak <GCHandle>) instance is


referencing the selected instance, it will be included in the
Referenced by list, but it will not be part of any root path, since a
weak reference never prevents an instance from being garbage
collected.

Only show instances included in root paths


If the Only show instances included in root paths checkbox
is checked, only instances that are part of one of the root paths
presented for the selected instance are presented in the
Referenced by tree. Instances that only have root paths that
include the selected instance are not included in any root path and
are usually of no interest when analyzing causes of a memory leak.
Using this option provides a way of analysing the root paths by
expanding instance items in the tree. If all instances are included
in the Referenced by tree, there is a risk that cycles are included in
the tree (e.g. m_childm_parentm_child,...), making it harder
to find the actual root paths. Enabling this option will prevent all
cycles (a root path from an instance cannot contain the instance
itself) and present the shortest path to each root.

References/Wraps
The References/Wraps tree is only available for managed type
instances and shows a tree of all references from the selected
instance, i.e., the values of all non-null reference fields. If the
instance wraps any resource instance, the tree also contains all
resource instances that are wrapped by the selected instance. For
more information, see Wrapped by on page 134. If the instance
does not wrap any resource instances (or the unmanaged resource
tracker is not enabled), the page name is only References.
The details of a reference can be viewed by double-clicking an
entry in this list. The list can be sorted by clicking on the column
headers. The following information is presented for each entry in
this list:
Field
This column shows the name of the field (or fields) that
contains the reference or the wrapped resource
identifier.
Type/Resource
This column shows the type name of the instance
referenced by the selected instance, or the resource

130 User Manual .NET Memory Profiler


name if the field wraps an unmanaged resource
instance.
Instance
This column shows the instance number of the instance
referenced by the selected instance.
Instance bytes
This column shows the number of bytes used by the
referenced instance.
Held instances
This column shows the number of instances that are
held by referenced the instance. This column is not
included by default, but can be included by customizing
the columns.
Held bytes
This column shows the number of bytes that are used
by instances that are held by the referenced instance.
Reachable instances
This column shows the number of instances that are
reachable from the referenced instance. This column is
not included by default, but can be included by
customizing the columns.
Reachable bytes
This column shows the number of bytes that are used
by instances that are reachable from the referenced
instance. This column is not included by default, but
can be included by customizing the columns.
For more information about held and reachable instances, see
Held and Reachable Instances on page 53..
It is possible to expand each instance in the References tree, to
get information about the next level of references.
Only include held instances
If the Only include held instances checkbox is checked, only
instances that are held by the selected instance is included in the
references tree. Additionally, each held instance will only be
included once in the tree, which will prevent cycles to be included
in the tree. (e.g., if the Only include held instances is checked
and a held instance has a reference back to the selected instance,
this reference will not be presented in the tree).
Using this option provides the possibility to investigate the
memory used exclusively by the selected instance.

Field values
If instance data have been collected for the selected instance, the
field values are presented in the Field values tree. If instance data

.NET Memory Profiler User Manual 131


have not been collected, a single entry with the message (No
instance data available) will be shown. To define when
instance data are collected for an instance, the Instance Data
Settings Page should be used.
If the type of the instance has any static fields, the Field values
tree will also contain all static fields of the type, grouped by
AppDomain (for normal static fields), or by thread (for thread
static fields).
If the instance itself is a primitive type (e.g., a boxed int, double, or
a string), the value of the instance is presented as a single field
with the name (value). Otherwise, the fields of the instance are
presented together with their values in the table, using the
following columns:
Name
This column shows the name of the field.
Value
This column shows the value of the field. How the value
is presented is described below.
Type
This column shows the type of the field. If the type is a
primitive type (e.g. int, long, float, double, object or
string), the primitive name will be used. Otherwise, the
name of the type will be used. If the actual type of the
referenced instance differs from the field type, the
actual type is also included after the field type.

Presentation Style
Using the Preferences settings, it is possible to select two different
styles of presenting the fields, i.e., Visual Studio and Flat.
Visual Studio
The Visual Studio style mimics the way fields are presented in the
Visual Studio Variables windows. The fields are presented in a
hierarchy based on the type they are declared in, and they are
sorted alphabetically.

132 User Manual .NET Memory Profiler


Flat
The fields are presented in the order they are declared in the
Types, without any hierarchy and with the top-level type fields
first.

Value Presentation
The way the field value is presented depends on the type of the
field:
Primitive numeric type (e.g., byte, short, int, long, float,
and double):
The value is converted to its string representation. A suffix
is added to floats and doubles (f and d, respectively).
Reference type:
If the reference field is null, then it is presented as null.
Otherwise, the instance number of the instance it
references is presented.
If the referenced instance is a string (System.String),
the contents of the string are presented after the instance
number.
If the referenced instance is a boxed primitive numeric
type, the value of the unboxed instance is presented, within
braces, after the instance number.
Otherwise, if the type of the referenced instance differs
from the type of the field, the name of the type is presented,
within braces, after the instance number. For example, if
the field type is System.Collection.ICollection and
the referenced instance is of type
System.Collection.ArrayList, the value will be
presented as: #xxxx {ArrayList}.
The + can be clicked to investigate the field values of the
referenced instance. To view the details of the referenced
instance, double-click the reference or select Show
Instance Details.

NOTE! Information about the referenced instance (type,


string value, or boxed value) can be presented only if

.NET Memory Profiler User Manual 133


instance data have been collected for the referenced
instance.

Value type:
A text representation of the fields in the value type is
presented in the Value column, within braces. Additional
information about the fields in the value type is available by
clicking +.

Wrapped by
The Wrapped by tree is only available for unmanaged resources
instances and shows a tree of all the managed instances that wrap
the selected resource instance. A managed instance is considered
to wrap a resource instance if it contains a field that is equal to the
identifier of the resource instance.
For more information about the information presented in this tree,
see Referenced by on page 129.

Related resource instances


The Related resource instances panel is available only for
unmanaged resource instances and shows a list of resource
instances that are related to the selected instance. Two resource
instances are related to each other if one instance is created during
the creation of the other. The list contains two types of related
instances, i.e. Nested instances and Outer instance. A nested
instance is a resource instance that was created during the creation
of the selected instance. An outer instance is an instance that was
being created while the selected instance was created.
For example, while creating a windows handle (HWND) using
CreateWindowEx, a bitmap might also get created during the call
to CreateWindowEx.

Call CreateWindowEx
Call CreateBitmap
CreateBitmap returns HBITMAP (#123)
CreateWindowEx returns HWND (#124)

In this scenario, the HWND #124 and HBITMAP #123 are related,
since the HBITMAP instance was created while CreateWindowEx
was still executing. The HBITMAP instance is a nested instance of
the HWND instance, and the HWND instance is an outer instance
of the HBITMAP instance.
The details of a related resource instance can be viewed by double-
clicking the corresponding entry in this list or by selecting Show
details from the menu. The list can be sorted by clicking on the

134 User Manual .NET Memory Profiler


column headers. The following information is presented for each
entry in this list:
System
This column shows the System of the resource
instance (e.g., a Windows subsystem such as Gdi or
User).
Resource
This column shows the name of the related resource
instance.
Instance
This column shows the instance number of the related
resource instance.

Root path
The Root paths panel is used to show the root paths of the
instance. A root path is the path of referrers from the selected
instance to a root. A root can, for instance, be a static field, a local
variable, or a method parameter. If a root cannot be identified, the
roots are simply referred to as <root>. For an unmanaged
resource instance, the wrapper instances are used as referrers to
the instance. If no wrapper instances exist, no root paths will be
presented.
The root path can be extremely useful for identifying memory
leaks. When using the observer pattern or caching instances, it is
very easy to forget to remove an observer or to let the cache grow
too much. The root path shows why an instance has not been
garbage collected.
The shortest path from the selected instance to each root is
presented, and the shortest path is shown first. The navigator
buttons above the root path can be used to select which root path
to show.
At the top of the Root path table is the nearest referrer. The
farther a referrer is from the selected instance, the farther that
referrer is down the list. At the bottom of the list is the root
referrer, which is either presented as the name of a static field, a
method, or as <root>.
The following data is presented for each referrer:
Namespace
This column shows the namespace name of the instance
or type that references the selected instance. If the
reference is an unidentified root, this column will
contain the text: <root>.
Name

.NET Memory Profiler User Manual 135


This column shows the type name of the instance or
type that references the selected instance. If the
reference is an unidentified root, this column will be
empty.
Instance/Field/Method
This column shows different information depending on
the type of the referrer:
If the referrer is an instance, this column shows the
instance number of that instance, followed by the
name of the field (or item in an array) containing
the reference will be appended at the end (e.g.,
#89,123.m_referenceField or #12,890[5]).
If the referrer is a static field root, this column
shows the name of the static field
If the referrer is a local variable or method
argument root referrer, the name of the method is
presented in this column.
If the referrer is a <GCHandle>, this column will
present the instance number of the <GCHandle>,
together with any additional GC handle
information, such as Weak or Pinned.

Instance creation
The Allocation call stack/Call stack panel and the Function
panel provide information about how the instance was created.
The call stack panel presents the call stack of the instance
allocation or creation. The Function panel is only available for an
unmanaged resource instance. It presents information about the
arguments that were used when calling the creation function.

Call Stacks/Methods Page


When an instance is allocated, the call stack of the allocation is
saved. The Call stacks/Methods page is used to present
information about all saved call stacks and methods. The
allocation stacks can be useful for finding code that performs
excessive allocations. They can also be used to locate call stacks or
methods that are responsible for creating a large number of live
instances. Call stacks and methods presentation is separated in
two views, accessible using the Call stacks page and the
Methods page.
Above the view pages there are two checkboxes that can be used to
select which allocations should be included:
Include managed allocations

136 User Manual .NET Memory Profiler


This checkbox can be used to include allocations of
managed instance in the call stacks and methods view.
Include unmanaged resource allocations
This checkbox can be used to include allocations of
unmanaged resource instance in the call stacks and
methods view.

Methods View
The methods view is used to present information about methods
that have performed instance allocations.
The methods information is presented in a tree. This tree includes
three levels of information:

1. Container information
The assembly/module, type, and namespace that
contains the base method. This level presents summary
information from child items in the tree. For example,
the Live instances summary information for a type
includes the sum of all live instances created by all
methods in the type.
This level is only included if the Show hierarchical
checkbox is checked.
2. Base method
This level presents the base methods and provides
allocation information for the method itself. The actual
allocations included in the information depends on the
Include setting described below.

.NET Memory Profiler User Manual 137


3. Callers of the method and functions called by
the method
This level can be used to get information about
functions that called the base method, and functions
that are called by it. By expanding the Called by and
Calls child nodes, partial call stacks that start or end
with the base method can be built.
Allocation information will be presented for all
allocations that match this partial call stack.
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.
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 (an arrow indicator, ', is used to indicate multiple
frames in a node). All frames of the partial call stack are presented
in a tooltip.

Above the methods tree, there is a toolbar with the following


settings and actions:
Top-level methods
The Top level methods dropdown list defines which functions
should be included as base functions in the methods tree. The
available options are:
Source
Only include functions and methods that have source
information.

138 User Manual .NET Memory Profiler


Source and externally visible
Only include native functions that are exported or
managed methods that are externally visible, or
methods that have source information.
All
Include all functions and methods that are available in
all call stacks.
Show value
This drop-down list is used to select the values to present for each
column in the call tree. The available options are:
Inclusive (Exclusive)
Show both the inclusive value (allocations performed by
the method and all called child methods) and the
exclusive value (allocations performed by the method
itself). The exclusive value is presented within
parenthesis.
Inclusive
Only show the inclusive value.
Exclusive
Only show the exclusive value.
Sort by
If more than one value is presented per column, this drop-down
list can be used to select the value to use when sorting using the
column.
Merge frames threshold
To reduce the complexity of the call tree, frames with little
information can be merged into a single node, [Other frame(s)].
The threshold value is used to specify when a frame is included in
the [Other frame(s)] node.
Show hierarchical
If the Show hierarchical check box is checked (the default), the
functions and methods view will be presented hierarchically, based
on assembly/module, type and namespace. Otherwise, the level 1
items will not be included, and the base methods will be presented
in a flat list (see below).

.NET Memory Profiler User Manual 139


Expand hot path
Expands the nodes with the highest sort value from the selected
node.

Collapse all
Collapses all expanded nodes in the call tree.

Matching Partial Call Stack


Each level 2 and 3 item has an associated partial call stack. The
partial call stack for a base method (level 2) item simply contains
the base method. The partial call stack for a level 3 item starts or
ends with the base method (as mentioned above).
The allocation information for these items is retrieved from the call
stacks that match the partial call stack of the item. To be
considered a match, an allocation call stack must contain all
functions in the partial call stack.
A function can be skipped due to the Top level methods setting,
by the call stack reducer, the session call stacks setting, or by the
call stack functions setting. Skipped functions in a call stack are
marked with a [Skipped frame(s)] entry. A [Skipped frame(s)]
entry in the partial call stack can match one or more frames in the
allocation call stack.
Example:
The following stacks will match:
Allocation call stack Partial call stack
Function1() Function1()
Function2() [Skipped frame(s)]
Function3() Function4()
Function4()
Function5()

140 User Manual .NET Memory Profiler


Call Stacks Functions
The Call Stacks Functions command (on the View menu) can
be used to determine which methods are included when presenting
caller functions and called functions.
The available options are the same as the top-level methods.

NOTE! This is an application wide setting, changing this option


will affect all call stack viewers, as well as the methods view.

Methods Allocation Information


The information presented for the methods tree items is similar to
the information presented on the Types/Resources page. However,
it only includes data from allocations performed by the method,
container or partial call stack.

NOTE! The numbers presented for a type (when showing


hierarchical) are not the same as the numbers presented under the
Overview page. Here they refer to instance allocations performed
by a method in the type, in the Overview view they refer to the
allocated instances of the type.

The Include allocations by called functions option is used to


determine whether the allocations information should include
allocations by called functions as well.
For more information about the information presented, see
Type/Resource/Filter Details Page on page 119. The following
information columns are always included:
Live instances
New live instances
If the Standard field set is selected, the following columns are
also included in the methods list:
Live bytes
New live bytes
Allocs/sec (or Allocs)
Bytes/sec (or Alloced bytes)
If the Dispose info field set is selected, the following columns are
also included in the methods list:
Disposed instances
Delta undisposed instances
Allocs/sec (or Allocs)
If the Heap Utilization field set is selected, the following
columns are also included in the methods list:

.NET Memory Profiler User Manual 141


Allocs/sec (or Allocs)
Gen #0 - Allocs/sec (or Allocs)
Gen #1 - Allocs/sec (or Allocs)
Gen #2 - Allocs/sec (or Allocs)
Large - Allocs/sec (or Allocs)
Unreachable instances
Unreachable bytes
If the Memory Leaks field set is selected, the following columns
are also included in the methods list:
Memory leak instances
Allocs/sec (or Allocs)

Call Stacks View


The call stack view is used to present call stacks and information
about the allocations and instances related to the call stacks.
Sort Stacks By
The Sort stacks by field is used to define the order of the call
stacks. Below is a list of all the possible options; however, the
available options depend on the selected field set.
The options are:
Allocs/sec (or Allocs)
Shows the stacks first that have the most allocations
(per second) between snapshots.
Bytes/sec (or Alloced bytes)
Shows the stacks first that have the most allocated bytes
(per second) in between snapshots.
Live instances
Shows the stacks first that have the most live instances.
New live instances
Shows the stacks first that have the most new live
instances.
Live bytes
Shows the stacks first that have the most live bytes.
New live bytes
Shows the stacks first that have the most new live bytes.
Disposed instances
Shows the stacks first that have the most disposed
instances.
Undisposed instances
Shows the stacks first that have the most undisposed
instances.

142 User Manual .NET Memory Profiler


Memory leak instances
Shows the stacks first that have the most memory leak
instances.
Allocs in gen #0 (or Allocs/sec in gen #0)
Allocs in gen #1 (or Allocs/sec in gen #1)
Allocs in gen #2 (or Allocs/sec in gen #2)
Allocs in large heap (or Allocs/sec in large
heap)
Shows the stacks first that have the most allocations in
the specified heap.
Unreachable instances
Shows the stacks first that have the highest number of
unreachable instances.
Unreachable bytes
Shows the stacks first that have the highest number of
unreachable bytes.

Hide stacks with zero sort value


If this checkbox is checked, then all call stacks for which the sort
value is zero will be hidden.
Stack Depth
To limit the stack depth, the Stack depth field can be used. The
stack depth can be selected either by choosing one of the pre-
defined values or by entering an arbitrary stack depth. If the
selected call stack depth is All, then all call stacks are presented at
their full depth. Otherwise, if the depth of a call stack is greater
than the selected stack depth, it will be truncated and an entry
named [Truncated] will be appended. All call stacks that become
equal after truncation will be merged, so truncating call stacks will
reduce the number of call stacks presented.
Call Stack
The Call stack group box is used to present a single call stack. The
navigator buttons above the call stack can be used to select which
call stack to show.
If source information is available for a method in the call stacks
list, then a symbol ( ) will be shown to the left of the method. If
running under Visual Studio the source can be shown by double-
clicking the method or by selecting the Show source command.
The functions presented in the call stack depend on the Call
Stack Functions setting. This setting can be changed using the
Call Stack Functions command in the View menu or the call
stack context menu. The available options are:
Source
Only includes functions and methods that have source

.NET Memory Profiler User Manual 143


information. Other functions and methods will be
presented as [Skipped frame].
Publically visible
Only includes native functions that are exported or
managed methods that are externally visible. Other
functions and methods will be presented as [Skipped
frame].
All
Includes all functions and methods that are available in
the call stack.

NOTE! The actual functions and methods available depend on the


call stack session settings. For more information, see Call Stacks
Settings Page on page 111.

To the right of the allocation call stack, an info panel is used to


present information about the instances allocated by the stack. The
fields presented include:
Live instances
New live instances
Allocs/sec (or Allocs)
Bytes/sec (or Alloced bytes)
Live bytes
New live bytes
Disposed instances
Delta undisposed instances
Allocs in gen #0 (or Allocs/sec in gen #0)
Allocs in gen #1 (or Allocs/sec in gen #1)
Allocs in gen #2 (or Allocs/sec in gen #2)
Allocs in large heap (or Allocs/sec in large heap)
Unreachable instances
Unreachable bytes
Memory leak instances
Each field corresponds to one of the columns presented under the
Overview page.
If the call stack has created any unmanaged resource instances,
then the creation context is indicated with the corresponding
symbol in the info panel as well. For more information, see
Creation Context on page 175.
The actual fields included in the info panel and the way they are
presented depend on the selected field set and whether dispose
and heap utilization tracking is enabled.

144 User Manual .NET Memory Profiler


Details (allocated instances)
The Details (allocated instances) shows the allocation details
of a selected call stack in the call stack view or an item in the
methods view. Each entry in the list contains information about
the allocations of a class that has been performed by the call stack
or method. The information presented is a subset of the
information presented on the Types/Resources page. For more
information about the information presented, see Overview Page
on page 113.
The Include allocations by called functions checkbox is used
to select whether allocation by called functions should be included
in the details.
The details of a type can be viewed by double-clicking on an entry
in the details list, which will bring up the Filter details page. All
instances allocated by the selected call stack or method will
included in the filter.
This list always contains the following columns:
Namespace/System
Name/Resource
Live instances Total
Live instances - New
If the Standard field set is selected, the following columns are
also included in the list:
Live bytes - Total
Live bytes - New
Allocs/sec (or Allocs)
Bytes/sec (or Alloced bytes)
If the Dispose info field set is selected, the following columns are
also included in the list:
Live instances Disposed
Undisposed instances Delta
Allocs/sec (or Allocs)
If the Heap Utilization field set is selected, the following
columns are also included in the list:
Allocs/sec (or Allocs)
Gen #0 - Allocs/sec (or Allocs)
Gen #1 - Allocs/sec (or Allocs)
Gen #2 - Allocs/sec (or Allocs)
Large - Allocs/sec (or Allocs)
Unreachable - Instances

.NET Memory Profiler User Manual 145


Unreachable - Bytes
If the Memory Leaks field set is selected, the following columns
are also included in the list:
Memory leak instances
Allocs/sec (or Allocs)

Native Memory Page


The Native Memory Page presents information about the native
memory of a process. Native memory is the memory managed by
the operating system, rather than the Common Language Runtime.

Selecting memory to show


To select the memory to show, the three radio buttons on the page
can be used:
Show memory of snapshot
This option is used to show the memory of the currently
selected snapshot.
Show memory difference between snapshot
This option is used to show the memory difference
between the selected snapshot and the comparison
snapshot (i.e., the memory entries of the comparison
snapshot are subtracted from the memory entries of the
selected snapshot).
Show memory of process
This option is used to show the memory of any process
running on the system (including non-.NET processes).
The dropdown list to the right of this option is used to
select the process for which memory is to be shown. A
separate snapshot of the native memory of the process
is taken when this option is selected or when the
Refresh button is pressed.
Two views are used to present information about the native
memory:
Committed memory
This view is used to present the committed memory of a
process. Committed memory is memory for which
physical storage (in memory or on disk) has been
allocated. The physical storage on disk includes the
paging file and files that are mapped into the memory
of the process (e.g., by loading a DLL).
Physical memory
This view is used to present the physical memory of a
process. Physical memory is the part of the committed

146 User Manual .NET Memory Profiler


memory that has been mapped to physical memory in
the computer. The total sum of this view is the value
presented as Memory usage by the Task manager.

NOTE! The amount of committed memory may be significantly


greater than the amount of total memory of the system. For
instance, loading a DLL file into the memory of a process makes
the whole DLL become part of committed memory, but only the
parts of the DLL that are actually used by the process will be
mapped to physical memory. For more information, read about
Memory Management in the Platform SDK documentation.

Trim working set


This button can be used to trim the working set of the selected
process. All physical memory is swapped out to the paging file,
module, or memory mapped file. It effectively sets the used
physical memory to zero. As soon as memory is needed, it will be
swapped back into physical memory.
By trimming the working set, it is possible to find the physical
memory requirements of the process. Since all memory is swapped
out, the physical memory presented is only the physical memory
used after trimming the working set. Any memory used only for
startup of the process will not be included.

Memory View
The native memory is presented using a tree view. Each node of
the tree represents a type of memory. The information presented
for each node is the name of the memory type and the memory
used by that type. If the tree node has children, the memory
presented will be the sum of the memory of all the child nodes.
At the top level, the memory is categorized as: Private, Shared and
Potentially shared. (For more information about the categories, see
the section about Private, Shared, and Potentially Shared
Memory on page 151.)
Underneath this category, the memory is further divided into
different types depending on whether the memory data come from
the profiled process or not.
For the profiled process, the following information is presented:
Managed heaps
JIT
Code
Thread stacks
Identified resources
Unidentified unmanaged heaps

.NET Memory Profiler User Manual 147


Profiler induced data
Other data
System
For all other processes, the following information is presented:
Code
Data
System
Above the tree view, the total memory used is presented. This is
the sum of Private, Shared, and Potentially shared memory. For
the profiled process, the memory used by the profiler is not
presented in the tree view, but it is included in the value presented
in parenthesis after the total memory.

Managed heaps
The managed heaps are divided into the Generation #0 to
Generation #2 heaps, the large object heap and overhead.
Generation Heaps and Large Object Heap
The generation heaps and the large object heaps are further
divided into Data, Holes, and Unreachable.
Data represents memory that is actually used by an allocated
instance.
Holes represent memory that is unused between two allocated
instances. Holes appear when the heap is not fully compacted,
due to pinned instances or optimizations in the garbage collector.
Unreachable represents memory that is currently used by an
allocated instance, but the instance is not reachable from any root.
Unreachable instances may appear after a generation #0 or a
generation #1 collection, since not all instances are collected.

NOTE 1! Unreachable instances are only identified if a full


reachability analysis is performed by the profiler at each GC. A full
reachability analysis is performed when a snapshot is collected, or
if heap utilization tracking is enabled. Otherwise, unreachable
instances will be presented as Data.

NOTE 2! Since the garbage collector has to look at all instances for
references to other instances, most instances will be mapped to
physical memory. Thus, the Physical memory view and Committed
memory view of the GC heap will be mostly the same. Large
unused instances (larger than the page size of 4096 bytes) that
contain no references may be swapped out to the page file in a low
memory condition (or if the Trim working set button is
pressed).

148 User Manual .NET Memory Profiler


Overhead
The Overhead node presents the memory used by the GC heap that
is not mapped to the generation heaps or the large object heap.
This includes any bookkeeping data needed by the garbage
collector as well as memory that is available for future allocations.
Memory that comes directly after a generation #0 heap is assumed
to be available for future allocations and is presented as Extra
under the Overhead node. All other overhead memory is presented
as Other under the Overhead node.

JIT
This node is only presented for the profiled process.
JIT memory is the memory used by the JIT-compiled code of the
process. The profiler tries to match the memory with the module
(.exe or .dll) that contains the code (or actually the IL code that
was JITted). If it succeeds, the memory is presented under the
Code node using the name of the matched module; otherwise the
memory is presented as <Other>.
If low-impact profiling is enabled, then JIT memory will give
information about how JITted code is shared between processes. If
low-impact profiling is not enabled, all JITted code will be private
to the profiled process, since the code has been modified by the
profiler.

Code
Code memory is executable memory that can be private, shared, or
potentially shared. The profiler tries to match the memory with the
module (.exe or .dll) that contains the code. If it succeeds, the
memory is presented under the Code node using the name of the
matched module; otherwise, the memory is presented as
<Other>.

Thread stacks
This node is only presented for the profiled process.
The Thread stacks node presents the memory used by the thread
stacks in the process. It is divided into Managed thread stacks,
which presents the memory used by threads managed by the .NET
runtime, and Unmanaged threads, which presents the
memory used by all other threads.

Identified resources
This node is only presented for the profiled process, and it is
presented only if the unmanaged resources tracker is enabled.
It presents the memory used by unmanaged resources tracked by
the unmanaged resources tracker. Only memory that is not

.NET Memory Profiler User Manual 149


presented under another node, such as Thread stacks, is included
here.

Unidentified unmanaged heaps


This node is only presented for the profiled process.
It presents the memory used by the Win32 heap functions (e.g.,
HeapAlloc), which has not been identified by the unmanaged
resources tracker.

Profiler induced data


This node is only presented for the profiled process, and it is
presented only if the unmanaged resources tracker is enabled.
Profiler-induced data are memory data that have been indirectly
allocated by the profiler itself. When the profiler retrieves data
about types, modules, and other entities, the runtime will allocate
memory for this information. It is likely that this information
would not have been retrieved if the process were not being
profiled, so memory under this node can be considered to be
profiler overhead.

Other Data
This node is only presented for the profiled process.
Other data memory is memory that can be private, shared or
potentially shared. This memory can be, for instance, resources of
a module or memory allocated using VirtualAlloc.
The profiler tries to match the memory with the file (.exe, .dll or
memory mapped file) that contains the data. If it succeeds, the
memory is presented under the Other data node using the name of
the matched module, otherwise the memory is presented as
<Other>.

Data
This node is presented only for non-profiled processes. A profiled
process has more details on the memory types (for instance, it
knows if the memory is part of the GC heap), so it will use the
Other data node to present additional information about data
memory.
Data memory is memory that can be private, shared, or potentially
shared. This memory can be, for instance, resources of a module or
memory allocated using VirtualAlloc or HeapAlloc. The GC heap is
also a part of the Data memory.
The profiler tries to match the memory with the file (.exe, .dll or
memory mapped file) that contains the data. If it succeeds, the
memory is presented under the Data node using the name of the
matched module; otherwise the memory is presented as
<Other>.

150 User Manual .NET Memory Profiler


System
This node presents the memory that is only available to the
operating system. It has no child nodes.

Private, Shared, and Potentially Shared Memory


Private memory is memory used solely by the selected process. The
GC heap is part of the private memory. Shared memory is used by
at least one other process in addition to the selected process. When
looking for memory leaks, the private memory is usually more
likely to be of concern.
Examples of shared memory are code pages and read-only data
sections. Because these pages of memory don't change, the
operating system can use the CPU hardware to map the physical
pages of RAM into multiple address spaces. For example, every
process uses code in NTDLL.DLL, but the same physical pages of
RAM that hold NTDLL.DLL's code are shared between all
processes.
Potentially shared memory is memory that has been marked as
shareable, but it is currently only being used by one process. It
might be shared at a later point if another process is requesting the
same memory.

Real-Time Page
The Real-time page presents real-time information about the
managed memory usage, native memory and resource usage, and
data from collected performance counters. It gives a good overview
of how the memory is being used during the life-time of the
profiled process.
The information includes, for example, the number of total
instances, total bytes, live instances, and live bytes. It is updated at
least once every second. The history of all collected data is stored
as series of data and can be used to present the data graphically.
Note that the numbers presented are not dependent on the
snapshots selected; if the session time selector is active, they
reflect the memory activity that had taken place at the selected
time, otherwise they reflect the memory usage at the end of the
session. For more information about the session time selector, see
Session Time Selector on page 168.
Three panes are used to present the real-time information, define
the data to present, and to define presentation settings: the
Graph, Settings and series, and Types/Resources panes.

.NET Memory Profiler User Manual 151


Graph
In the graph pane, graphs of selected data series are presented.
Initially, total and live managed bytes and vertical markers for
each collected snapshot are presented.
The graph always contains at least one x-axis, representing the
time elapsed since starting the profiler session. Additionally, it
contains zero or more y-axes, which are added when plots are
added to the graph. When a plot is added, it must have a y-axis
matching its unit. If no matching y-axis exists, a new one is added.
For example, adding Total instances to an empty graph will add a
y-axis with the text Instances. Adding Live instances to the
same graph will not cause another y-axis to be added, since both
Total instances and Live instances are using the unit
Instances. However, adding Total bytes, will cause a y-axis with
the text Bytes to be added.
To select which graphs to include in the graph view, the check
boxes in the Settings and series panel should be used.

The colored legend in the Settings and series pane indicates the
color and type of the graph when the series is included in the graph
view. For more information on working with the graph, see
Working with the Graph on page 165. For more information
about the Settings and statistics pane, see Settings and Series
on page 154.

A Comment on the Appearance of Total and Live


Plots
When including managed memory and instances graphs in the
graph view, e.g. Total instances or Total bytes, the graphs will
often have a saw-tooth shape. Every time an instance is allocated,

152 User Manual .NET Memory Profiler


the plot value increases, and every time a garbage collect is
performed, the total bytes and total instances are reduced. Ideally,
after a garbage collect, the total number of instances on the heap
should be equal to the number of live instances, but since the
garbage collector does not look at all instances for lower
generation GCs (generation #0 and generation #1), there might be
instances that are not collected, even though they are not
reachable.
The garbage collector is optimized using the assumption that
young instances are very short-lived, and, thus, in order for the
garbage collector to function optimally, very few instances should
survive a generation #0 collect.
Below is a graph showing an ideal shape of the total bytes plot
together with the live bytes plot. As you can see, at each generation
#0 collect, the number of total bytes approaches the number of live
bytes, and the live bytes are almost constant.

The next graph shows the plots when the conditions are not
optimal. After each generation #0 collection, the total bytes have
increased considerably, even though the live bytes are almost
constant. Not even a generation #1 collection manages to decrease
the total bytes on the heap. Only after a full generation #2
collection, does the number of total bytes become equal to the
number of live bytes.

.NET Memory Profiler User Manual 153


The main difference between the two scenarios presented above is
that, in the first scenario, the instances are very short-lived, and in
the second scenario, the instances survive for much longer. Also
note that the number of live bytes is almost constant at around
10,000 Kbytes in both cases, but, in the first case, the memory
overhead is only about 200 Kbytes, while in the second case, it is
almost 20,000 Kbytes. Obviously, the second scenario should be
avoided if possible, since it has a much higher memory overhead
and performs more generation #2 collections, which is an
expensive thing to do.

Settings and Series


The Settings and series pane is used to define how real-time
data is presented, which data series to include, and to present
numerical values from the included real-time data.
The panes include a layout selector, and a set of collapsible groups
(Sources, Settings, and real-time series categories).

Real-time layout
The real-time layout drop-down list is used to select the layout to
use when presenting real-time data. The layout defines which data
sources to use (i.e. session files), presentation settings, which data
series to include, and how data should be presented in the real-
time graph. A single layout (Standard) is included with the
installation of .NET Memory Profiler. This layout includes the
most important real-time information for the .NET runtime and
native resources (if native resource tracking is enabled). Additional
real-time series can be added using the Add and Add series
links.
The Save/Manage button is used to show a drop-down dialog
where real-time layouts can be managed.

154 User Manual .NET Memory Profiler


The Manage real-time layouts drop-down provides the
following options:
Save current real-time layout
This option allows the user to save a modified layout, or save a
layout under a different name. If the Layout name is changed, an
additional option is provided, to allow the layout to be saved as a
new layout (Save new layout), or to rename the current layout
(Rename current layout).
It is also possible to save the layout as a default layout, to be used
in all new profiler sessions, or to save it to the profiler project
associated with the session (if any). The options under Save to
additional locations can be used to define where the layout should
be saved (Save in default layouts, Save in project).
Delete current real-time layout
This option deletes the currently selected layout from the available
layouts in the session.
Retrieve real-time layouts
The Retrieve real-time layouts option provides the possibility to
import real-time layout from another session, profiler project, or
the default layouts.

.NET Memory Profiler User Manual 155


Once the layout source has been selected, a list with available
layouts to import is presented. If the Clear all current layouts
(reset) option is selected, all layouts in the current
session are removed before importing the selected
layouts.

Sources
The Sources group is used to define the sources used for the real-
time data. By default, the current session is used as the real-time
source, but it is possible to add external session files as additional
sources.

Enterprise only An additional source is added using the Add link on the right
hands side of Sources. The will show the Add/Modify source
drop-down dialog.

Session
Under Session the session to use as source is selected. It can be
the current profiler session, or an external session file (selected
using the Browse button).

156 User Manual .NET Memory Profiler


Execution context
The Execution context settings can be used to define from which
execution context the real-time data should be retrieved (i.e.
process, runtime, or AppDomain). For the current session, this is
by default the same execution context as the current snapshot
selection.
Enterprise only (Enterprise only) NOTE. By adding the same session more
than once and then using the execution context, it is for
instance possible to present separate real-time graphs for
separate processes or runtimes in the same session.

Settings
The Settings group is used to define settings for the real-time
graphs and real-time series values. It includes the following
settings:
Averaging length
Defines the length of the averaging window, in seconds. This
setting is used for series where the value is calculated as moving
average.
When Moving average is selected as the value for a real-time series
(and graph), an averaging window is used to calculate the value. If
the averaging window is short (e.g. one second), this can cause the
graph to be a bit noisy, as can be seen in the screenshot below.

The Averaging length slider can be used to increase the size of the
averaging window. This will reduce the noise in the graph and can
make the graph easier to interpret.

.NET Memory Profiler User Manual 157


Accumulation interval
Defines the accumulation interval length, in seconds. This setting
is used for series where the value is accumulated over a time
interval.
Recent data accumulation interval
Same settings as the Accumulation interval, but this setting is
used for the recent data graphs.
Time origin
The Time origin field is used to select the time origin of the graphs.
This is especially useful if more than one source is included in the
real-time layout. The drop-down list is populated with the session
start time, and with the time markers from comments added using
the .NET Memory Profiler API.

NOTE. Currently the profiler only uses comments added by the


API as time markers. This will be extended in future versions of
the profiler.

By selecting matching time markers in multiple sources, the real-


time graphs will be aligned, and it will be easier to compare real-
time data from the source sessions.
End time
In addition to the time origin, it is also possible to specify the end
time of the real-time graph. If both the origin time and the end
time are specified for a source, the corresponding x-axis will be
locked for the time range. If multiple sources are used and the end
times are specified, then multiple x-axes will be included in the
graph, one for each source. This way it will be possible to compare
the memory usage behavior of an operation between separate
sessions, for instance to see how well an optimization works.

Real-time series
Below the graph settings, the included real-time series are
presented, grouped by the series category. Currently the following
categories are available:

158 User Manual .NET Memory Profiler


Events and annotations
The events and annotations category include real-time
events, such as snapshot collection, garbage collections,
and comments added using the profiler API.

Managed memory statistics


This category includes statistics of the memory usage
and garbage collections of the .NET runtime. For more
information about the information presented, see
Managed memory statistics on page 162.

Native resources statistics


This category includes statistics of the total resource
usage of the selected processes. For more information
about the information presented, see Native resources
statistics on page 163.

Types
This category includes memory usage information for
specific types. To make a type available as a real-time
series and to include real-time type information in the
graph, it must be marked for real-time collection using
the Types/Resources real-time view. The real-time data
available includes allocation and instances information
for the type. For more information about the
information presented, see Managed memory
statistics on page 162.

Resources
This category includes resource usage information for
specific resources. To make a resource available as a
real-time series and to include real-time resource
information in the graph, it must be marked for real-
time collection using the real-time Types/Resources
view. The real-time data available includes allocation
and instances information for the resource. For more
information, see Native resources statistics on page
163.

Performance counters (one per


performance counter category) (Enterprise only)
If performance counters are added to the layout, a
category group will be created for each performance
counter category. New performance counter categories
are added using the Add series link (see below).

.NET Memory Profiler User Manual 159


Within each category, the real-time series are presented. Each real-
time series is includes:
A checkbox to include/exclude the series from the
graph
A legend icon, which indicates how the series will be
presented in the graph, and acts as a button for series
settings.
Name of the series
The value(s) of the series; either the last collected value,
or the value at the time selected using the time selector.
One value is presented for each included source.

New series are added using the Add link (in the series category
header), or by using the Add series link below the series
categories. The Add link is used to an additional series in the
same category. The Add series link can be used to add series to
a new category.

Real-time series settings

160 User Manual .NET Memory Profiler


The real-time series settings are shown when the legend of a series
is clicked, or when new series are added. The following settings are
included:
Category
The category field is only included when adding series
to a new category (i.e. when using the Add series
link). It allows the category of the series to be selected,
such as a performance counter category, or one of other
categories presenter under .
Series
The category field is only included when adding new
series. It allows the series to add to be selected, base on
the current category.
Color
Allows the color of the real-time series to be selected,
when it is included in the graph.
Value
Indicates how the value of the series should be
calculated. This option is only available if more than
one way of calculating the series value is available. The
following options exists:
o Moving average
The value is calculated as a moving average, using
the averaging length specified in the settings.
o Accumulated over time interval
An accumulated value is calculated over a time
interval, using the time interval specified in the
settings.
o Accumulated from origin
The value is accumulated from the selected time
origin.
o Total accumulated
The value is accumulated from the start of the
profiler session.
Presentation
Indicates how the value should be presented in the
graph. This field is only included if more than one way
of presenting the value is available. This following
options exists:
o Line
o Scatter
o Line and scatter
o Mountain
o Bar

.NET Memory Profiler User Manual 161


o Event
Location
Indicates the placement of the graph. The graphs view
can be divided in up to four vertical panels. The
following options are available:
o Top
o Below top
o Above bottom
o Bottom
This setting only indicate the vertical order of the
graph, unused locations will not be shown. E.g. if all
included graphs are located at the Bottom, only the
bottom panel will be shown.

Managed memory statistics


The following real-time data is available under the Managed
memory statistics category:

NOTE. Several of the values will be updated only after a garbage


collect. These values are marked with an *.

Total instances
This is the total number of instances in the managed
heap, which includes both instances that are reachable
and instances that cannot be reached.
Live instances*
This is the number of live instances at the last GC.
Total bytes
This number shows the total number of bytes used by
all the instances in the managed heap, including both
instances that are reachable and instances that cannot
be reached.
Live bytes*
This number shows the number of bytes used by the
instances that were reachable at the last GC.
Allocs/sec
This number shows the number of allocations
performed per second. It can be presented as a moving
average, or be accumulated, either over a time interval
or since a specified start time.
Bytes/sec
This number shows the number of bytes allocated per
second. It can be presented as a moving average, or be
accumulated, either over a time interval or since a
specified start time.

162 User Manual .NET Memory Profiler


Disposed instances*
This number shows the number of instances that have
been disposed but that have not yet been garbage
collected.
Undisposed instances*
This number shows the number of instances of
disposable classes that have been garbage collected
without being properly disposed.
Gen #0 GCs*
This number shows the number of generation #0
garbage collects that have been performed.
Gen #1 GCs*
This number shows the number of generation #1
garbage collects that have been performed.
Gen #2 GCs*
This number shows the number of generation #2
garbage collects that have been performed.
Root references*
This number shows the number of root references that
existed at the time of the last GC.
Non-null root references*
This number shows how many of the root references
were not null at the time of the last GC.
Instance references*
This number shows how many references between
instances that existed at the time of the last GC.
Bytes moved*
This number shows how many bytes were moved when
the memory was compacted during the last GC.

Native resources statistics


The following numbers are presented under the native resources
category:
Total instances
This is the total number of unmanaged resource
instances that exists in the process (as tracked by the
resource tracker).
Total bytes
This number shows the total number of bytes used by
all the resource instances in the process (as tracker by
the resource tracker).
Allocs/sec
This number shows the number of resource instance
allocations performed per second. It can be presented

.NET Memory Profiler User Manual 163


as a moving average, or be accumulated, either over a
time interval or since a specified start time.
Bytes/sec
This number shows the number of bytes allocated by
unmanaged resource instances per second. It can be
presented as a moving average, or be accumulated,
either over a time interval or since a specified start
time.

Real-time Types/Resources

The real-time Types/Resources view consists of a table that


shows real-time data for each type and resource in the profiled
process. The entries can be sorted by clicking on the column
headers.
The following columns are used to present information about each
class:
Collect
This column is used to indicate whether historical real-
time data should be collected for the type or resource. If
a type or resource is collected, it is made available as a
real-time series under the Settings and series pane.
Namespace/System
This column shows the namespace name of the type, or
system of the resource.
Name/Resource
This column shows the name of the type or resource.
Total instances
This column shows the total number of type or resource
instances that exists. For managed types, this includes
both instances that are reachable and instances that
cannot be reached.
Live instances (last GC)
For managed types, this column shows the number of
type instances that were reachable at the time of the
last GC.

164 User Manual .NET Memory Profiler


For all field sets except Dispose info, the following columns are
also included by default:
Total bytes
This column shows the total number of bytes used by
all instances of the type or resource. For managed
types, this includes both instances that are reachable
and instances that cannot be reached.
Live bytes (last GC)
This column show the number of bytes used by the
instances of the type or resource. For managed types,
this number only includes instances that were
reachable at the time of the last GC.
Allocs/sec
This column shows how many allocations of the type or
resource that have been performed during the last
second.
Bytes/sec
This column shows how many bytes have been
allocated for the type or resource during the last
second.
If the Dispose info field set is selected, only disposable types are
included and the following columns are also included:
Disposed instances
This column shows the number of type instances that
were disposed at the time of the last GC, but are still
reachable.
Undisposed instances
This column shows the number of type instances that
have been garbage collected without being properly
disposed.

Working with the Graph


To control the scaling of the axes and the appearance of plots, a set
of commands and an axis scroll bar are provided. A data reader is
also provided to facilitate reading data values in the graph.
Commands
Scale to Show All When checked, the x-axis is scaled to
include all available data.
Autoscale Right When checked, the x-axis is scaled to
Side X include the time of the last data point.
The left side of the x-axis is not
automatically modified. This has the
effect of condensing the contents of
the graph whenever new data are
added.

.NET Memory Profiler User Manual 165


Lock X-axis When checked, the x-axis is scaled to
Range include the time of the last data point
without modifying the length of the x-
axis. This has the effect of scrolling the
contents of the graph whenever new
data are added.
Connect GC Data When checked, data that are collected
only at garbage collects is connected
with lines. If the command is not
checked, GC data are shown only as
small circles.
Include Zero When checked, the y-axes are scaled to
include both zero and the highest
value of the plots. If the command is
not checked, the y-axes are scaled only
to show the lowest and the highest
values of the plot.
Show time When checked, the time selector is
selector shown in the graph when moving the
mouse over the graph. For more
information, see Session Time
Selector on page 168.
Show recent data When checked, recent real-time data is
shown in more details on the right side
of the graph. For more information,
see Recent data graph on page 167.
Use separate When checked, the recent data uses a
scale for recent separate y-axis, to allow more detailed
data information to be presented for the
recent data. If not checked, recent data
and old data uses the same scaling.

Axis Overview Bar

The axis overview bar gives you an overview of the collected real-
time data and allows you to manually select the x-axis range of the
graph. Below is an explanation of the different parts:
Left shaft

166 User Manual .NET Memory Profiler


Clicking this part will scroll the x-axis one page to the
left. All autoscaling of the x-axis will be stopped when
scrolling the axis.
Left axis end box
Dragging this part will change the position of the left
side of the x-axis. If the axis scaling is set to Scale to
show all before dragging this box, the axis scaling
will be changed to Autoscale Right Side X.
Axis scroll box
Dragging this part will scroll the entire x-axis to the left
or to the right. All autoscaling of the x-axis will be
stopped when dragging the scroll box.
Right axis end box
Dragging this part will change the position of the right
side of the x-axis. All autoscaling of the x-axis will be
stopped when dragging this box.
Right shaft
Clicking this part will scroll the x-axis one page to the
right. All autoscaling of the x-axis will be stopped when
scrolling the axis.

Data Reader

The data reader can be used to read the value at a specific location
of a plot. The data reader is enabled when the time selector is
disabled. Simply move the mouse over a plot to read the value of
the plot. When the cursor is close enough to a plot, a tooltip
window will appear, showing the name of the plot and the X-
(time) and Y-value of the plot at the location of the cursor.

Recent data graph


Recent data can be shown in more detail by selecting the "Show
recent data" option in the Graph toolbar. When this option is
enabled, the graph is divided into two horizontal parts. The right
side of the graph presents the most recent real-time data, and the
left side presents older data. The length of the recent data part is
specified using the drop-down list to the left of the Show recent
data checkbox.

.NET Memory Profiler User Manual 167


Session Time Selector

The time selector is used to select the time for which the real-time
information should be presented. It is enabled using the Show
time selector command. When the time selector is enabled, the
mouse can be moved over the graph to select the time for the real-
time data. The numbers in the statistics view and the
Types/Resources table will be updated to reflect the selected time.
There can be a slight delay until the updated values have been
retrieved, especially when remote profiling. During this delay, the
old numbers will be presented in a gray color.
It is possible to lock the time selector at a specific time by left-
clicking in the graph. This makes it possible to move the mouse
away from the graph, for instance to select a type or resource in the
Types/Resources view. The time selector will be unlocked if the
mouse is moved into the graph again, or by left clicking in the
graph again.

NOTE! If the time selector is moved to the left of the first data
point, then no values will be shown.

168 User Manual .NET Memory Profiler


Reducing Data
As mentioned earlier, all real-time data that are collected from the
profiled process are stored in a history. Since storing data for an
extended period of time will use increasing amounts of memory,
the stored data have to be reduced. There are two limits
determining the amount of memory used for the real-time data
history:
1. Maximum memory used by global memory statistics
and types and resources that are included in the graph.
2. Maximum memory used by types and resources that
are not included in the graph.
When a limit is reached, data are removed from the beginning of
the affected histories until the memory used is below the limit
again.
Having two limits allows data to be collected for all types and
resources, not just types and resources that are included in the
graph. If all types and resources were to be collected and only one
limit were used, the amount of memory used by types and resource
not included in the graph (presumably not very important data)
would overwhelm the amount of memory used by global statistics
and included types and resources. There may be thousands of
types in the profiled process, but probably only a few of them are
included in the graph. On the other hand, not collecting data from
types and resources not included in the graph would lead to
missing data before you get a chance to include the item in the
graph.
The default limits for data reduction are:
1. 1,024 Kbytes for memory used by global memory
statistics and types and resources with collection of
historical real-time data.
2. 2,048 Kbytes for memory used by types and resources
that are not collected.
These limits can be changed using the Tools->Options form, or
the session or project property pages.

Dispose Tracker
The dispose tracker is a powerful tool for tracking memory
problems pertaining to disposable types. Any type that implements
IDisposable signals that all its instances should be disposed as
soon as they are not needed anymore. Often these types wrap
unmanaged resources, such as file handles, database connections,
bitmaps, etc. The types may also be disposable because they
contain references to other disposable instances, or they simply
need to know when they are not needed anymore.

.NET Memory Profiler User Manual 169


By using finalizers, disposable classes wrapping unmanaged
resources can usually handle the clean-up of its resources. One
problem is that there is no guarantee when the finalizer will be
called, it may very well take a long time. For scarce resources such
as file handles and database connections this can prove to be a very
significant problem. There is also a cost involved with using
finalizers.
Another problem is that the garbage collector has no notion of the
cost of an unmanaged resource. For instance, a bitmap may use
several megabytes of memory, but the garbage collector only sees
the memory used by the instance keeping a handle to the bitmap.
Additionally, the documentation suggests that, if Dispose is not
called properly, the finalizer will eventually clean up any
unmanaged resources and the instance will be garbage collected.
However, this is not always the case. Instances of some classes in
the framework will never be finalized and garbage collected unless
they are disposed.
The abovementioned problems suggest that you should always call
Dispose on instances of disposable types, and the dispose tracker
helps you to make sure that all instances are disposed.
The dispose tracker is enabled by default unless low-impact
profiling is active. The dispose tracker does not use any additional
memory, and it has very low performance overhead, so it is
recommended that is always be enabled.
To view the information collected by the dispose tracker, the
Dispose info field set should be used. When this field set is
selected, some of the information presented in the different
profiler views is replaced by dispose information. For more
information about which information is replaced, see the
documentation about Field Sets on page 92.
The dispose information includes:
Disposed instances
The numbers presented for disposed instances
represent the number of instances that have been
disposed, but not yet garbage collected. For more
information, see Disposed Instances on page 170.
Undisposed instances
The numbers presented for undisposed instances
represent the number of instances that have been
garbage collected without being properly disposed. For
more information, see Undisposed instances on page
172.

Disposed Instances
Usually, the number of disposed instances for any type should be
zero or close to zero. If it is not zero, it may indicate a memory

170 User Manual .NET Memory Profiler


leak. However, there are several possible causes for disposed
instances to exist:
1. There are still short-lived references to the instance,
e.g. it may still be referenced by a local variable or an
argument. In this case, when collecting another
snapshot, the instance should have been garbage
collected.
2. The instance is part of a pool. Disposing the instance
simply returns it to the pool to allow it to be reused. In
this case it is normal for the instance not to be garbage
collected, and it is no indication of a memory leak.
3. Something else references the instance. This is a very
likely memory leak, since usually the instance should
no longer be used after it has been disposed. Use the
root paths under instance details to try to find out why
the instance has not been garbage collected.
An instance is usually considered to be disposed as soon as the
Dispose() method is called, but it is possible for a disposable class
to hide the Dispose method and perform the disposal of the
instance using a method with a more suitable name instead. For
instance, several classes prefer the name Close(). According to
the Dispose pattern guideline, the method replacing Dispose
should just call Dispose. Unfortunately, there is a possibility that
the hidden Dispose method calls the replacing method. For
instance:

public class ResourceWrapper : IDisposable


{
public virtual void Close()
{
// Release unmanaged resources.
//

GC.SuppressFinalize( this );
}

void IDisposable.Dispose()
{
Close();
}
}

In this case, there is a risk that the disposal of the instance is


missed and that the instance will be considered undisposed when
collected.
An instance is considered to be disposed if:
1. The Dispose() method,or
IDisposable.Dispose() if the method is hidden, of
the instance is called, before any call to Finalize().

.NET Memory Profiler User Manual 171


2. The Dispose(bool) method of the instance is called
(if it exists), with true as argument, before any call to
Finalize().

Undisposed instances
If all instances of a class are properly disposed, the number of
undisposed instances will be zero. As mentioned previously, it is
preferable to make sure that all instances are properly disposed,
but there is a set of disposable classes whose instances do not need
to be disposed. These classes do not contain unmanaged resources,
do not reference other disposable classes, do not need to be
cleaned up, and do not have a finalizer. Usually these classes
should not be disposable in the first place, but they might be
derived from a base class that expects its derived classes to
possibly contain unmanaged resources, or they might be used as
base classes for other classes that may contain unmanaged
resources.
An example of a disposable class that does not need to be disposed
is the System.IO.MemoryStream class, since it only references
managed memory and has no finalizer. It is derived from
System.IO.Stream, an abstract class that can expect classes
derived from it to contain unmanaged resources, e.g., file handles
and network sockets. It therefore implements IDisposable, even
though not all derived classes will contain unmanaged resources,
e.g., System.IO.MemoryStream.
Even though there are disposable classes whose instances do not
need to be disposed, it is recommended that all instances of all
disposable classes always be disposed, unless you are certain that
an instance does not need to be disposed.

NOTE! There are several disposable classes in the framework


whose instances are not always disposed. You should not try to
dispose these instances yourself, even if you have a reference to the
instance. For example, instances of PaintEventArgs are not
always disposed, and it would be possible to dispose them at the
end of the OnPaint method, but that might have undesired
consequences. You must only dispose an instance if you clearly
know that you are the one responsible for disposing it, and that it
is not being used elsewhere.

Heap Utilization Tracker


The heap utilization tracker can be used to analyze and optimize
the way the garbage collected heap is used. Tracking heap
utilization is an advanced feature that is disabled by default. In
order to analyze the information provided by the heap utilization

172 User Manual .NET Memory Profiler


tracker, you should have a good knowledge of how the generational
garbage collector of the .NET runtime works.
The heap utilization tracker keeps track of the generation of each
allocated instance and whether the instance was allocated in the
large object heap. It then records in which heap (generation #0,
#1, #2 or large) the instance was garbage collected or in which
heap it resides at the time of the snapshot if it still has not been
garbage collected.
Usually, when a heap snapshot is collected, a full garbage
collection is performed, and thus all surviving instances will reside
in the generation #2 heap, but, when heap utilization tracking is
enabled, it is also possible to collect a heap snapshot using only a
generation #0 garbage collect. This will lower the profilers
influence on the generations of the heap and will also allow
unreachable instances to be counted.
You should only use the generation #0 heap snapshot when doing
heap utilization analysis. The normal snapshot is more thorough in
making sure that all unreachable instances have been garbage
collected.

NOTE! To get more accurate numbers of the heap utilization, you


should try to make sure that several garbage collections of all
generations have been performed between two consecutive
snapshots.

Example:
Assume that 1000 instances have been allocated since the
comparison snapshot and that the selected snapshot was
collected using a generation #0 garbage collection 100
seconds later.
900 instances were garbage collected before the
selected snapshot
o 700 were garbage collected by the first
generation #0 GC
o 100 were garbage collected by the first
generation #1 GC
o 100 were garbage collected by a generation
#2 GC
25 instances are live in generation #1 at the time
of the selected snapshot
75 instance are live in generation #2 at the time
of the selected snapshot
If we sum this up, the distribution of the 1000 instance
allocations is as follows:
Generation #0: 700 instances

.NET Memory Profiler User Manual 173


Generation #1: 100 + 25 = 125 instances
Generation #2: 100 + 75 = 175 instances
If Show heap utilization as percent is selected, then
the heap distribution numbers are presented relative to the
total number of allocations:
Allocs (or Allocs/sec): 1000 (or 10/sec)
Allocs in gen #0: 70%
Allocs in gen #1: 12.5%
Allocs in gen #2: 17.5%
If Show heap utilization as percent is not selected, the
heap distribution numbers will be presented in the same
way as the total number of allocations (i.e., it depends on
the /sec setting).

Unreachable instances
If a generation #0 heap snapshot has been performed, it is possible
that there are instances left on the heap that are not reachable
from any root. The reason for this is that the garbage collector does
not make a full reachability analysis when performing a generation
#0 collection and does not know whether some instances are
reachable or not.
The number of unreachable instances of each type is presented
when showing heap utilization information. This number can be
used to analyze how well the garbage collected heap is utilized.

Unmanaged Resources Tracker


Professional and The unmanaged resources tracker allows the profiler to present
Enterprise only detailed information about unmanaged resources, such as heap
memory, bitmaps, and windows. The information presented
includes:
Resources overview
An overview of all resources with allocated instances is
presented together with the managed types in the
Types/Resources view. For more information, see
Overview Page on page 113.
Resource details
The details of a specified resource can also be
presented. The details include a list of all live instances
of the resource and information about the call stacks
that have allocated the instances. For more
information, see Type/Resource/Filter Details Page
on page 119.
Resource instance details

174 User Manual .NET Memory Profiler


Information about a specific resource instance is
presented under the Instance details page. This
information includes the allocation call stack, nested
resource instances, and managed instances that wrap
the resource instance. For more information, see
Instance Details Page on page 128.
Real-time resources overview
If real-time data collection is enabled, the real-time
view includes information about the number of
allocated resource instances and live resource
instances. For more information, see Real-Time Page
on page 151.

The resource tracker is enabled using the Enable unmanaged


Resources check box on the General settings page.

Resource Tracker Limitations


In order to track resources, the resource tracker makes low-level
modifications in the profiled process. Even though there are no
known problems with these modifications, there is a risk that they
can cause problems in the profiled process (including unexpectedly
terminating the process).
Additionally, the unmanaged nature of resource creation and
destruction makes it hard to guarantee that all resources are
correctly tracked. There is a risk that the profiler will fail to track
some resource creations or destructions. If there is a risk that the
destruction of an instance will not be tracked, the resource tracker
will ignore the instance. This minimizes the risk of presenting
instances that do not actually exist at the cost of missing some
instances.
If you notice any resource problems with the resource tracker, e.g.,
released instances that are still presented by the profiler, please
inform us by sending an e-mail to memprofiler@scitech.se.

Creation Context
When an unmanaged resource instance is created, the call stack
and the instance are associated with a creation context. The
creation context indicates how the resource instance was created.
Below is a presentation of the different creation contexts that exist:

Managed runtime
The "managed runtime" creation context indicates that
the instance was created by the runtime itself, e.g.,
internal structures used when loading classes and
JITting.

Unmanaged interop

.NET Memory Profiler User Manual 175


The "unmanaged interop" creation context indicates
that the instance was created using a P/Invoke call, i.e.,
by managed code that makes a call to an unmanaged
function.

Other unmanaged
The "other unmanaged" creation context indicates that
the instance was created by a thread that has not run
any managed code.

AppDomains Tracker
The AppDomains tracker can be used to associate instances with
the AppDomain they were created in. The AppDomains tracker is
particularly useful when profiling ASP.NET applications, or other
applications that rely on AppDomains for separation.
The AppDomains tracker is enabled by using the Enable
AppDomains tracker check box General page under the
session settings or in the start profiling wizard.
If the AppDomain tracker is enabled, the AppDomain is recorded
for each instance allocation (both managed instances and
unmanaged resource instances). When comparing snapshots that
contain AppDomain information, an AppDomains selector will be
visible in the profiler window. This selector can be used to filter the
snapshot data so that it only includes information about instances
allocated in the selected AppDomain.

NOTE! The AppDomain filter will not affect the information


presented in the Native memory view.

NOTE! It is not always possible to associate an instance with an


AppDomain. The runtime can create instances internally, and
unmanaged resource instances can be created in a native thread.
To retrieve information about instances that are not associated
with any AppDomain, the AppDomain selector must be set to show
(all) AppDomains.

Call Stacks Reduction


Each time a managed instance or unmanaged resource instance is
allocated, the allocation call stack is recorded. The allocation call
stack is a very important piece of information when analyzing how
memory and resources are used by the profiled process. To be able
present the call stack information, .NET Memory Profiler must
store the contents of each unique call stack. If too many unique call
stacks exist, the memory usage within the profiler and the profiled

176 User Manual .NET Memory Profiler


process might become too high. The performance will also suffer,
especially when viewing methods information in the profiler.
To mitigate the problem with high memory usage and bad
performance, it is sometimes necessary to reduce the number of
call stacks stored. The call stack reducer is responsible for
analyzing the call stacks and remove the least important call stack
frames. For more information about the call stack reducer, see
Call Stack Reducer on page 177.

Limiting Call Stack Depth


NOTE. In the current version of the profiler, the call stack depth is
not (and cannot be) limited, but if opening session files created by
an older version of the profiler, the call stack may be truncated.

Limiting the call stack depth is an efficient way of limiting the


memory usage of the call stacks information. However, truncating
call stacks will obviously also cause some information to be lost.
This is particularly evident when investigating allocations
performed by a method and all its child allocations. If the method
has been truncated from any call stack, the child allocation
information is no longer accurate. This is indicated in the methods
view by coloring the allocation data gray, and providing
information about the truncation in the tool tip (as can be seen in
the screenshot below).

Call Stack Reducer


The call stack reducer rates the importance of all functions in all
call stacks, and keeps a count of the number of call stack frames
that exist. If the number of frames exceeds a threshold (defined by
the Max skippable call tree nodes setting), the call stacks
reducer will skip functions that are deemed to be "least important".
It will skip as many functions as necessary to make the number of
call tree nodes less than the threshold.
The importance of a method or function in a call stack is based on
several parameters. The parameters include:
Whether it is a private, public, or source method
Source methods are more important than other
methods, public methods are more important than
private methods.

.NET Memory Profiler User Manual 177


Whether it is a native function or a managed method
How close the function is to a source function or the
function making the allocation
Functions that are close to a source function or the
function making the allocation, are considered more
important than functions "in the middle".
How much memory will be saved if the function is
skipped
The parameters are combined for each function, and the combined
parameters will provide a "level of importance" for the function.
The "level of importance" will then be used to decide what
functions should be skipped when reducing the call stacks.
When a function is excluded from a call stack, it is replaced with an
entry named [Skipped frame(s)]. If two or more adjacent functions
are skipped, only one [Skipped frame(s)] entry will be added,
which will cause the stack depth to be decreased.
There is a slight performance penalty when using the call stacks
reducer, but the result is often a good compromise between
reducing the memory used by call stacks and providing adequate
call stack information.

GC Handle Identification
GC handles are used to create handles to managed instances. They
act as roots for the garbage collector and can be used to prevent an
instance from being collected, to pin a managed instance in
memory, or to create a weak reference to an instance. The .NET
Framework provides access to GC handles through the
System.WeakReference class and the
System.InteropServices.GCHandle structure. The runtime
also uses GC handles internally to keep track of certain instances,
such as managed COM interfaces and static field data.
.NET Memory Profiler can identify the internal GC handles that
are created by the runtime itself or by using the WeakReference
and GCHandle types. If GC handle identification is enabled (using
Preferences in the Options dialog), a pseudo-Type called
<GCHandle> will be presented by the profiler. This type
represents the internal GC handles used by the runtime; it does
not map to a real managed type. The <GCHandle> type and its
instances can be investigated in the same way as any other
managed type, e.g., by viewing the details of the type or the
instances.
Root Kind
A GC handle acts as a root for the garbage collector, and,
depending on the kind of root, it will affect the garbage collector in

178 User Manual .NET Memory Profiler


different ways. Below is a list of root kinds and descriptions of how
they affect the garbage collector.
Weak
A weak GC handle will not prevent the instance it
corresponds to from being garbage collected. Weak GC
handles are, for instance, used by the
System.WeakReference class.
Pinned
A pinned GC handle prevents the corresponding
instance from being garbage collected and from being
moved in memory.
Normal
A normal GC handle prevents the corresponding
instance from being garbage collected.
RefCounted
A reference counted GC handle is used internally by the
runtime, e.g., when dealing with COM interfaces.
GCHandle Root Identification
Normally a <GCHandle> root is not considered to be identified
when calculating root paths in the Type details and Instance
details view. That is, a root path ending in a <GCHandle> will not
be presented if the Only include identified roots option is
enabled.
However, if the Treat System.InteropServices.GCHandles
roots as identified option is enabled in the Preferences screen
and the runtime <GCHandle> is stored in a GCHandle structure
field (or a boxed GCHandle instance), it will be treated like an
identified root.

NOTE! This can considerably affect the way the root paths are
presented for some types and instances. For example, a top level
System.Windows.Forms.Form is kept alive using a <GCHandle>
allocated using GCHandle.Alloc. If GCHandle roots are treated

.NET Memory Profiler User Manual 179


as identified, the first root path will be a direct root to the top-level
form, as can be seen in the picture below.

If GCHandle roots are not treated as identified, the direct root will
not be included, as can be seen in the picture below.

<GCHandle> Type Details


The type details of the <GCHandle> pseudo-type include the same
information as for any other type, with two differences.
1. The Instances list contains one additional column (Root
kind) that provides information about the kind of root.
2. The Size (with children) column is not available in the
Instances list.
<GCHandle> Type Instance Details
The type instance details of a <GCHandle> instance include the
same information as any other instance. Additionally, the root kind
of the GC handle is included in the info panel at the top.

180 User Manual .NET Memory Profiler


WeakReference and GCHandle Presentation
The implementation of WeakReferences and the managed
GCHandle structure makes use of the runtime GC handles, and
this is reflected in the presentation of instance details of these
types.
If GC handle identification is enabled, the References list in the
Type instance details view will include a reference to the
<GCHandle> instance, as shown below.

If GC handle identification is not enabled, the list will include a


direct reference to the target of the GC handle, as shown below.

Visual Studio Integration


.NET Memory Profiler can be integrated into Visual Studio 2010,
Visual Studio 2012, Visual Studio 2013, Visual Studio 2015, and
Visual Studio 2017. This integration allows you to start profiling
processes within the development environment, as well as to open
previously stored session files.
Working with .NET Memory Profiler within Visual Studio is very
similar to working with the stand-alone version, but some
differences exist.
In Visual Studio, each session (active or previously stored) is
presented in an editor window that gives you the possibility of
working with multiple sessions simultaneously.
Profiling is started using the same commands as the stand-alone
version (Profile Application, Profile ASP.NET, Profile
Service and Attach to Process), except that the commands are
located in the Profiler menu and the Attach to Process
command is named Attach to Profiler Process. In Visual

.NET Memory Profiler User Manual 181


Studio it is also possible to start profiling a Visual Studio project in
a solution. For more information see the next section.

Start Profiling a Project


To start profiling the project defined as the Startup Project in a
solution, select Start Memory Profiler from the Profiler
menu. To start profiling any project in the solution, use the right
mouse button on the wanted project in the solution explorer and
select Start Memory Profiler.
If a profiler project is set as active, the started profiling session
will be associated with the active profiler project, and the
settings from the profiler project will be used (except the
Launch settings, which are overridden by the solution
project settings).
The profiler will use the Debug Mode setting under Debugging
Configuration Properties of the project to decide how to start the
profiler:
Project
If the project is a Windows Application or Console
Application project, this will start profiling the
application. The Command Line Arguments and
Working Directory properties are used to provide
arguments and the initial directory for the application.
If the project is an ASP.NET project, then ASP.NET
profiling will be started and the Start Page will be
requested.
Note that class libraries cannot be profiled using this
option.
Program
Indicates that a specific program should be used to start
profiling. For example, you might run a pre-built client
that consumes your Class Library project. You must use
the Start Application property to define what program
to start.
URL
Indicates that a particular URL (Start URL) should be
accessed to initiate profiling. For example, you might
access the URL to a web site that uses your Class
Library project.
When the Start Memory Profiler command is selected, a new
profiler session window will be created, and the process to profile
is started directly.
If multiple start-up projects are selected in the solution the action
performed depends on the edition of the profiler. In the Enterprise
edition, all start-up projects will be started and memory usage
information will be collected for all processes. In the Standard and

182 User Manual .NET Memory Profiler


Professional editions, only the first start-up project will be started,
and memory usage information will only be collected from one
process.

Debug Profiling
Professional and It is also possible to start a profiling session that runs under the
Enterprise only Visual Studio debugger. To start a debug profiling session,
select the Debug with Memory Profiler command under
Profiler menu. This will start the profiling session similar to the
way it is started using the Start Memory Profiler command.
When debug profiling is enabled, the instance number for each
instance is presented in all watch windows (Watch, Locals , Auto,
and debugger tool tips), making it easier to identify instances while
debugging.

A visualizer is also provided for each instance presented in the


watch windows. It is accessed using the magnifying glass at the
side of the instance value.

Selecting the Profiler visualizer will show the instance details of


the selected instance, including information like the allocation call
stack, root paths, and a full instance graph.
It is also possible to collect heap snapshots while stopped at a
breakpoint. This makes it possible to investigate the memory usage

.NET Memory Profiler User Manual 183


of a specific operation within the debugger. For example, it is
possible to stop at a breakpoint before making a method call,
collect a heap snapshot, step over the method call and collect a
new snapshot. The memory usage of the method can then be
investigated by comparing the two collected snapshots.

NOTE! The profiler visualizer and the instance numbering are


only available when debugging a 32-bit process. 64-bit processes
use a remote debugger and the profiler is not able to inject
additional information in the watch windows.

Profiling the Azure Compute Emulator


Enterprise only If the Visual Studio start-up project is an Azure project and the
Start Memory Profiler command is selected, the profiler
will extract the Azure compute emulator settings from the
solution and profile the Azure compute emulator processes.
When starting to profile the Azure compute emulator, the profiler
will shut down the emulator if it is already running, and then
restart it with profiling enabled. Currently the following processes
will be profiled when profiling the compute emulator:
IISExpress.exe (if IIS Express is used)
w3wp.exe (if IIS is used)
waiishost.exe
waworkerhost.exe

Run Tests under the Profiler


Enterprise only In order to present memory usage information and perform
memory assertions when running unit tests, the unit test
runner must run under the profiler. The enterprise edition
includes the possibility to easily use the Visual Studio test
runner to run tests under the profiler.
The Run Tests under the Profiler command (under the Profiler
menu) is used to create a unit testing session. As long as this
session is active, all unit tests started using the Visual Studio test
runner, will be run under this session. This includes the context
menu commands in the code editor as well as the commands
available in the Visual Studio Test Explorer.

NOTE! The unit test execution engine will be restarted when


starting or stopping the unit testing session. Visual Studio may
also restart the execution engine between tests. If the execution
engine is restarted while profiling unit tests, the profiler will
automatically profile the new execution engine process.

184 User Manual .NET Memory Profiler


To stop profiling unit tests, de-select the Run Tests under the
Profiler command, or stop the unit test profiling session.

Open a Previously Saved Session


A previously saved session can be opened using the Open->File
command under the File menu of Visual Studio. In the current
version, there is no entry for Profiler Sessions in the Files of Type
dropdown list. To select a profiler session, select All files in the
list.

Access Profiler Settings


It is possible to change session settings within Visual Studio. To
change the default session settings, use the Tools->Options
command. The Options dialog includes an additional entry
named .NET Memory Profiler under which the preferences
page and the default session settings pages can be reached. If a
profiler project or a profiler session window is selected, View-
>Property Pages can be used to edit the project or session
settings. For more information, see Session Settings on page 98.

Commands in Visual Studio


Most menu and toolbar commands are the same for both the
stand-alone version and the integrated version, with a few
differences. Below is a presentation of all the commands available
from within Visual Studio:
Commands on the File menu:
Open->File The Open->File command in Visual
Studio can be used to open a
previously saved session file. Currently
there is no entry for Profiler Sessions
in the Files of Type dropdown list.
To select a profiler session, select All
files in the list.

Commands on the Edit menu:


Copy Copies data from the selected item in
the currently selected control to the
clipboard. For more information see
Copying Data to the Clipboard on
page 93.
Copy All Copies all data from the currently
selected control to the clipboard. For
more information see Copying Data
to the Clipboard on page 93.

.NET Memory Profiler User Manual 185


Commands on the View menu:
Show Allocs and This command affects all columns and
Bytes per Second fields that present the number of
allocations performed and bytes
allocated. If this command is checked,
the values of those fields and columns
will be divided by the elapsed time
between the snapshots. Otherwise the
actual allocation- and byte-count will
be presented.
Show Heap This command affects all columns and
Utilization as fields that present information about
Percent the heap utilization. If this command
is checked, those fields and numbers
will be presented as percentages of the
total number of allocations performed
between snapshots. Otherwise, the
way they are presented is determined
by the Show Allocs and Bytes per
Second setting. This command is only
available if heap utilization tracking is
enabled. For more information, see
Heap Utilization Tracker on page
172.
Show [Field set] Allows you to select how the heap
information should be presented. It
will affect which columns are shown in
the tables and how the fields in the
info panels are presented. For more
information see Field Sets on page
92.
Show Failed If at least one memory assertion has
Memory failed, this command will bring up a
Assertions dialog that allows you to view
information about the failed memory
assertions.
Details Back Steps back to the previously shown
information. This can, for instance, be
useful if you want to look at the details
of a referrer of an instance and then
get back to the original instance.
Details Forward Steps forward through details
information previously left using
Details Back.

186 User Manual .NET Memory Profiler


Show Details Shows details about the selected item.
Show Source If the selected item is a type or
resource, the type/resource details
page will be shown, if it is an instance,
the instance details page will be
shown. If the selected item is a method
(in a call stack) and source file
information is available, this
command will be named Show
source and will show the source of
the method when selected.
Call stack Defines which functions/methods
functions should be included when viewing call
stacks. The available options are:
Source, Publically visible, and All.
Show conditional Enables or disables conditional
formatting formatting in the Overview page.
Conditional formatting indicates how
a presented cell value relates to the
total (or max) value of a column, and
whether the value has increased or
decreased since the comparison
snapshot.
Use totals for Determines if the total value of a
conditional column should be used for conditional
formatting formatting. If not selected, the
maximum value is used instead.
Profiler Layout- Opens the column chooser window.
>Column chooser For more information, see Column
Layout and Customization on page
95.
Profiler Layout- Toggles auto-adjustment of table
>Auto-adjust columns. For more information, see
column widths Column Layout and Customization
on page 95.
Profiler Layout- Resets the layout of columns and tool
>Reset layout windows. For more information, see
Column Layout and Customization
on page 95.

Command on the View->Other Windows menu


Profiler Projects Shows the Profiler Projects Explorer
Explorer window. For more information, see
(Professional and Profiler Projects on page 79.
Enterprise only)

Commands on the Profiler menu:


Start Memory Starts profiling the start-up project of
Profiler the loaded solution. For more
information, see Start Profiling a
Project on page 182.

.NET Memory Profiler User Manual 187


Debug with Starts profiling the start-up project of
Memory Profiler the loaded solution, under the Visual
(Professional and Studio debugger. For more
Enterprise only)
information, see Debug Profiling on
page 183.
Launch using Starts profiling using the settings from
Memory Profiler the currently active profiler project.
Project For more information, see Profiler
(Professional and
Projects on page 79 and the How
Enterprise only)
to topic Start Profiling using a
Profiler Project on page 23.
Run Tests under Creates a unit test session under which
Profiler all Visual Studio unit tests will be run.
(Enterprise only) For more information, see Run Tests
under the Profiler on page 184.
Profile Starts a wizard that helps you profile a
Application stand-alone application. For more
information, see Start Profiling an
Application on page 4.
Profile ASP.NET Starts a wizard that helps you profile
an ASP.NET application. For more
information, see Start Profiling
ASP.NET on page 4.
Profile Windows Starts profiling a Windows Store App
Store App with the help of a wizard. For more
information, see Start Profiling a
Windows Store App on page 5.
Profile Silverlight Start profiling a Silverlight application
application with the help of a wizard. For more
information, see Start Profiling a
Silverlight Application on page 8.
Profile WPF Starts profiling a WPF browser
browser application with the help of a wizard.
application For more information, see Start
Profiling a WPF Browser Application
on page 9.
Profile Windows Starts a wizard that allows you to
Service profile a Windows Service. For more
information, see Start Profiling a
Windows Service on page 9.
Attach Profiler to Starts a wizard that allows you to
Process attach the profiler to a running .NET
(Professional and process. For more information, see
Enterprise only)
Attach to a Process on page 20.
Import Memory Starts a wizard that allows you to
Dump import memory dump files as heap
(Professional and snapshots. For more information, see
Enterprise only)
Import Memory Dump Files on page
21.

188 User Manual .NET Memory Profiler


Start Restarts a profiler session. This
command is only available after an
active session has been stopped.
Stop Stops the currently active profiler
session.
Collect Heap Collects a snapshot of the GC heap and
Snapshot native memory. The results will be
presented under the snapshot pages.
Collect Gen #0 Collects a snapshot of the GC heap and
Heap Snapshot native memory by only doing a
generation #0 garbage collect. This
command is only available if heap
utilization tracking or low impact
profiling is enabled. For more
information, see Heap Utilization
Tracker on page 172.
Save Snapshot Saves the latest collected snapshot in a
temporary profiler session file.
Collect peak Collects the current peak snapshot. If a
snapshot higher peak is detected after the
(Professional and current peak has been collected, an
Enterprise only)
additional peak snapshot will be
collected when the session ends. For
more information, see Peak
Snapshots on page 78.
Reset peak Resets the current peak snapshot. New
(Professional and peak snapshot information will be
Enterprise only) collected at the next garbage
collection. For more information, see
Peak Snapshots on page 78.
Track peak Enables and disables peak snapshot
snapshots collection. When enabled, temporary
(Professional and snapshot information will be stored
Enterprise only)
each time a new peak has been
detected and a peak snapshot will be
collected when the session ends. For
more information, see Peak
Snapshots on page 78.
Manage ignored Opens the Ignored Analysis Issue
analysis issues window, which can be used to view
and modify the ignored analysis
issues. For more information, see
Modifying Ignored Issues on page
37.
Ignore Ignores analysis issues that are caused
framework issues by the .NET Framework. For more
information, see Ignoring Framework
Issues on page 52.

.NET Memory Profiler User Manual 189


Auto-detect Defines how duplicates should be
duplicates automatically detected by the memory
analyser. The options are: None,
Only trivial and All. For more
information, see Duplicate Instances
Detection on page 47.
Detect duplicates Starts investigation of all duplicate
instances. For more information, see
Duplicate Instances Detection on
page 47.
Only detect Limits the duplicate instances analyser
trivial duplicates to only detect trivial duplicates. This
can speed up the analysis significantly,
but all duplicates will not be detected.
Manage filters Opens the Manage filters window. For
more information, see Saving and
Managing Filters on page 76.
Rename Renames a previously saved snapshot.
Snapshot This command is only available if the
selected snapshot has been saved and
you are currently profiling a process.

Commands on the Profiler->Project menu:


New Profiler Starts a wizard that allows you to
Project create a new profiler project. For more
(Professional and information, see Profiler Projects on
Enterprise only)
page 79 and the How to topic
Create or Load a Profiler Project on
page 22.
Load Profiler Opens a profiler project and includes it
Project in the profiler projects explorer
(Professional and window. For more information, see
Enterprise only)
Profiler Projects on page 79 and the
How to topic Create or Load a
Profiler Project on page 22.
Save Profiler Saves the project that is currently
Project selected in the profiler projects
(Professional and explorer.
Enterprise only)
Save Profiler Saves the project that is currently
Project As selected in the profiler projects
(Professional and explorer to a new file.
Enterprise only)

In order to reduce the number of commands in the menus of


Visual Studio, several of the profiler commands are only visible
when a profiler session is shown in the active document window.
The most commonly used commands are also available in two
Visual Studio toolbars: Memory Profiler Control and
Memory Profiler Launcher.

190 User Manual .NET Memory Profiler


The NmpCore Tool

NmpCore is standalone tool for collecting snapshots and creating


session files on machines where .NET Memory Profiler is not
installed. Additionally, it also acts as an agent for remote profiling.
It is useful for gathering memory usage information on production
machines, end-user machines, or testing machines. For instance, it
can be used to attach to a running server process, collect one or
more memory snapshots and create a session file. This session file
can then be analyzed using .NET Memory Profiler on another
machine. This is a preferred alternative to creating a memory
dump and importing it on another machine.
NmpCore is a free tool that can be downloaded by anyone; it does
not require a .NET Memory Profiler license. Additionally, it is a
single file application that does not require any installation.
The latest version of NmpCore can be downloaded from
http://memprofiler.com/NmpCore.aspx. It is also included in the
.NET Memory Profiler installation. By default, it can be found at
C:\Program files\SciTech\NetMemProfiler5\NmpCore.exe.

NOTE. Professional and Enterprise only. The session files created


by NmpCore can only be opened and analyzed by .NET Memory
Profiler Professional; the Standard edition cannot be used.

Starting NmpCore
NmpCore can be started from a command line, using the
command:
NmpCore [<options>] <process>
To start NmpCore, the command line must at least specify the
process to profile or specify that NmpCore should run as a remote
agent. The process to profile can be specified using the following
command line arguments:

Argument Short Description


form
/attach <pid> /a Attach to a running process using
/attach <process name> the profiling API. Specify the
process using process id or
process name, e.g. /a 1234, or /a

.NET Memory Profiler The NmpCore Tool 191


SomeProcess.exe. Requires that
the process runs under .NET
Framework 4.0 and has
concurrent GC disabled. For
more information, see Attach to
Process using Profiling API on
page 215.
/program <program name> /p Profile a standalone program.
<args> This must be the last command
line argument to NmpCore, since
all additional arguments will be
passed to the started program.
/asp /asp Profile an ASP.NET application,
hosted by IIS. Using this option
will cause NmpCore to stop the
IIS service and restart it with
profiling enabled.
/service <service name> /svc Profile a Windows Service. Using
this option will cause NmpCore
to stop the specified service and
restart it with profiling enabled.

Additional command line options can also be included to define


the session settings, and to define how snapshots should be
collected and how a session file should be created.
Some common options are:
Argument Short Description
form
/collectandstop <count> /cs Collects the specified number of
snapshots and then stops the
profiler. The snapshot collection
interval is specified using the
/autocollect argument. If the
/autocollect argument is not
included, the default collection
interval of 10 minutes is used.
/autocollect <interval> Enables automatic snapshot
collection and sets the collection
time interval (in minutes).
/sessionfile <file path> Specifies the name of the session
of the session file that should be
created. If no session file name is
specified, as Save as window
will be shown when the profiling
has stopped.
/peaksnapshot [+/-] Enables or disables peak
snapshot collection.
/controlpanel [+/-] Shows or hides the NmpCore
control panel. The control panel
provides a user interface for
collecting snapshots manually
and for stopping the profiler. It is
shown by default unless the
/collectandstop argument has
been provided.

192 The NmpCore Tool .NET Memory Profiler


/register Temporarily registers NmpCore.
In order to profile a process
running under .NET Framework
prior to version 4.0
(2.0/3.0/3.5), NmpCore has to be
registered. This option will cause
an elevation prompt if User
Access Control is enabled. To
prevent the prompt each time
NmpCore is run, use the
/persistentregister option
instead.
/persistentregister Persistent registration of
NmpCore. Same as the /register
option, but the registration is not
removed when NmpCore exits.
Subsequent uses of NmpCore will
not require any registration.

In additional to the above command line arguments, all other


command line arguments for .NET Memory Profiler can be used,
except for /noui and /open. For more information, see Available
Command Line on page 27.
To start NmpCore as a remote profiling agent, use the following
command line arguments:
Argument Short Description
form
/remoteagent /ra Starts NmpCore as a remote
profiling agent. For more
information, see Remote
Profiling on page 80.
/remoteagentport /rap Specifies the port to use when
running NmpCore as a remote
profiling agent. For more
information, see Remote
Profiling on page 80.

Command Line Examples


Use the command line below to:
1. Attach to a process named SomeProcess.exe
2. Collect a single snapshot and stop profiling,
3. Save the session as
C:\Sessions\DumpSession.prfsession.
NmpCore /a SomeProcess.exe /cs1 /sf "C:\Sessions\DumpSession.prfsession"

The response file corresponding to the command line above:

.NET Memory Profiler The NmpCore Tool 193


# Attach to process with the name SomeProcess.exe (short form /a)
/attach SomeProcess.exe

# Collect a single snapshot and stop profiler (short form /cs)


/collectandstop

# Save session as DumpSession.prfsession (short form /sf)


/sessionfile c:\Sessions\DumpSession.prfsession

Another possibility is to collect a few snapshots in the same session


file. Use the command line below to:
Attach to a process named SomeProcess.exe
Collect three snapshots with a 5 minute delay between
the snapshots and then stop profiling.
Save the session as
C:\Sessions\DumpSession.prfsession.
NmpCore /a SomeProcess.exe /cs3 /ac5 /sf "C:\Sessions\DumpSession.prfsession"

A similar command line can also be used even when starting the
program from Nmpore. Note that the /p argument must come last.
NmpCore /cs3 /ac5 /sf "C:\Sessions\DumpSession.prfsession" /p <path>\SomeProcess.exe

NmpCore MSBuild Task


An MSBuild task is available that can be used to run NmpCore
when building a project using MSBuild. The NmpCore task is
available in the following NuGet packages:
SciTech.NmpCore.Task: Includes the free NmpCore
tool and the NmpCore MsBuild task.
SciTech.NmpCore.TestProject: Includes a .NET
Memory Profiler test project that will automatically run
unit tests under NmpCore after build. To activate the
NmpCore select "NmpCore" as the build action for the
file ProfileTest.prfproj.
To run the NmpCore task explicitly in a project, the NmpCore task
can be added to a target like this:
<Target Name="RunNmpCore">
<NmpCore Project="SomeProfilerProject.prfproj" />
</Target>

This target will start profiling a process based in the settings in the
provided profiler project.
The NmpCore NuGet package includes a target that will run
NmpCore on all files in the NmpCore item group. A profiler project
can be added to the NmpCore items by selecting the build action
NmpCore. The target forwards the following MSBuild properties to
NmpCore:
TargetPath, TargetDir, TargetName, TargetFileName

194 The NmpCore Tool .NET Memory Profiler


ProjectPath, ProjectDir, ProjectName, ProjectFileName
ConfigurationName
These properties can be used in the profiler project using the
MSBuild property syntax, e.g. $(TargetPath).
Using a profiler project is the easiest way of specifying the process
to profile, but it is also possible to specify profiling settings using
the task properties. Most of the properties maps directly to a
corresponding NmpCore command line argument. For more
information about the command line arguments, see Command
Line Arguments on page 26.
Below is a list of the available properties:

NmpCore task property Corresponding command


line argument
AppPoolNames /apppools
AttachToProcess /attach
AttachType /attachtype
AutoCollectInterval /autocollect
AutoCollectStopCount /collectandstop
CollectRealTime /collectrealtime
DisableInlining /disableinlining
EnableAllocationCallStacks /callstacks
EnableDisposeTracker /disposetracker
EnableResourceTracker /resourcetracker
IisExpressConfig /iisexpressconfig
IncludeInstanceData /includeinstancedata
InstanceTracking /instancetracking
MaxTriggeredSnapShots /maxsnapshots
MemLeakCollectFullSnapshot /memleakcollect
MemLeakHaltThread /memleaksuspend
MemLeakStopSession /memleakstopsession
PassThroughExitCode /passthrough
PeakMemoryThreshold /peaksnapshotthreshold
ProcessFilter /profileprocess
ProfilingLevel /profilinglevel
ProfilingType /profilingtype
ProgramArguments (arguments provided to the profiled
process)
ProgramPath /program
Properties /properties
RequestUrl /requesturl
SaveProject /saveproject
ServiceName /service

.NET Memory Profiler The NmpCore Tool 195


SessionEndAction /sessionend
SessionFile /sessionfile
ToolPath /toolpath
TrackAppDomains /appdomaintracker
TrackHeapUtilization /heaputil
TrackPeakMemory /peaksnapshot
WinStoreAppUserModelId /winstorepackage
WinStorePackageId /winstoreapp
WorkingDirectory /workingdirectory

The SciTech.NmpCore.TestProject NuGet package includes a


profiler project that can be used to profile a unit test project. The
profiler project can be edited using the XML-editor in Visual
Studio, or by opening the project in .NET Memory Profiler. If using
the XML-editor, it is recommended that only the StartInfo and
SessionSettings are modified. The test project contains
comments about the settings that can be modified, e.g. how to
change the unit testing framework.

.NET Memory Profiler API

The .NET Memory Profiler API can be used to control the profiler
within the profiled process, retrieve the memory usage (allocations
and instances), and to detect potential memory leaks using
assertions. This API is very well suited for doing automated testing
of memory usage errors, e.g., by using a unit testing framework
such as NUnit, XUnit, or VSTest.
The API can be accessed by adding the SciTech.MemProfilerApi
NuGet package. This package includes the class library
SciTech.MemProfilerApi.dll, which supports .NET
Framework 2.0 or later, and .NET Standard 1.1 or later. The class
library is also available under the Redist folder in the .NET
Memory Profiler installation folder (default location: C:\Program
files\SciTech\NetMemProfiler5\Redist).
This class library contains the two main classes of the API:
SciTech.NetMemProfiler.MemProfiler

196 .NET Memory Profiler API .NET Memory Profiler


SciTech.NetMemProfiler.MemAssertion
The MemProfiler class contains static methods that can be used
to:
Detect whether the current process is running under
the profiler (MemProfiler.IsProfiling).
Collect fast snapshots that can be used as a reference
when retrieving memory usage and doing memory
assertions (MemProfiler.FastSnapshot).
Collect full snapshots that will be saved by the profiler
(MemProfiler.FullSnapshot).
Retrieve memory usage information from within the
profiled process (MemProfiler.GetMemoryUsage).
Add comments that will be shown in the real-time
graph of the profiler (MemProfiler.AddComment).
The MemAssertion class contains static methods for asserting
that certain class instances do not exist (NoInstances,
NoNewInstances, and NoNewInstancesExcept). It also
contains methods for grouping several assertions into one
assertion session (BeginAssertions and EndAssertions).
For reference information about the .NET Memory Profiler API
methods, see the .NET Memory Profiler API Reference
documentation.

Retrieve Memory Usage Information


The GetMemoryUsage methods in the MemProfiler class can be
used to retrieve the current memory usage from within the profiled
process.
The memory usage includes information about all memory activity
that has occurred since a specified base snapshot. The information
is returned as a MemoryUsage object which provides access to
allocations information and live instances information.
The GetLiveInstancesInfo method can be used to retrieve
information about live instances, either for all types or a set of
specified types. The returned InstancesInfo includes
information about the count of new and total instances, and the
number of bytes used by the instances.
The GetAllocationsInfo method can be used to retrieve
information about allocations performed, either for all types or a
set of specified types. The returned AllocationsInfo includes
information about the number of allocated instances and bytes,
and the number of finalized and undisposed instances.
The types to include in the allocations information or the live
instances information can be specified using type set. For more

.NET Memory Profiler .NET Memory Profiler API 197


information about type sets, see Specifying Types using TypeSets
on page 207.
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.GetLiveInstancesInfo();


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.GetLiveInstancesInfo( 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 the profiler
assertions. However, instances will not be marked as potential
memory leaks when asserting memory usage using the
MemoryUsage class.
The code below shows how unit test assertions can be performed
when retrieving the memory usage.

198 .NET Memory Profiler API .NET Memory Profiler


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);

Use Assertions to Detect Memory Leaks


Another part of the API are the assertions, which can be used to
detect potential memory leaks.
In many cases, it is possible to know how an operation will affect
the memory usage of the managed heap when it is executed. For
instance, some operations should not create new live instances of
certain classes after it has finished. By using the assertion methods
in the MemAssertion class you can make sure that the memory
usage of the operation behaves as expected. There are two ways of
performing memory assertions:
Defining the assertions in an
AssertionsDefinition instance and then perform
the assertions using the MemAssertion.Assert
method.
Using the NoInstances, NoNewInstances and
NoNewInstancesExcept methods in the
MemAssertion class.
The AssertionsDefinitions approach requires slightly more
coding, but it is much more flexible and provides additional
memory checks, so it is the recommended approach when
performing memory assertions.
To perform a memory assertion, you have to perform the
following:
1. Establish a base snapshot using the method
MemProfiler.FastSnapshot().
The base snapshot is used as a reference when looking
for new instances.
2. Perform the operation that you want to check for
memory leaks.
3. Analyze the memory impact of the operation and write
memory assertions that checks that instances are
garbage collected as expected.
To catch as many memory leaks as possible, it is desirable to
include memory assertions that check for as many instances as
possible. The problem is that many operations may have side
effects on memory that are not easy to anticipate. For instance,
when performing an operation for the first time, new Types might
get loaded, creating unexpected new instances of RuntimeTypes

.NET Memory Profiler .NET Memory Profiler API 199


and Strings. It is therefore important to remember that the
instances that are identified as memory leaks are identified only as
potential memory leaks. The potential memory leak instances have
to be analyzed to decide whether they are real leaks or if they are
identified falsely as memory leaks by an incorrect memory
assertion.
The risk of falsely identifying instances as leaks is bigger when
using the MemAssertion.NoNewInstancesExcept methods
(or the MemAssertion.NoNewInstances and
AssertionsDefinition.NoNewInstances methods without
the Type argument), since these methods include all loaded types
in the process, except the ones that have been specifically selected
for exclusion. If these methods are used, do not perform the
assertions the first time the operation is performed, so that side
effects, e.g., from loading types, can be avoided.
Example:
Consider the ShowDialog method below, which shows a modal
dialog (derived from System.Windows.Forms.Form):
void ShowDialog()
{
using( SomeDialog dlg = new SomeDialog() )
{
dlg.ShowDialog();
}
}

Creating a dialog, showing it, and then disposing it, are operations
that should not create any new live instances. In reality, however,
quite a few new live instances might be created as a side effect of
creating the dialog. The first time the method is executed the
SomeDialog type might get loaded, creating a new live Type
instance (actually a RuntimeType), and new strings (e.g., the
name of the type).
In this case, it is known that after the dialog has been shown and
disposed, it should be eligible for garbage collection. If the
SomeDialog instance cannot be garbage collected, then we might
have something referencing the instance unintentionally (for
instance, a left-over event handler).
To assert that the SomeDialog instance can be garbage collected,
the NoNewInstances method can be used:
MemAssertion.NoNewInstances( typeof( SomeDialog ) );

This method will make a full garbage collect and then assert that
no new instances of the SomeDialog class exist on the GC heap.
The ShowDialog code with the memory assertion looks like this:

200 .NET Memory Profiler API .NET Memory Profiler


using SciTech.NetMemProfiler;

void ShowDialog()
{
// Establish a base snapshot
MemProfiler.FastSnapshot();

using( SomeDialog dlg = new SomeDialog() )


{
dlg.ShowDialog();
}

// Assert that no new instances of SomeDialog has been


// created. The FastSnapshot collected at the
// beginning of the method will be used as
// reference.
MemAssertion.NoNewInstances( typeof( SomeDialog ) );
}

If the memory assertion fails, i.e., a new instance of SomeDialog


does exist, a full snapshot will be collected and reported to the
profiler, and the instance of SomeDialog will be marked as a
potential memory leak.
One problem with the example above is that it only detects
instances of SomeDialog as potential memory leaks. The
SomeDialog class probably contains a set of child Controls, and
all of them should also be eligible for garbage collection after the
dialog has been disposed. All those instances can also be checked
by changing the NoNewInstances assertion to:
MemAssertion.NoNewInstances( typeof( Control ), true );

The second argument to NoNewInstances is a Boolean value


indicating whether subclasses of the specified Type should be
checked as well.

NOTE! When profiling a debug build of a program, the scope of


the local variables is often longer than it might appear. In the
example above, the dlg variable might still be in use at the time of
the assertion. This will prevent the SomeDialog instance from
being collected, and the assertion will fail, falsely identifying the
SomeDialog instance as a memory leak.

To avoid this, use a release build or wrap the tested code in a


method:

.NET Memory Profiler .NET Memory Profiler API 201


using SciTech.NetMemProfiler;

void DoShowDialog()
{
using( SomeDialog dlg = new SomeDialog() )
{
dlg.ShowDialog();
}
}

public void ShowDialog()


{
// Establish a base snapshot
MemProfiler.FastSnapshot();

DoShowDialog();
// Assert that no new instances of SomeDialog has been
// created. The FastSnapshot collected at the
// beginning of the method will be used as
// reference.
MemAssertion.NoNewInstances( typeof( SomeDialog ) );
}

Using Wildcard to Perform Namespace


Assertions
All assertion methods that accept a Type argument also have an
overload that accepts a string describing the Type. This string can
end with the wildcard character *, which allows all types that
starts with the specified text to be matched. This can be used to
include all types in a namespace (e.g., System.Windows.Forms.*
will include all types in the System.Windows.Forms
namespace).

Memory Assertions Session


Each time a memory assertion is performed, or memory usage is
retrieved, a full garbage collection is performed. This garbage
collection has to be performed in order to make sure that all
instances that are eligible for garbage collection have really been
collected. If more than one assertion is to be performed at the
same time, the BeginAssertions and EndAssertions
methods should be used to avoid excessive garbage collections.
The garbage collection is performed when calling
BeginAssertions, and then no more garbage collections are
performed for memory assertions until EndAssertions is called.
It is also recommended to call
BeginAssertions/EndAssertions to avoid falsely identifying
instances as memory leaks. This is especially important if using the
NoNewInstancesExcept methods. Consider the following
assertion:

202 .NET Memory Profiler API .NET Memory Profiler


MemProfiler.FastSnapshot();

// Do some operation that will be checked

MemAssertion.NoNewInstancesExcept( new Type[] { typeof( SomeClass),


typeof( SomeOtherClass ) );

The problem with the assertion above is that at the time of the
assertion call, a new Type array exists, and the assertion will fail.
If BeginAssertions/EndAssertions is used, this will be
avoided, since instances created in-between BeginAssertions
and EndAssertions are ignored by the memory assertion.
MemProfiler.FastSnapshot();

// Do some operation that will be checked

BeginAssertions();
MemAssertion.NoNewInstancesExcept( new Type[] { typeof( SomeClass),
typeof( SomeOtherClass ) );
EndAssertions();

NOTE! The BeginAssertions method returns an IDisposable


object. Disposing this object is equivalent to calling
EndAssertions, making it possible to use the using pattern:
using( MemAssertion.BeginAssertions() )
{
MemAssertion.NoNewInstances( ... );
MemAssertion.NoInstances( ... );
}

If using is not used, it is recommended to call EndAssertions


in a finally block, to avoid having unmatched
BeginAssertions/EndAssertions pairs.

Performing Assertions using the


AssertionsDefinition class
In addition to using the MemAssertion methods, e.g.,
NoInstances and NoNewInstances, it is also possible to
perform assertions by using the MemAssertion.Assert method
with the AssertionsDefinition class. This will give you access
to additional assertions and more flexibility when defining the
types included in the assertions. The AssertionsDefinition
class provides the possibility of defining the expected memory
usage in multiple steps, and it also contains additional assertions,
such as MaxNewInstances and MaxNewBytes.

NOTE. Due to the added flexibility and functionality, using


AssertionsDefinition is recommended over using the
MemAssertion methods.

The assertions are defined by creating an instance of the


AssertionsDefinition class and then building the definition
using the methods in the class.

.NET Memory Profiler .NET Memory Profiler API 203


The methods in the AssertionsDefinition class can be divided into
three groups:
NoXXX
This group contains the methods NoInstances and
NoNewInstances. These methods are used to define
that no instances should exist of the specified types,
unless the type has been specifically allowed using an
AllowXXX or MaxXXX method.
AllowXXX
This group contains the methods AllowInstances and
AllowNewInstances. These methods are used to
define that instances of the specified types are allowed
to exist even if they have been restricted by a call to a
NoXXX method. Note that all types are allowed by
default. If a type has not been restricted by a NoXXX
call, then allowing it using AllowXXX will have no
effect.
MaxXXX
This group contains the methods MaxInstances,
MaxNewInstances, MaxBytes, and
MaxNewBytes. These methods are used to define the
maximum number of instances or bytes that are
allowed to exist at the time of the assertion. They also
override restrictions placed using a NoXXX call.
MaxAllocations/MaxAllocatedBytes
This group contains the methods MaxAllocations,
MaxAllocatedBytes. These methods are used to
define the maximum number of allocations or allocated
bytes that are allowed to be performed until the time of
the assertion.

Note that the order of the calls to the AssertionsDefinition


methods is not relevant; an AllowXXX or MaxXXX call always
takes precedence over a NoXXX call. Consider the following two
code snippets:
AssertionsDefinition ad = new AssertionsDefinition();
ad.NoNewInstances( typeof( Control ), true );
ad.AllowNewInstances( typeof( TextBox ) );

AssertionsDefinition ad = new AssertionsDefinition();


ad.AllowNewInstances( typeof( TextBox ) );
ad.NoNewInstances( typeof( Control ), true );

The above definitions are equal. An assertion using these


definitions will fail if any new instance of a class derived from
Control exists, except if the class is TextBox.

204 .NET Memory Profiler API .NET Memory Profiler


When an assertions definition has been built, it can be asserted
using the MemAssertion.Assert method. The code example

.NET Memory Profiler .NET Memory Profiler API 205


below shows how a memory assertion can be performed using an
AssertionsDefinition.
using System.Drawing;
using SciTech.NetMemProfiler;

/// <summary>
/// This method opens up a form that allows the user
/// select a bitmap. The selected bitmap is loaded
/// and made available through the LoadedBitmap
/// property.
/// </summary>
Bitmap LoadBitmap()
{
using( LoadBitmapDialog dlg = new LoadBitmapDialog() )
{
dlg.ShowDialog();
return dlg.LoadedBitmap;
}
}

/// <summary>
/// Tests the memory usage of the LoadBitmap method.
/// </summary>
Bitmap TestLoadBitmap()
{
// Establish a base snapshot
MemProfiler.FastSnapshot();

Bitmap loadedBitmap = LoadBitmap();

// Assert that no new instances related to the


// System.Windows.Forms or System.Drawing
// namespaces have been created, except
// for a single Bitmap instance.
using( MemAssertion.BeginAssertions() )
{
AssertionsDefinition ad = new AssertionsDefinition();
// No new instances of any type in the
// System.Windows.Forms namespace should
// exist, including all types derived from
// a System.Windows.Forms type.
ad.NoNewInstances( System.Windows.Forms.*, true );
// No new instances of any type in the
// System.Drawing namespace should
// exist, including all types derived from
// a System.Drawing type.
ad.NoNewInstances( System. Drawing.*, true );
// Since a Bitmap is returned, we must allow 1
// new Bitmap to be created. The MaxNewInstances
// assertion will override the NoNewInstances
// assertion above.
ad.MaxNewInstances( typeof( Bitmap ), 1 );

// The AssertionsDefinition has been built,


// lets perform the actual assertion.
MemAssertion.Assert( ad );
}

return loadedBitmap;
}

For more information about AssertionsDefinition and the


MemAssertion.Assert method, see the .NET Memory Profiler API
Reference documentation.

206 .NET Memory Profiler API .NET Memory Profiler


Specifying Types using TypeSets
Even if the AssertionsDefinition class provides much
flexibility when specifying the type to include in the assertion,
there are some scenarios that are either hard to express or where
the intention is ambiguous.
Consider the following example (where DerivedClass1 is derived
from BaseClass and DerivedClass2 is derived from DerivedClass1):
AssertionsDefinition ad = new AssertionsDefinition();
ad.NoNewInstances( typeof( BaseClass ), true );
ad.AllowNewInstances( typeof( DerivedClass1 ), true );
ad.MaxNewInstances( typeof( DerivedClass2 ), 5 )

In this case, it is not clear what happens if there are, for instance,
10 new instances of DerivedClass2. It is allowed by the
AllowInstances call, but since 10 new instances exist, the
MaxNewInstances should fail. As mentioned previously, the
AllowXXX and MaxXXX assertions take precedence over the
NoXXX assertions, but the precedence between AllowXXX and
MaxXXX is not defined.
To resolve this ambiguity, DerivedClass2 should not be included in
the AllowNewInstances call. This can be accomplished by using
a TypeSet. The TypeSet class is an immutable class that is used
to define a set of Types by adding or removing types from another
TypeSet. Two predefined TypeSets are available, TypeSet.Empty
(containing no types) and TypeSet.All (containing all loaded
types).
The Add and Subtract methods can be used to create a new
TypeSet with the specified types added or removed. For example,
the following code can be used to create a TypeSet that contains
the BaseClass type and all types derived from it, except the
DerivedClass2 type.
// Start with an empty TypeSet;
TypeSet ts = TypeSet.Empty;
// Add DerivedClass1 and all its derived classes to a
// new TypeSet
ts = ts.Add( typeof( DerivedClass1 ), true );
// Remove DerivedClass2
ts = ts.Subtract( typeof( DerivedClass2 ) );

Using the above example, the assertions can be rewritten as:


AssertionsDefinition ad = new AssertionsDefinition();

TypeSet ts = TypeSet.Empty;
ts = ts.Add( typeof( DerivedClass1 ), true );
ts = ts.Subtract( typeof( DerivedClass2 ) );

ad.NoNewInstances( typeof( BaseClass ), true );


ad.AllowNewInstances( ts );
ad.MaxNewInstances( typeof( DerivedClass2 ), 5 )

For more information about the TypeSet class, see the .NET
Memory Profiler API Reference documentation.

.NET Memory Profiler .NET Memory Profiler API 207


Declarative Memory Assertions
Professional and Memory assertions can also be performed declaratively by
Enterprise only appending attributes to methods. This is a convenient way of
expressing the expected memory behavior of a method, and
when running under .NET Memory Profiler the expectations
will be asserted automatically.
For each method in the AssertionsDefinition class, there exists a
corresponding attribute in the SciTech.NetMemProfiler
namespace, as can be seen in the following table.

AssertionsDefinition Method Corresponding Attribute


AssertionsDefinition.NoNewInstan NoNewInstancesAttribut
ces e
AssertionsDefinition.NoInstances NoInstancesAttribute
AssertionsDefinition.AllowNewInst AllowNewInstancesAttri
ances bute
AssertionsDefinition.AllowInstance AllowInstancesAttribute
s
AssertionsDefinition.MaxNewInsta MaxNewInstancesAttrib
nces ute
AssertionsDefinition.MaxInstances MaxInstancesAttribute
AssertionsDefinition.MaxNewBytes MaxNewBytesAttribute
AssertionsDefinition.MaxBytes MaxBytesAttribute
AssertionsDefinition.MaxAllocation MaxAllocationsAttribute
s
AssertionsDefinition.MaxAllocated MaxAllocatedBytesAttrib
Bytes ute
If a method has one or more assertion attributes, the profiler will
replace the method with a method that:
1. Collects a reference snapshot.
2. Executes the original code.
3. Create an AssertionsDefinition corresponding to
the attributes.
4. Asserts that the expected memory behavior is met by
calling MemAssertion.Assert.
For instance, instead of using the TestLoadBitmap method in the
AssertionsDefinition example, it is possible to express the
assertions using attributes like this:

208 .NET Memory Profiler API .NET Memory Profiler


using System.Drawing;
using SciTech.NetMemProfiler;

[NoNewInstances(System.Windows.Forms.*,
IncludeSubclasses=true)]
[NoNewInstances(System.Drawing.*,IncludeSubclasses=true)]
[MaxNewInstances( typeof( Bitmap), 1]
Bitmap LoadBitmap()
{
using( LoadBitmapDialog dlg = new LoadBitmapDialog() )
{
dlg.ShowDialog();
return dlg.LoadedBitmap;
}
}

When running this code under .NET Memory Profiler, the profiler
will replace this method with a method looking similar to this:
using System.Drawing;
using SciTech.NetMemProfiler;

Bitmap LoadBitmap()
{
// --- Generated by .NET Memory Profiler
// Collect a reference snapshot
MemSnapShot refSnapshot = MemProfiler.FastSnapshot();

try
{
// --- Original code
using( LoadBitmapDialog dlg = new LoadBitmapDialog() )
{
dlg.ShowDialog();
return dlg.LoadedBitmap;
}
// --- Generated by .NET Memory Profiler
}
finally
{
// Build the AssertionsDefinition, as
// defined by the attributes.
using( MemAssertion.BeginAssertions() )
{
AssertionsDefinition ad = new AssertionsDefinition();
ad.NoNewInstances( System.Windows.Forms.*, true );
ad.NoNewInstances( System. Drawing.*, true );
ad.MaxNewInstances( typeof( Bitmap ), 1 );
MemAssertion.Assert( refSnapshot, ad );
}
}
}

As can be seen, the code in the replaced method is similar to the


code in the AssertionsDefinition example. The advantage of
using attributes is that the expected memory behavior is
documented by the attributes, and there is no code overhead when
not running under the profiler.
For more information about the assertion attributes, see the .NET
Memory Profiler API Reference documentation.

.NET Memory Profiler .NET Memory Profiler API 209


Memory Assertions on Generic Types
The assertions work with fully-specified generic types (e.g.,
List<string>), as well as open generic types (e.g., List<>).

Using Memory Assertions with Unit Testing


It is possible to use the memory assertions with a unit-testing
framework, such as NUnit. Each memory assertion method returns
a boolean value, which indicates whether the assertion succeeded
or not. The return value can be used as argument to the unit test
assertion:
Assert.IsTrue( MemAssertion.NoNewInstances( typeof( Control ), true
);

It is also possible to add a handler to the


MemAssertion.AssertionFailed event, which is raised when
a memory assertion has failed. This is especially useful when using
declarative assertions, since the assertion methods are not
explicitly called. For example:
[TestFixture]
public class SomeMemoryTestFixture
{
[TestFixtureSetUp]
public void FixtureSetup()
{
MemAssertion.AssertionFailed += new EventHandler(
MemAssertion_AssertionFailed );
}

[TestFixtureTearDown]
public void FixtureTearDown()
{
MemAssertion.AssertionFailed -= new EventHandler(
MemAssertion_AssertionFailed );
}

void MemAssertion_AssertionFailed(
object sender, EventArgs e )
{
// A memory assertion has failed. Inform the
// unit testing framework
Assert.Fail( Memory assertion failed );
}

[Test]
[NoNewInstances( typeof( Control ),
IncludeSubclasses=true )]
public void SomeTest()
{
// ...
}
}

How to Call the .NET Memory Profiler API


Methods
It is possible to call all the methods of the .NET Memory Profiler
API even when the program is not running under the profiler. The

210 .NET Memory Profiler API .NET Memory Profiler


methods will never throw an exception. If not running under the
profiler, then all methods will return immediately without
performing any action, and all the memory assertion methods will
return true.
The property MemProfiler.IsProfiling can be used to
determine whether the program is running under the profiler or
not.
There are a few common scenarios when running the profiler API:
1. Calling the API methods from within normal code that
will be included in the release build:
void ShowDialog()
{
MemProfiler.FastSnapshot();

// Show the dialog

MemAssertion.NoNewInstances( ... );
}

2. Making the calls to the profiler API conditional, i.e.,


dependent on some compiler-defined symbol:
void ShowDialog()
{
#if ENABLE_MEM_ASSERTIONS
MemProfiler.FastSnapshot();
#endif

// Show the dialog

#if ENABLE_MEM_ASSERTIONS
MemAssertion.NoNewInstances( ... );
#endif
}

3. Only using the API from dedicated test methods that


are not included in the release build, or at least will
never be called when running the release build.
[Test]
void TestShowDialog()
{
MemProfiler.FastSnapshot();

ShowDialog();

Assert.IsTrue( MemAssertion.NoNewInstances( ... ) );


}

Each of the scenarios above has advantages and disadvantages.


The first scenario is probably the easiest to implement. The API
calls and memory assertions are inserted directly into the code that
needs to be tested. If the program is not running under the
profiler, the performance impact will be very low (the method calls
will return immediately after checking a static boolean field). One
disadvantage is that the API methods are actually called, making it
necessary to include the (redistributable) file
SciTech.MemProfilerAPI.dll when distributing the program.

.NET Memory Profiler .NET Memory Profiler API 211


The second scenario avoids the necessity of distributing the
MemProfiler.dll file, but it adds extra code around each profiler
API call.
The last scenario separates the profiler API calls from the program,
allowing the program to be distributed without
SciTech.MemProfilerAPI.dll. If working with a unit-testing
framework, this might be the preferred way of using the API.
However, it may be more suitable to call some API methods from
the real code, e.g., MemProfiler.AddRealTimeComment.

Adding Comments to the Real-time Graph


By calling the method MemProfiler.AddRealTimeComment,
comments can be added to the real-time graph of the profiler. The
comments will be shown in the graph if the Comments checkbox
is checked on the graph page. A comment is shown as a vertical
line, including the text that was supplied when calling
AddRealTimeComment.
Adding comments can be useful when analyzing the real-time
memory usage of certain operations. By adding a comment before
and after an operation, it is easy to see how the memory was used
during the operation. Comments can also be used in the real-time
graph to specify origin time and end time.

Handling Failed Memory Assertions


If a memory assertion has identified one or more instances as
potential memory leaks, a dialog box will be brought up that
informs you about the failed assertions and allows you to decide on
actions to perform.

212 .NET Memory Profiler API .NET Memory Profiler


The information presented for a failed assertion includes the failed
assertion method, the call stack of the assertion, and the instances
that have been identified as potential memory leaks by the
assertion. For more information about the presentation of memory
assertions, see Viewing Failed Memory Assertions on page 213.
In the dialog box, there are two actions that can be performed after
the memory assertion has failed:
Collect a full heap snapshot
If this option is checked, a full heap snapshot will be
collected when OK is clicked. A full snapshot has to be
collected in order for the profiler to present information
about the potential memory leak instances.
Stop the profiling session
If this option is selected, the profiling session will be
ended when OK is clicked, after the full heap snapshot
has been collected (if requested).

NOTE! If the profiler is running in non-interactive mode and


Perform default actions is selected for memory leak detection,
then no dialog box will appear when a memory assertion has
failed.

Viewing Failed Memory Assertions


To view information about all failed memory assertion, the
command Show Failed Memory Assertions can be used.

.NET Memory Profiler .NET Memory Profiler API 213


This command will bring up a dialog box presenting information
about the failed assertions.

Show failed memory assertions


This area is used to select the failed memory assertions to show. To
show all memory assertions, select the All failed memory
assertions option; to show only memory assertions that have
failed between the selected snapshot and the comparison
snapshot, select Failed memory assertions for selected
snapshots.
Failed assertion
Information about the failed assertions is presented here. The text
box and up-down field can be used to select the assertion to show.
At the top of the failed assertions group, information about the
assertion method is presented. Below the assertion information,
the call stack of the assertion is presented.
At the bottom of the group box, a list is used to present the
instances that have been identified as potential memory leaks. If
the Group by class check box is checked, the instances are
grouped and the number of instances per class is presented.
Otherwise, all instances are presented in the list.

214 .NET Memory Profiler API .NET Memory Profiler


Appendix

Additional information and know issues.

Attach to Process using Profiling API


In order for .NET Memory Profiler and the NmpCore tool to attach
to a process using the profiling API, the process must be running
under .NET Framework 4.0. Additionally, unless .NET Framework
4.5 is installed, the concurrent garbage collector must not be
enabled. This is normally not a problem when attaching to server
processes (like ASP.NET running under IIS), since they are using
the server garbage collector, which is not using concurrent GC. For
a standalone program, the concurrent garbage collector can be
disabled by modifying the application config file. To disable
concurrent GC and run the program under .NET runtime 4.0,
modify the config file so that it includes the following settings:
<?xml version="1.0"?>
<configuration>
<runtime>
<gcConcurrent enabled="false" />
</runtime>
<startup>
<supportedRuntime version="v4.0.30319" />
</startup>
</configuration>

Support for Generics

Generic Types
Only classes that have had at least one instance allocated are
presented by the profiler, and an instance of a generic class can
only be allocated when all generic type parameters are known.
Therefore, the generic classes presented by the profiler are always
fully instantiated (i.e., all type parameters are known).
The names of generic classes are presented using C# syntax. The
type parameters are presented using the name of the type unless
the type is a primitive type (e.g., int, float, and string). Primitive
type parameters are presented using the C# name of the type. For
example, the name of a
System.Collections.Generics.Dictionary<K,V> class

.NET Memory Profiler Appendix 215


instantiated with int (System.Int32) and
System.Windows.Forms.Control, will be presented as:
Dictionary<int, Control>

Generic Methods
Generic methods are defined in the .NET documentation as
methods that are declared with type parameters (e.g., Swap<T>(
T x, T y ) ). Here, methods that access class-level type
parameters are also considered to be generic methods. For
instance, the DoSomething method below is considered a generic
method.
class GenericClass<T>
{
void DoSomething( T value );
}

When a generic method is presented in a call stack or in the


method view of the Call Stacks/Methods page, the type parameters
of the method or the class containing the method are presented.
However, due to the way the runtime optimizes the generation of
generic methods, the profiler cannot always retrieve the actual type
parameters of the method.
When a generic method is instantiated with a reference type, the
runtime allows this instantiation to be shared for all reference
types. For example, the methods List<string>.Add() and
List<Control>.Add(), both use the same instantiation of
Add,since System.String and
System.Windows.Form.Control are both reference types.
This sharing of instantiations prevents the profiler from
identifying the actual instantiation of a method. Instead, the
profiler will present the methods with the generic type parameter
names used when designing the class. Thus, both of the Add
methods will be named List<T>.Add().
If a generic method is instantiated only using value type
parameters, then no sharing of method code occurs, and the
profiler can correctly identify the instantiated method. For
instance, the methods List<int>.Add() and
List<float>.Add() will be presented with the actual type
parameters.
The same rules apply to generic methods that are declared with
type parameters. For instance, Swap<string>() and
Swap<Control>() will be presented as Swap<T>(), but
Swap<int>() will be presented as Swap<int>().

Known Issues
Below is a list of known issues with the profiler.

216 Appendix .NET Memory Profiler


Instance data are not collected for all classes
when low-impact profiling is enabled.
Roots are not always identified and instance
fields data is not always available
Depending on the session settings, the profiler may fail
to retrieve some static or instance fields, which will
cause static fields roots to be missed, or instance data to
not be collected.
Identification of generic type parameters
As discussed under Generic Methods on page 216, the
actual type parameters cannot always be identified for
generic methods. It is possible to make an
implementation that identifies all type parameters for
generic methods, but the performance overhead for this
is high. Currently, there are no plans for implementing
better identification of type parameters for generic
methods.

.NET Memory Profiler Appendix 217


Glossary of Terms

memory leak
A memory leak is characterized by an unintentionally increasing
amount of memory usage. Traditionally a memory leak occurs
when memory is allocated and the reference is discarded before
the memory is released. In a garbage collected environment this
can never occur, since an instance is released as soon as all
references to it has been removed. On the other hand, it is possible
to unintentionally reference an instance by a long-term reference,
by for instance adding an observer to a long-living instance and
never removing it. The behavior of having unintentional long-term
references to instances is similar to the traditional memory leak
and will be referred to as a memory leak in this manual.

code injection
Code injection is the process of adding additional code to a
method, or adding completely new methods. By injecting code it is
possible to get information about when certain things happen, e.g.
when an instance is disposed.

live instance
A live instance is an instance that is reachable by walking the
references from any root.

disposable
A disposable class is a class which implements the
System.IDisposable interface, or is derived from a class
implementing System.IDisposable. A disposable instance is an
instance of a disposable class.

instance number
Instance number is a unique number identifying a specific
instance. Whenever an instance is part of a heap snapshot it is

.NET Memory Profiler Glossary of Terms 219


assigned an instance number. This number will always be used to
identify this particular instance, even as it is moved around on the
GC heap.

referrer
A referrer is an instance field, static field, local variable or method
argument which references an instance.

root reference
Root references acts as starting points when the garbage collector
performs a heap walk. Root references can for instance be local
variables, method arguments, references to static reference fields
or other internal references in the common language runtime.

220 Glossary of Terms .NET Memory Profiler


Context Menus 93
Copying Data to the Clipboard 93
Create or Load a Profiler Project 22
Creation Context 175

Index D
Data 150
Debug Profiling 183
Declarative Memory Assertions 207
Details (allocated instances) 145
Disposable Types Classification and
Undisposed Instances 51
Dispose Tracker 169
. Disposed Instances 170
.NET Memory Profiler API 196 Duplicate Instances Additional Bytes 48
Duplicate Instances Detection 47
A
E
A Comment on the Appearance of Total and
Live Plots 152 Exit Codes 31
Access Profiler Settings 185
Adding and Removing Sessions 80 F
Adding Comments to the Real-time Graph Fast Column Filter 94
211 Field Sets 92
Allocation Stacks 123 Field values 131
Analysis Issues List 39 Find Memory Leaks 12
AppDomains Tracker 176 Find out Information about the Native
Attach to a Process 20 Memory of a .NET Process 15
Attach to Process using Profiling API 214
Automatic Memory Analysis 31 G
Available Command Line Arguments 27
GC Handle Identification 178
C General Settings Page 102
Generic Methods 215
Call Stack Reducer 177 Generic Types 215
Call Stacks Functions 141 Graph 152
Call Stacks Reduction 176 Graph Presentation 57
Call Stacks Settings Page 111 Graph Synchronization 67
Call Stacks View 142 Guided Profiling and the Tasks Window 70
Call Stacks/Methods Page 136
Code 149 H
Column Layout and Customization 95
Combined Instances Graph 63 Handling Failed Memory Assertions 212
Command Line Arguments 26 Heap Utilization Tracker 172
Command Line Examples 193 Held and Reachable Instances 53
Commands 86 Held by a Set of Instances 56
Commands in Visual Studio 185 Held Duplicates 49
Compare Snapshots using the Profiler How to Call the .NET Memory Profiler API
Projects Explorer 24 Methods 210
Comparing Project Snapshots 80 How to... 2

.NET Memory Profiler Index 221


I Navigating Types, Resources, Filters, and
Instances 94
Identified resources 149
NmpCore MSBuild Task 194
Ignoring Analysis Issues 35
Non-Interactive Mode 25
Ignoring Framework Issues 52
Import Memory Dump Files 21
Increase the Performance of the Profiler 19 O
Info Panel 93 Open a Previously Saved Session 185
Instance and Allocation Filters 72 Other Data 150
Instance creation 136 Overview Page 113
Instance Data Collection Settings Page 111
Instance Details Page 128 P
Instance Graph 57, 129
Instance Graph Commands 68 Peak Snapshots 78
Instance Tracking Settings Page 101 Perform Unit Testing together with the
Instances 120 Profiler 16
Instances graph 127 Performing Assertions using the
Instances, Allocation Stack, Root Path, and AssertionsDefinition class 203
Graph Synchronization 127 Possible Duplicate Instances 50
Interactive Mode 25 Predefined Filters 75
Introduction 1 Preferences 96
Issue Presentation 33 Private, Shared, and Potentially Shared
Memory 151
Profile a .NET Process 2
J
Profile a Remote Process 10
JIT 149 Profiler induced data 150
Profiler Projects 79
K Profiling Level Settings Page 100
Profiling the Azure Compute Emulator 184
Known Issues 216
R
L
Real-time layout 154
Launch Settings Page 104
Real-Time Page 151
Limiting Call Stack Depth 177
Real-time series 158
Real-time series settings 160
M
Real-time Settings Page 108
Managed heaps 148 Real-time Types/Resources 164
Managed memory statistics 162 Recent data graph 167
Matching Partial Call Stack 140 Reducing Data 169
Memory Assertions on Generic Types 209 Referenced by 129
Memory Assertions Session 202 References/Wraps 130
Memory Leak Settings Page 109 Related resource instances 134
Memory View 147 Remote Profiling 80
Methods View 137 Remote Profiling Security 82
Modifying Ignored Issues 37 Resource Tracker Limitations 175
Response Files 30
N Retrieve Memory Usage Information 197
Root path 135
Native Memory Page 146
Root Paths in the Graph 60
Native resources statistics 163
Run Tests under the Profiler 184
Runtimes and AppDomains Selector 85

222 Index .NET Memory Profiler


S Using Memory Assertions with Unit Testing
209
Saving and Managing Filters 76
Using Wildcard to Perform Namespace
Select Processes to Profile 9
Assertions 202
Session File Settings Page 107
Session Settings 98
Session Time Selector 168 V
Settings 157 View Real-time Heap Utilization 13
Settings and Series 154 Viewing Failed Memory Assertions 213
Setup Native Stack Walks 24 Visual Studio Integration 181
Shortest root paths 123
Snapshot and Process Dropdown Lists 84 W
Snapshot Filters 75
Snapshots Settings Page 105 Work with a Previously Saved Session 15
Sources 156 Working with the Graph 64, 165
Specifying Types using TypeSets 206 Wrapped by 134
Start Profiling a .NET Core App 6
Start Profiling a Project 182
Start Profiling a Silverlight Application 8
Start Profiling a Windows Service 9
Start Profiling a Windows Store App 5
Start Profiling a WPF Browser Application 9
Start Profiling an Application 4
Start Profiling an ASP.NET Core App using
IIS Express and .NET Core 7
Start Profiling ASP.NET 4
Start Profiling using a Profiler Project 23
Starting .NET Memory Profiler 25
Starting NmpCore 191
Static field values 128
Status Bar 91
Support for Generics 215
Symbol File Locations 98
System 151

T
Tasks Window 72
The .NET Memory Profiler Window 83
The NmpCore Tool 191
Thread stacks 149
Type/Resource/Filter Details Page 119

U
Undisposed instances 172
Unidentified unmanaged heaps 150
Unmanaged Resources Tracker 174
Unreachable instances 174
Use Assertions to Detect Memory Leaks 199
Use the Memory Analyser 11

.NET Memory Profiler Index 223

Anda mungkin juga menyukai