.NET Core에서 높은 CPU 사용량 디버그
이 문서의 적용 대상: ✔️ .NET Core 3.1 SDK 이상 버전
이 자습서에서는 과도한 CPU 사용량 시나리오를 디버그하는 방법을 알아봅니다. 제공된 예제 ASP.NET Core 웹앱 소스 코드 리포지토리를 사용하면 교착 상태를 의도적으로 초래할 수 있습니다. 엔드포인트가 응답을 중지하고 스레드가 누적됩니다. 다양한 도구를 사용하여 진단 데이터의 몇 가지 주요 부분으로 이 시나리오를 진단하는 방법을 알아봅니다.
이 자습서에서는 다음을 수행합니다.
- 높은 CPU 사용량 조사
- dotnet-counters를 사용하여 CPU 사용량 확인
- 추적 생성을 위해 dotnet-trace 사용
- PerfView에서 성능 프로파일링
- 과도한 CPU 사용량 진단 및 해결
필수 조건
이 자습서에서는 다음을 사용하여 작업을 수행합니다.
- .NET Core 3.1 SDK 이상 버전.
- 시나리오를 트리거하는 샘플 디버그 대상.
- 프로세스를 나열하고 프로필을 생성하는 dotnet-trace.
- CPU 사용량을 모니터링하는 dotnet-counters.
CPU 카운터
진단 데이터를 수집하기 전에 높은 CPU 판단 기준을 관찰해야 합니다. 프로젝트 루트 디렉터리에서 다음 명령을 사용하여 샘플 애플리케이션을 실행합니다.
dotnet run
프로세스 ID를 찾으려면 다음 명령을 사용합니다.
dotnet-trace ps
명령 출력에서 프로세스 ID를 기록해 둡니다. 기존 프로세스 ID는 22884
였지만 사용자의 프로세스 ID는 다를 것입니다. 현재 CPU 사용량을 확인하려면 dotnet-counters 도구 명령을 사용합니다.
dotnet-counters monitor --refresh-interval 1 -p 22884
refresh-interval
은 카운터 폴링 CPU 값 사이의 시간(초)입니다. 출력은 다음과 같은 형태가 됩니다.
Press p to pause, r to resume, q to quit.
Status: Running
[System.Runtime]
% Time in GC since last GC (%) 0
Allocation Rate / 1 sec (B) 0
CPU Usage (%) 0
Exception Count / 1 sec 0
GC Heap Size (MB) 4
Gen 0 GC Count / 60 sec 0
Gen 0 Size (B) 0
Gen 1 GC Count / 60 sec 0
Gen 1 Size (B) 0
Gen 2 GC Count / 60 sec 0
Gen 2 Size (B) 0
LOH Size (B) 0
Monitor Lock Contention Count / 1 sec 0
Number of Active Timers 1
Number of Assemblies Loaded 140
ThreadPool Completed Work Item Count / 1 sec 3
ThreadPool Queue Length 0
ThreadPool Thread Count 7
Working Set (MB) 63
웹앱을 실행하면 시작 직후에 CPU가 전혀 소비되지 않고 0%
에 보고됩니다. 경로 매개 변수로 60000
을 사용하여 api/diagscenario/highcpu
경로로 이동합니다.
https://localhost:5001/api/diagscenario/highcpu/60000
이제 dotnet-counters 명령을 다시 실행합니다. cpu-usage
카운터만 모니터링하려면 이전 명령에 '--counters System.Runtime[cpu-usage]`를 추가합니다. CPU가 소비되고 있는지 확실하지 않으므로 위와 동일한 카운터 목록을 모니터링하여 카운터 값이 애플리케이션의 예상 범위 내에 있는지 확인합니다.
dotnet-counters monitor -p 22884 --refresh-interval 1
아래와 같이 CPU 사용량이 증가하는 것을 확인할 수 있습니다(호스트 컴퓨터에 따라 CPU 사용량이 달라질 수 있음).
Press p to pause, r to resume, q to quit.
Status: Running
[System.Runtime]
% Time in GC since last GC (%) 0
Allocation Rate / 1 sec (B) 0
CPU Usage (%) 25
Exception Count / 1 sec 0
GC Heap Size (MB) 4
Gen 0 GC Count / 60 sec 0
Gen 0 Size (B) 0
Gen 1 GC Count / 60 sec 0
Gen 1 Size (B) 0
Gen 2 GC Count / 60 sec 0
Gen 2 Size (B) 0
LOH Size (B) 0
Monitor Lock Contention Count / 1 sec 0
Number of Active Timers 1
Number of Assemblies Loaded 140
ThreadPool Completed Work Item Count / 1 sec 3
ThreadPool Queue Length 0
ThreadPool Thread Count 7
Working Set (MB) 63
요청 기간 동안 CPU 사용량은 증가된 비율을 중심으로 유지됩니다.
팁
더 높은 CPU 사용량을 시각화하기 위해 여러 브라우저 탭에서 이 엔드포인트를 동시에 실행할 수 있습니다.
이 시점에서는 CPU가 예상보다 높게 실행되고 있다고 봐도 무방합니다. 문제의 영향을 식별하는 것이 원인을 찾는 데 중요합니다. 문제의 원인을 찾기 위해 진단 도구 외에 높은 CPU 사용량 효과를 활용할 예정입니다.
Profiler를 사용하여 높은 CPU 분석
CPU 사용량이 높은 앱을 분석할 때는 코드가 수행하는 작업에 대한 인사이트를 제공할 수 있는 진단 도구가 필요합니다. 일반적으로 프로파일러를 선택하며, 선택할 수 있는 다양한 프로파일러 옵션이 있습니다. dotnet-trace
는 모든 운영 체제에서 사용할 수 있지만 안전 지점 바이어스 및 관리 전용 호출 스택의 제한 사항으로 인해 Linux용 'perf' 또는 Windows용 ETW와 같은 커널 인식 프로파일러에 비해 더 일반적인 정보가 제공됩니다. 성능 조사에 관리 코드만 관련된 경우 일반적으로 dotnet-trace
이면 충분합니다.
perf
도구를 사용하여 .NET Core 앱 프로필을 생성할 수 있습니다. dotnet-trace를 사용할 수도 있지만 이 도구를 시연해 보겠습니다. 샘플 디버그 대상의 이전 인스턴스를 종료합니다.
.NET 앱이 /tmp
디렉터리에 map
파일을 만들도록 DOTNET_PerfMapEnabled
환경 변수를 설정합니다. 이 map
파일은 perf
에서 CPU 주소를 이름별로 JIT 생성 함수에 매핑하는 데 사용됩니다. 자세한 내용은 성능 맵 및 jit 덤프 내보내기를 참조하세요.
참고 항목
.NET 6은 .NET 런타임 동작을 구성하는 환경 변수에 대해 COMPlus_
대신 접두사 DOTNET_
을 표준화합니다. 그러나 COMPlus_
접두사도 계속 작동합니다. 이전 버전의 .NET 런타임을 사용하는 경우에도 환경 변수에 COMPlus_
접두사를 사용해야 합니다.
동일한 터미널 세션에서 샘플 디버그 대상을 실행합니다.
export DOTNET_PerfMapEnabled=1
dotnet run
높은 CPU API 엔드포인트(https://localhost:5001/api/diagscenario/highcpu/60000
)를 다시 실행합니다. 1분 요청 내에서 실행되는 동안 프로세스 ID를 사용하여 perf
명령을 실행합니다.
sudo perf record -p 2266 -g
perf
명령이 성능 수집 프로세스를 시작합니다. 약 20~30초 동안 실행한 후 Ctrl+C를 눌러 수집 프로세스를 종료합니다. 동일한 perf
명령을 사용하여 추적의 출력을 볼 수 있습니다.
sudo perf report -f
다음 명령을 사용하여 flame-graph를 생성할 수도 있습니다.
git clone --depth=1 https://github.com/BrendanGregg/FlameGraph
sudo perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > flamegraph.svg
이 명령은 성능 문제를 조사하기 위해 브라우저에서 볼 수 있는 flamegraph.svg
를 생성합니다.
Visual Studio를 사용하여 높은 CPU 데이터 분석
모든 *.nettrace 파일은 Visual Studio에서 분석할 수 있습니다. Visual Studio에서 Linux *.nettrace 파일을 분석하려면 기타 필요한 문서와 함께 *.nettrace 파일을 Windows 컴퓨터로 전송한 다음 Visual Studio에서 *.nettrace 파일을 엽니다. 자세한 내용은 CPU 사용 현황 데이터 분석을 참조하세요.
참고 항목
- 프로세스를 나열하는 dotnet-trace
- 관리되는 메모리 사용량을 검사하는 dotnet-counters
- 덤프 파일을 수집 및 분석하는 dotnet-dump
- dotnet/diagnostics
다음 단계
.NET