To analyze a dump file for high CPU usage using WinDbg, you can follow these detailed steps:
- Set Up Your Environment: Begin by setting up WinDbg and ensuring you have the correct symbol paths configured. Symbols are critical for accurately interpreting the dump file and understanding what each thread and function call represents.
.sympath srvC:\Symbolshttp://msdl.microsoft.com/download/symbols
- Open the Dump File: Load the dump file into WinDbg by selecting
File > Open Crash Dumpfrom the menu. This will load the file and allow you to begin your analysis. - Load Necessary Extensions: Make sure to load any necessary extensions, such as the SOS extension for .NET applications, using the
.loadcommand. This step is crucial for debugging both native and managed code. - The list item has been kept at the same length as the original.
User Mode Time
Thread Time
0:10c8 0 days 0:00:15.218
2:064c 0 days 0:00:05.789
3:0884 0 days 0:00:03.281
- Switch to the High CPU Thread:
- Select the thread you want to analyze by using the
~command followed by the thread number andsto switch context. Once you have switched context, you can review the conversation and gather insights. - Example:
~3s(if thread 3 is the one with high CPU usage).
- Select the thread you want to analyze by using the
- Analyze the Call Stack:
- Use the
kb(ork,kp,kpn) command to display the call stack of the selected thread. This provides insight into the function calls that are active on that thread, helping to understand the program’s execution flow and identify potential issues. - Example:
kb
- Use the
Child-SP RetAddr Call Site
000000000014e548 00007ff6db12af54 myapp!SomeFunction+0x34
000000000014e550 00007ff6db12b12a myapp!AnotherFunction+0x5e
000000000014e580 00007ffa7a9b8182 kernel32!BaseThreadInitThunk+0x22
000000000014e5b0 0000000000000000 ntdll!RtlUserThreadStart+0x34
- Analyze Managed Code (If Applicable):
- If the application involves managed code, particularly .NET, use the SOS extension to examine the managed call stack. The
!clrstackcommand will display the call stack for the managed code. - Example:
!clrstack- Ensure to carefully review the output of the
!clrstackcommand to identify potential issues or anomalies within the managed call stack.
- Ensure to carefully review the output of the
- If the application involves managed code, particularly .NET, use the SOS extension to examine the managed call stack. The
OS Thread Id: 0x10c8 (0)
Child SP IP Call Site
000000000014e548 00007ff6db12af54 MyApp.Program.Main()
000000000014e550 00007ff6db12b12a System.Threading.ThreadHelper.ThreadStart()
- Check for Blocking Issues:
- Sometimes high CPU usage can be due to blocking issues or contention on locks. Use the
!locksor!syncblkcommands to identify any potential locking issues.
- Sometimes high CPU usage can be due to blocking issues or contention on locks. Use the
CritSec MyApp!SomeCriticalSection+0 at 00007ff6`db12af54
LockCount 1
RecursionCount 1
OwningThread 10c8
- This shows that a critical section is held by thread 0x10c8.
- Inspect Other Threads:
- If the initial thread doesn’t provide enough insight, repeat the above steps for other threads identified by
!runawayas having high CPU usage.
- If the initial thread doesn’t provide enough insight, repeat the above steps for other threads identified by
~*e !thread
0:10c8 0x0000000000000000 ntdll!ZwWaitForSingleObject+0xa
1:064c 0x0000000000000000 kernel32!WaitForSingleObjectEx+0x94
2:0884 0x0000000000000000 MyApp!SomeOtherFunction+0x32
- Evaluate Thread States:
- To get a sense of what other threads are doing, use the
~*e !threadcommand, which lists the state of all threads. This can help identify any patterns or anomalies in thread activity.
- To get a sense of what other threads are doing, use the
~*k
. 0 Id: 10c8.0e18 Suspend: 0 Teb: 00007ff6dafca000 Unfrozen # Child-SP RetAddr Call Site 00 000000000014e548 00007ff6`db12af54 myapp!SomeFunction+0x34
Examine CPU Consumption Over Time:
!runaway time
User Mode Time
Thread Time
0:10c8 0 days 0:00:15.218
1:064c 0 days 0:00:00.500
2:0884 0 days 0:00:00.200
- Check Module Involvement:
- Run
lmto list all loaded modules. This can help identify any third-party libraries or unusual modules that might be contributing to the high CPU usage.
- Run
start end module name
00007ff6dafc0000 00007ff6db100000 myapp (deferred)
00007ff6db100000 00007ff6db200000 someother (deferred)
In the memory layout of the application, the “myapp” module, located in the address range 00007ff6dafc0000 to 00007ff6db100000, is currently in a deferred state. Following this, the “someother” module occupies the range 00007ff6db100000 to 00007ff6db200000, also in a deferred state. This information provides a glimpse into the dynamic loading and unloading of modules within the application’s memory space, contributing to its overall functionality and behavior.
- Look for Resource Leaks:
- Use commands like
!vmor!heapto check for memory or resource leaks, which can sometimes correlate with high CPU usage.
- Use commands like
- Save and Document Findings:
- Document your findings by saving the command outputs using
.logopenand.logclose. This can be invaluable for reporting and further analysis.
- Document your findings by saving the command outputs using
- Advanced Analysis:
- Depending on the complexity of the issue, you may need to dive deeper using additional commands like
!analyze,!gcroot(for garbage collection issues in .NET), or!dumpheap(to analyze the heap and potential memory issues).
- Depending on the complexity of the issue, you may need to dive deeper using additional commands like
- Cross-Reference with Application Logs:
- It can also be helpful to cross-reference your findings with application logs or performance counters to correlate CPU usage patterns with specific events or workloads.
Remember that analyzing dump files for high CPU usage is an iterative process. You might need to cycle through several different threads and commands to uncover the root cause. Building familiarity with WinDbg and its extensive command set is key to becoming proficient in diagnosing and resolving high CPU issues.