|
| 1 | +--- |
| 2 | +title: Debug a managed memory dump with .NET Diagnostic Analyzers | Microsoft Docs |
| 3 | +description: Learn how to use Visual Studio's .NET Diagnostics Analyzers to analyze a managed memory dump |
| 4 | +ms.custom: SEO-VS-2021 |
| 5 | +ms.date: 04/21/2021 |
| 6 | +ms.topic: how-to |
| 7 | +dev_langs: |
| 8 | + - CSharp |
| 9 | + - VB |
| 10 | +helpviewer_keywords: |
| 11 | + - analyzers |
| 12 | + - dump debugging |
| 13 | + - debugging managed memory dump |
| 14 | + - debugging [Visual Studio] |
| 15 | +author: poppastring |
| 16 | +ms.author: madownie |
| 17 | +manager: andster |
| 18 | +monikerRange: '>= vs-2019' |
| 19 | +ms.workload: |
| 20 | + - "multiple" |
| 21 | +--- |
| 22 | + |
| 23 | +# How to debug a managed memory dump with .NET Diagnostic Analyzers |
| 24 | + |
| 25 | + |
| 26 | + |
| 27 | +In this tutorial, you will: |
| 28 | + |
| 29 | +> [!div class="checklist"] |
| 30 | +> * Opening a memory dump |
| 31 | +> * Select and execute analyzers against the dump |
| 32 | +> * Review the results of the analyzers |
| 33 | +> * Navigating to the problematic code |
| 34 | +
|
| 35 | + |
| 36 | +In the example described in this article, the concern is that your app not responding to requests in a timely manner. |
| 37 | + |
| 38 | + |
| 39 | +## Opening a memory dump in Visual Studio |
| 40 | + |
| 41 | +1. Open the memory dump in Visual Studio by using the **File > Open > File** menu command and select your memory dump. |
| 42 | + |
| 43 | +1. Notice on the Memory Dump Summary page a new **Action** called **Run Diagnostics Analysis**. |
| 44 | + |
| 45 | +  |
| 46 | + |
| 47 | +1. Select this action to start the debugger and open the new **Diagnostic Analysis** page with a list of available analyzer options, organized by the underlying symptom. |
| 48 | + |
| 49 | + |
| 50 | +## Select and execute analyzers against the dump |
| 51 | + |
| 52 | +To investigate these symptoms, the best options are available under **Process Responsiveness** as it best matches the issue in this example. |
| 53 | + |
| 54 | +  |
| 55 | + |
| 56 | +1. Click the **Analyze** button to start the investigative process |
| 57 | + |
| 58 | +1. The analyzer will present results based on the combination of process info and CLR data captured in the memory dump. |
| 59 | + |
| 60 | +## Review the results of the analyzers |
| 61 | + |
| 62 | +1. In this case, the analyzer has found two errors. Select the analyzer result to see the **Analysis Summary** and suggested **Remediation**. |
| 63 | + |
| 64 | +  |
| 65 | + |
| 66 | +1. The **Analysis Summary** has stated that the “CLR thread pool is experiencing starvation”. This information suggests that the CLR has currently used all available thread pool threads, which means your service cannot respond to any new requests until a thread is released. |
| 67 | + |
| 68 | + > [!NOTE] |
| 69 | + > The **Remediation** in this case is "Do not synchronously wait on Monitors, Events, Task, or any other objects that may block your thread. See if you can update the method to be asynchronous.". |
| 70 | +
|
| 71 | +## Navigating to the problematic code |
| 72 | + |
| 73 | +My next job is to find that problematic code. |
| 74 | + |
| 75 | +1. Clicking on the **Show call stack** link Visual Studio will immediately switch to the threads that are exhibiting this behavior. |
| 76 | + |
| 77 | +1. The **Call Stack** window will show methods that might potentially quickly distinguish between my code (SyncOverAsyncExmple.*) from Framework code (System.*). |
| 78 | + |
| 79 | +  |
| 80 | + |
| 81 | +1. Each call stack frame corresponds to a method and by double-clicking on the stack frames Visual Studio will navigate to the code that led directly to this scenario on this thread. |
| 82 | + |
| 83 | +1. In this example, there are no symbols or code, however, on the **Symbols not loaded** page you can select the **[Decompile Source code](../debugger/decompilation.md)** option. |
| 84 | + |
| 85 | +  |
| 86 | + |
| 87 | +1. In the decompiled source below it is evident that an asynchronous Task (ConsumeThreadPoolThread) is calling a synchronous blocking function. |
| 88 | + |
| 89 | + > [!NOTE] |
| 90 | + > The "DoSomething()" method that contains a WaitHandle.WaitOne method, which is blocking the current thread pool thread until it receives a signal. |
| 91 | +
|
| 92 | + To improve the apps responsiveness, it is important to remove blocking synchronous code from all asynchronous contexts. |
| 93 | + |
| 94 | +  |
| 95 | + |
| 96 | + |
| 97 | +## See also |
| 98 | + |
| 99 | +* [Use dump files in the debugger](../debugger/using-dump-files.md) |
| 100 | +* [Generate source code from .NET assemblies while debugging](../debugger/decompilation.md) |
| 101 | +* [Specify symbol (.pdb) and source files](../debugger/specify-symbol-dot-pdb-and-source-files-in-the-visual-studio-debugger.md) |
0 commit comments