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.)
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 native heaps
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”, “Gaps,” and “Unreachable”.
“Data” represents memory that is actually used by an allocated instance.
“Gaps” represent memory that is unused between two allocated instances. “Gaps” 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
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
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).
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 native resources tracker is enabled.
It presents the memory used by native resources tracked by the native resources tracker. Only memory that is not presented under another node, such as Thread stacks, is included here.
Unidentified native 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 native resources tracker.
Profiler induced data
This node is only presented for the profiled process, and it is presented only if the native 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>.”
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.