Thursday, May 20, 2021

Visual Studio Memory Profile - Run profiling tools with or without the debugger


Visual Studio offers a choice of performance measurement and profiling tools. Some tools, like CPU Usage and Memory Usage, can run with or without the debugger, and on release or debug build configurations. Tools that appear in the Diagnostics Tools window run only during a debugging session. Tools that appear in the Performance Profiler run without the debugger and you analyze the results after you choose to stop and collect data (for post-mortem analysis).


You can use the non-debugger performance tools with Windows 7 and later. Windows 8 or later is required to run the debugger-integrated profiling tools.

The non-debugger Performance Profiler and the debugger-integrated Diagnostic Tools provide different information and experiences. Debugger-integrated tools show you variable values and let you use breakpoints. Non-debugger tools give you results closer to the end-user experience.

To help decide which tools and results to use, consider the following:

·       Debugger-integrated tool vs. non-debugger tool

o   External performance problems, like file I/O or network responsiveness issues, won't look much different in the debugger or non-debugger tools.

o   The debugger itself changes performance times, as it does necessary debugger operations like intercepting exception and module load events.

o   Release build performance numbers in the Performance Profiler are the most precise and accurate. Debugger-integrated tool results are most useful to compare with other debugging-related measurements, or to use debugger features.

o   Some tools, such as the .NET Object Allocation tool, are only available for non-debugger scenarios.

·       Debug vs. release build

o   For problems caused by CPU-intensive calls, there might be considerable performance differences between release and debug builds. Check to see whether the issue exists in release builds.

o   If the problem occurs only during debug builds, you probably don't need to run the non-debugger tools. For release build problems, decide whether features provided by the debugger-integrated tools will help to pinpoint the problem.

o   Release builds provide optimizations like inlining function calls and constants, pruning unused code paths, and storing variables in ways that can't be used by the debugger. Performance numbers in the debug builds are less accurate, because debug builds lack these optimizations.

Collect profiling data while debugging

When you start debugging in Visual Studio by selecting Debug > Start Debugging, or pressing F5, the Diagnostic Tools window appears by default. To open it manually, select Debug > Windows > Show Diagnostic Tools. The Diagnostic Tools window shows information about events, process memory, and CPU usage.

·       Use the Settings icon in the toolbar to select whether to view Memory UsageUI Analysis, and CPU Usage.

·       Select Settings in the Settings drop-down list to open the Diagnostic Tools Property Pages with more options.

·       If you're running Visual Studio Enterprise, you can enable or disable IntelliTrace by going to Tools > Options > IntelliTrace.

The diagnostic session ends when you stop debugging.

For more information, see:

·       Measure application performance by analyzing CPU usage

·       Measure memory usage in Visual Studio

The Events tab

During a debugging session, the Events tab of the Diagnostic Tools window lists the diagnostic events that occur. The category prefixes BreakpointFile, and others, let you quickly scan the list for a category, or skip the categories you don't care about.

Use the Filter drop-down list to filter events in and out of view, by selecting or clearing specific categories of events.

Use the search box to find a specific string in the event list. Here are the results of a search for the string name that matched four events:

For more information, see Searching and filtering the Events tab of the Diagnostic Tools window.

Collect profiling data without debugging

To collect performance data without debugging, you can run the Performance Profiler tools.

1.     With a project open in Visual Studio, set the solution configuration to Release, and select Local Windows Debugger (or Local Machine) as the deployment target.

2.     Select Debug > Performance Profiler, or press Alt+F2.

3.     On the diagnostic tools launch page, select one or more tools to run. Only the tools that are applicable to the project type, operating system, and programming language are shown. Select Show all tools to also see tools that are disabled for this diagnostic session.

For memory Usage capturing , you have setting option for memory usage such as you can choose to select Native code or Managed code or mixed to capture memory for either C++ or Dotnet

4.     To start the diagnostic session, select Start.

While the session is running, some tools show graphs of real-time data on the diagnostic tools page, as well as controls to pause and resume data collection.

5.     To end the diagnostic session, select Stop Collection.

The analyzed data appears on the Report page.

You can save the reports, and open them from the Recently Opened Sessions list on the Diagnostic Tools launch page.

For more information, see:

·       Analyze CPU usage

·       Analyze memory usage for .NET code

·       Analyze memory usage

·       Analyze performance of .NET asynchronous code

·       Analyze database performance

·       Analyze GPU usage

Collect profiling data from the command line

To measure performance data from the command line, you can use VSDiagnostics.exe, which is included with either Visual Studio or the Remote Tools. This is useful for capturing performance traces on systems where Visual Studio isn't installed, or for scripting the collection of performance traces. For detailed instructions, see Measure application performance from the command line.


Measure memory usage in Visual Studio - Dot Net / Native (C++)


Find memory leaks and inefficient memory while you're debugging with the debugger-integrated Memory Usage diagnostic tool. The Memory Usage tool lets you take one or more snapshots of the managed and native memory heap to help understand the memory usage impact of object types. You can also analyze memory usage without a debugger attached or by targeting a running app. For more information, see Run profiling tools with or without the debugger.

Although you can collect memory snapshots at any time in the Memory Usage tool, you can use the Visual Studio debugger to control how your application executes while investigating performance issues. Setting breakpoints, stepping, Break All, and other debugger actions can help you focus your performance investigations on the code paths that are most relevant. Performing those actions while your app is running can eliminate the noise from the code that doesn't interest you and can significantly reduce the amount of time it takes you to diagnose an issue.


