|
| 1 | +--- |
| 2 | +title: Application or Service Memory Leaks Troubleshooting Guidance |
| 3 | +description: Provides guidance on how to troubleshoot application or service memory leaks. |
| 4 | +ms.date: 08/12/2025 |
| 5 | +manager: dcscontentpm |
| 6 | +audience: itpro |
| 7 | +ms.topic: troubleshooting |
| 8 | +ms.reviewer: kaushika, warrenw, vjulio, v-lianna |
| 9 | +ms.custom: |
| 10 | +- sap:system performance\app,process,service performance (slow,unresponsive) |
| 11 | +- pcy:WinComm Performance |
| 12 | +--- |
| 13 | +# Application or service memory leaks troubleshooting guidance |
| 14 | + |
| 15 | +This article provides guidance on troubleshooting applications or services with memory leak behaviors and how to proceed. |
| 16 | + |
| 17 | +_Applies to:_ All supported versions of Windows Server and Windows Client |
| 18 | + |
| 19 | +You see Event ID 2004 repeatedly in the system log. As the event source mentions, there's a resource exhaustion in the system on the virtual memory space. The description lists the system's top memory consumers at that time. |
| 20 | + |
| 21 | +Apart from this event, you also notice high memory consumption by checking live or historical data from monitoring tools, or by using the Windows Task Manager. |
| 22 | + |
| 23 | +The following troubleshooting process is helpful for both scenarios where first-party and third-party processes might be leaking memory. For first-party processes, you can use the public symbol store available. However, if you can't see the actual function in a third-party process, you can engage the vendor for further check. Even if the function doesn't show, the allocation stack should indicate a third-party module. |
| 24 | + |
| 25 | +## Before you begin |
| 26 | + |
| 27 | +You might see the following examples in the system event log and Task Manager. |
| 28 | + |
| 29 | +```output |
| 30 | +Log Name: System |
| 31 | +Source: Microsoft-Windows-Resource-Exhaustion-Detector |
| 32 | +Date: <DateTime> |
| 33 | +Event ID: 2004 |
| 34 | +Task Category: Resource Exhaustion Diagnosis Events |
| 35 | +Level: Warning |
| 36 | +Keywords: Events related to exhaustion of system commit limit (virtual memory). |
| 37 | +User: SYSTEM |
| 38 | +Computer: WIN-LAB |
| 39 | +Description: |
| 40 | +Windows successfully diagnosed a low virtual memory condition. The following programs consumed the most virtual memory:wpa.exe (9844) consumed 13714722816 bytes, msedgewebview2.exe (112572) consumed 3037757440 bytes, and EngHost.exe (37280) consumed 2619834368 bytes. |
| 41 | +``` |
| 42 | + |
| 43 | +:::image type="content" source="./media/troubleshoot-application-service-memory-leaks/task-manager-test-limit.png" alt-text="Screenshot of Task Manager showing the process with high memory consumption."::: |
| 44 | + |
| 45 | +The memory shown in the default list of columns isn't the one that should be focused on, since it represents the memory privately used by the process but backed by physical memory (working set). You need to verify virtual memory that is used by the operating system for its operation regardless of the way the virtual memory is backed (RAM or pagefile). In this case, you need to verify **Commit size**. |
| 46 | + |
| 47 | +Here are some examples: |
| 48 | + |
| 49 | +:::image type="content" source="./media/troubleshoot-application-service-memory-leaks/task-manager-test-limit-commit-size.png" alt-text="Screenshot of Task Manager showing the process with high commit size."::: |
| 50 | + |
| 51 | +:::image type="content" source="./media/troubleshoot-application-service-memory-leaks/task-manager-virtual-memory-commit-size.png" alt-text="Screenshot of Task Manager showing the VirtMemTest32 process with high commit size."::: |
| 52 | + |
| 53 | +You can use [VMMap](/sysinternals/downloads/vmmap) and [Windows Performance Toolkit](/windows-hardware/test/wpt) for troubleshooting. |
| 54 | + |
| 55 | +VMMap is used to determine the type of memory leaks. The Windows Performance Toolkit includes the Windows Performance Recorder (WPR) tool and the Windows Performance Analyzer (WPA) tool, which are used to collect and analyze data. |
| 56 | + |
| 57 | +## Gather data |
| 58 | + |
| 59 | +During this stage, if the memory usage is growing over time and isn't released, it indicates a leak pattern. The increase doesn't need to be a straight line to fall into this pattern. The key point is that the memory usage keeps on increasing over time. |
| 60 | + |
| 61 | +:::image type="content" source="./media/troubleshoot-application-service-memory-leaks/increase-leak-pattern.png" alt-text="Screenshot of the memory usage with an increase pattern."::: |
| 62 | + |
| 63 | +At this point, with a leak pattern, you need to determine the leaking memory type. Open VMMap and select the process that is identified as the leaking memory. |
| 64 | + |
| 65 | +### Determine the memory type |
| 66 | + |
| 67 | +When virtual allocation memory is leaked, it's represented in VMMap as **Private Data**: |
| 68 | + |
| 69 | +:::image type="content" source="./media/troubleshoot-application-service-memory-leaks/virtual-memory-private-data.png" alt-text="Screenshot of the virtual allocation memory leaks represented as Private Data in VMMap."::: |
| 70 | + |
| 71 | +If you have a memory dump of the process, you can run the following command to see the memory layout. Virtual allocation shows as `<unknown>`: |
| 72 | + |
| 73 | +```console |
| 74 | +0:000> !address -summary |
| 75 | + |
| 76 | +--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal |
| 77 | +Free 58 0`85c87000 ( 2.090 GB) 52.26% |
| 78 | +<unknown> 56 0`7866f000 ( 1.881 GB) 98.52% 47.03% |
| 79 | +Image 116 0`016de000 ( 22.867 MB) 1.17% 0.56% |
| 80 | +Stack32 9 0`00240000 ( 2.250 MB) 0.12% 0.05% |
| 81 | +Other 6 0`001aa000 ( 1.664 MB) 0.09% 0.04% |
| 82 | +Heap32 8 0`0012b000 ( 1.168 MB) 0.06% 0.03% |
| 83 | +Stack64 9 0`000c0000 ( 768.000 kB) 0.04% 0.02% |
| 84 | +Heap64 4 0`00039000 ( 228.000 kB) 0.01% 0.01% |
| 85 | +TEB64 3 0`00006000 ( 24.000 kB) 0.00% 0.00% |
| 86 | +TEB32 3 0`00006000 ( 24.000 kB) 0.00% 0.00% |
| 87 | +PEB64 1 0`00001000 ( 4.000 kB) 0.00% 0.00% |
| 88 | +PEB32 1 0`00001000 ( 4.000 kB) 0.00% 0.00% |
| 89 | +``` |
| 90 | + |
| 91 | +When heap allocation memory is leaked, it's represented with **Heap**: |
| 92 | + |
| 93 | +:::image type="content" source="./media/troubleshoot-application-service-memory-leaks/virtual-memory-heap-allocation.png" alt-text="Screenshot of the VirMemTest32 process with the heap allocation memory leaks represented as Heap in VMMap."::: |
| 94 | + |
| 95 | +If you have a memory dump of the process, you can run the following command to see the memory layout. Heap allocation shows as `Heap`: |
| 96 | + |
| 97 | +```console |
| 98 | +0:000> !address -summary |
| 99 | + |
| 100 | +--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal |
| 101 | +Heap32 67 0`709f3000 ( 1.760 GB) 91.47% 87.99% |
| 102 | +Free 115 0`04e03000 ( 78.012 MB) 3.81% |
| 103 | +<unknown> 59 0`0470c000 ( 71.047 MB) 3.61% 3.47% |
| 104 | +Image 225 0`02e8f000 ( 46.559 MB) 2.36% 2.27% |
| 105 | +Other 37 0`021af000 ( 33.684 MB) 1.71% 1.64% |
| 106 | +Stack32 39 0`00d00000 ( 13.000 MB) 0.66% 0.63% |
| 107 | +Stack64 39 0`00340000 ( 3.250 MB) 0.16% 0.16% |
| 108 | +Heap64 4 0`00039000 ( 228.000 kB) 0.01% 0.01% |
| 109 | +TEB64 13 0`0001a000 ( 104.000 kB) 0.01% 0.00% |
| 110 | +TEB32 13 0`0001a000 ( 104.000 kB) 0.01% 0.00% |
| 111 | +Other32 1 0`00001000 ( 4.000 kB) 0.00% 0.00% |
| 112 | +PEB64 1 0`00001000 ( 4.000 kB) 0.00% 0.00% |
| 113 | +PEB32 1 0`00001000 ( 4.000 kB) 0.00% 0.00% |
| 114 | +``` |
| 115 | + |
| 116 | +### Collect trace data for virtual allocation memory |
| 117 | + |
| 118 | +Since you have the way to identify the leaking memory, the next step is to collect reproducible data to determine the driver responsible for the leaking allocations. |
| 119 | + |
| 120 | +Use the following command to collect data when the process shows the behavior. **WPR.exe** is included natively on operating systems after Windows 10 or Windows Server 2016. |
| 121 | + |
| 122 | +Run the following command from a command prompt as an administrator: |
| 123 | + |
| 124 | +```console |
| 125 | +C:\>wpr -start VirtualAllocation |
| 126 | +``` |
| 127 | + |
| 128 | +Allow the process to run for some time. You can monitor the growth of memory consumption with Task Manager (**Commit size**). |
| 129 | + |
| 130 | +Since it only collects virtual allocation data, the trace file doesn't grow so large, so you can leave it running for several minutes. Once you see enough leaked memory, stop the trace by using the following command: |
| 131 | + |
| 132 | +```console |
| 133 | +C:\>wpr -stop virtalloc.etl |
| 134 | +``` |
| 135 | + |
| 136 | +### Collect trace data for heap allocation memory |
| 137 | + |
| 138 | +Like virtual allocation, you can also use WPR for heap tracing. |
| 139 | + |
| 140 | +However, a registry modification is required to enable the heap tracing. You can manually modify the registry or run the following command to enable heap tracing for the target process (for example, **VirtMemTest32.exe**). |
| 141 | + |
| 142 | +Run the following command from a command prompt as an administrator: |
| 143 | + |
| 144 | +```console |
| 145 | +C:\>wpr -heaptracingconfig VirtMemTest32.exe enable |
| 146 | +``` |
| 147 | + |
| 148 | +> [!NOTE] |
| 149 | +> If the process is running when you run the command, restart the process for the setting to be enabled. |
| 150 | +
|
| 151 | +Heap tracing is successfully enabled for process **VirtMemTest64.exe**. |
| 152 | + |
| 153 | +The result is: |
| 154 | + |
| 155 | +Registry key: `Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Image File Execution Options\VirtMemTest32.exe` |
| 156 | +Value name: `Tracing Flags` |
| 157 | +Value type: `REG_DWORD` |
| 158 | +Value data: `0x00000001 (1)` |
| 159 | + |
| 160 | +You can delete the registry key or set the value to `0` after troubleshooting. |
| 161 | + |
| 162 | +Use the following command to collect data when the process shows the behavior. **WPR.exe** is included natively on operating systems after Windows 10 or Windows Server 2016. |
| 163 | + |
| 164 | +Run the following command from a command prompt as an administrator: |
| 165 | + |
| 166 | +```console |
| 167 | +C:\>wpr -start Heap |
| 168 | +``` |
| 169 | + |
| 170 | +Allow the process to run for some time. You can monitor the growth of memory consumption with Task Manager (**Commit size**). |
| 171 | + |
| 172 | +Since it only collects heap data, the trace file doesn't grow so large, so you can leave it running for several minutes. Once you see enough leaked memory, stop the trace by using the following command: |
| 173 | + |
| 174 | +```console |
| 175 | +C:\>wpr -stop Heap.etl |
| 176 | +``` |
| 177 | + |
| 178 | +## Analyze data |
| 179 | + |
| 180 | +Use **WPA.exe** to open the trace. WPA can be downloaded via the Assessment and Deployment Kit (ADK) package for the Windows Performance Toolkit. |
| 181 | + |
| 182 | +Open WPA and set up the symbol path. In the menu, select **Trace** > **Configure Symbol Paths**. Configure symbols by adding the public symbol path as `srv*C:\LocalPubSymbols*https://msdl.microsoft.com/download/symbols`, so you can load symbols (in the menu, select **Trace** > **Load Symbols**) before checking the trace. |
| 183 | + |
| 184 | +### Analyze trace data for virtual allocation memory |
| 185 | + |
| 186 | +Replicate the following view by replacing the process with the one you've identified as relevant. Ensure that the **Commit Stack** column is on the left of the gold/yellow line. Drill down by expanding the stack, and you see the function that shows the allocation of virtual memory. The driver listed before (up) the function is the one calling to that operation. |
| 187 | + |
| 188 | +:::image type="content" source="./media/troubleshoot-application-service-memory-leaks/trace-data-virtual-allocation.png" alt-text="Screenshot of the analysis trace data for virtual allocation memory." lightbox="./media/troubleshoot-application-service-memory-leaks/trace-data-virtual-allocation.png"::: |
| 189 | + |
| 190 | +### Analyze trace data for heap allocation memory |
| 191 | + |
| 192 | +Replicate the following view by replacing the process with the one you've already identified as relevant. Ensure that the **Handle** and **Stack** columns are on the left of the gold/yellow line. Drill down by expanding the stack, and you see the function that shows the allocation of heap memory. The driver listed before (up) the function is the one calling to that operation. |
| 193 | + |
| 194 | +> [!NOTE] |
| 195 | +> If you don't see the heap allocation graph, it's because the registry key isn't set correctly. Review the steps. |
| 196 | +
|
| 197 | +:::image type="content" source="./media/troubleshoot-application-service-memory-leaks/trace-data-heap-allocation.png" alt-text="Screenshot of the analysis of the trace data for heap allocation memory." lightbox="./media/troubleshoot-application-service-memory-leaks/trace-data-heap-allocation.png"::: |
| 198 | + |
| 199 | +:::image type="content" source="./media/troubleshoot-application-service-memory-leaks/heap-allocation-function-driver.png" alt-text="Screenshot of the analysis of the trace data for heap allocation memory with the drive listed." lightbox="./media/troubleshoot-application-service-memory-leaks/heap-allocation-function-driver.png"::: |
0 commit comments