The debugger-integrated Diagnostics Tools are supported for .NET development in Visual Studio, including ASP.NET, ASP.NET Core, native/C++ development, and mixed mode (.NET and native) apps. Windows 8 and later is required to run profiling tools with the debugger (Diagnostic Tools window).

In this tutorial, you will:

· Take snapshots of memory

· Analyze memory usage data

If Memory Usage does not give you the data that you need, other profiling tools in the Performance Profiler provide different kinds of information that might be helpful to you. In many cases, the performance bottleneck of your application may be caused by something other than your memory, such as CPU, rendering UI, or network request time.


Custom Allocator Support The native memory profiler works by collecting allocation ETW event data emitted during run time. Allocators in the CRT and Windows SDK have been annotated at the source level so that their allocation data can be captured. If you are writing your own allocators, then any functions that return a pointer to newly allocated heap memory can be decorated with __declspec(allocator), as seen in this example for myMalloc:

__declspec(allocator) void* myMalloc(size_t size)

Collect memory usage data

1.     Open the project you want to debug in Visual Studio and set a breakpoint in your app at the point where you want to begin examining memory usage.

If you have an area where you suspect a memory issue, set the first breakpoint before the memory issue occurs.


Because it can be challenging to capture the memory profile of an operation that interests you when your app frequently allocates and de-allocates memory, set breakpoints at the start and end of the operation (or step through the operation) to find the exact point that memory changed.

2.     Set a second breakpoint at the end of the function or region of code that you want to analyze (or after a suspected memory issue occurs).

3.     The Diagnostic Tools window appears automatically unless you have turned it off. To bring up the window again, click Debug > Windows > Show Diagnostic Tools.

4.     Choose Memory Usage with the Select Tools setting on the toolbar.

5.     Click Debug / Start Debugging (or Start on the toolbar, or F5).

When the app finishes loading, the Summary view of the Diagnostics Tools appears.


Because collecting memory data can affect the debugging performance of your native or mixed-mode apps, memory snapshots are disabled by default. To enable snapshots in native or mixed-mode apps, start a debugging session (Shortcut key: F5). When the Diagnostic Tools window appears, choose the Memory Usage tab, and then choose Heap Profiling.

Stop (Shortcut key: Shift+F5) and restart debugging.

6.     To take a snapshot at the start of your debugging session, choose Take snapshot on the Memory Usage summary toolbar. (It may help to set a breakpoint here as well.)


To create a baseline for memory comparisons, consider taking a snapshot at the start of your debugging session.

7.     Run the scenario that will cause your first breakpoint to be hit.

8.     While the debugger is paused at the first breakpoint, choose Take snapshot on the Memory Usage summary toolbar.

9.     Press F5 to run the app to your second breakpoint.

10.  Now, take another snapshot.

At this point, you can begin to analyze the data.

Analyze memory usage data

The rows of Memory Usage summary table lists the snapshots that you have taken during the debugging session and provides links to more detailed views.

The name of the columns depend on the debugging mode you choose in the project properties: .NET, native, or mixed (both .NET and native).

·       The Objects (Diff) and Allocations (Diff) columns display the number of objects in .NET and native memory when the snapshot was taken.

·       The Heap Size (Diff) column displays the number of bytes in the .NET and native heaps

When you have taken multiple snapshots, the cells of the summary table include the change in the value between the row snapshot and the previous snapshot.

To analyze memory usage, click one of the links that opens up a detailed report of memory usage:

·       To view details of the difference between the current snapshot and the previous snapshot, choose the change link to the left of the arrow (Memory Usage Increase). A red arrow indicates an increase in memory usage, and a green arrow to indicates a decrease.


To help identify memory issues more quickly, the diff reports are sorted by object types that increased the most in overall number (click the change link in Objects (Diff) column) or that increased the most in overall heap size (click the change link in Heap Size (Diff) column).

·       To view details of only the selected snapshot, click the non-change link.

The report appears in a separate window.

Managed types reports

Choose the current link of a Objects (Diff) or Allocations (Diff) cell in the Memory Usage summary table.

The top pane shows the count and size of the types in the snapshot, including the size of all objects that are referenced by the type (Inclusive Size).

The Paths to Root tree in the bottom pane displays the objects that reference the type selected in the upper pane. The .NET garbage collector cleans up the memory for an object only when the last type that references it has been released.

The Referenced Objects tree displays the references that are held by the type selected in the upper pane.

To display the instances of a selected type in the upper pane, choose the  icon.

The Instances view displays the instances of the selected object in the snapshot in the upper pane. The Paths to Root and Referenced Objects pane displays the objects that reference the selected instance and the types that the selected instance references. When the debugger is stopped at the point where the snapshot was taken, you can hover over the Value cell to display the values of the object in a tool tip.

Native type reports

Choose the current link of a Allocations (Diff) or Heap Size (Diff) cell in the Memory Usage summary table of the Diagnostic Tools window.

The Types View displays the number and size of the types in the snapshot.

·       Choose the instances icon () of a selected type to display information about the objects of the selected type in the snapshot.

The Instances view displays each instance of the selected type. Selecting an instance displays the call stack that resulted in the creation of the instance in the Allocation Call Stack pane.

·       Choose Stacks View in the View Mode list to see the allocation stack for the selected type.

Change (Diff) reports

·       Choose the change link in a cell of the summary table of the Memory Usage tab on the Diagnostic Tools window.

·       Choose a snapshot in the Compare To list of a managed or native report.

The change report adds columns (marked with (Diff)) to the base report that show the difference between the base snapshot value and the comparison snapshot. Here's how a Native Type View diff report might look:

Popular Posts