KeiStory

dotnet-dump 사용 및 분석하기

 

서버에서 메모리 조사가 필요해 dump 를 떠서 확인할 일이 있어 분석하는 방법에 대해 알아봅니다.

 

[도구설치]

dotnet tool install -g dotnet-dump


[실행중인 .net process 목록]

dotnet-dump ps

 

[특정 process dump 수집] : dump 파일 생성

dotnet-dump collect --process-id 71864

 

[dump 파일 분석 모드 진입]

dotnet-dump analyze dump_20241011_220524.dmp

 

아래 명령어 부터는 분석 모드 진입 후 명령입니다. 


[스택 트레이스]

clrstack



[Heap 검사 - 메모리상태]

dumpheap -stat

사이즈 작은 순으로 정렬되어 보입니다.


[객체가 할당된 힙 영역과 해당 객체]

dumpheap -type <ClassName>
dumpheap -type Roslyn.Utilities.StringTable+Entry[]


[특정 메모리 주소의 개체를 확인]

dumpobj 02229f7a3d50


[스레드 목록을 확인]

threads

 

[전체 메모리 맵 확인]

eeheap -gc


[메모리 누수 탐지] - 메모리주소기준

gcroot 02229f7a3d50


[쓰레드별 메모리 사용량 확인]

clrthreads

 

[Excpetion 확인]

dumpheap -type Exception

 

[덤프파일의 메모리 분석 결과를 파일로 보내기]

dotnet-dump analyze <dump-file> -c "dumpheap -stat" > heap_stat.txt

 

아래와 같이 dump 파일을 Visual Studio 에서 열고 진단 분석 실행을 하게 되면

당시의 cpu, memory 사용량등을 확인할 수 있습니다.

 

참고

https://learn.microsoft.com/ko-kr/dotnet/core/diagnostics/dotnet-dump

 

dotnet-dump 진단 도구 - .NET CLI - .NET

네이티브 디버거 없이 Windows 및 Linux 덤프를 수집하고 분석하기 위해 dotnet-dump CLI 도구를 설치하고 사용하는 방법을 알아봅니다.

learn.microsoft.com

 

 

분석내용 ( clrthreads )

lrthreads 명령어 출력 결과는 .NET 런타임 내의 스레드 상태와 관련된 정보를 보여줍니다. 이 정보를 통해 스레드의 상태, GC 모드, 할당 컨텍스트, 스레드 풀 관련 여부 등을 확인할 수 있습니다. 여기에서 주요 항목을 설명하고 각 스레드가 어떤 상태에 있는지 분석해 보겠습니다.

1. 스레드 개요

출력된 정보에서 다음과 같은 요약을 확인할 수 있습니다:

  • 전체 스레드 수: 17
  • 실행 중인 스레드 수: 8 (Background 스레드)
  • Dead 상태의 스레드 수: 8 (DeadThread: 8)
  • Background 스레드: 백그라운드 작업을 처리하는 스레드 (주로 스레드풀에서 실행됨)

2. 스레드 상태와 정보 해석

각 스레드의 상태와 추가 정보를 확인해 보겠습니다:

  • ID: .NET 스레드 ID입니다. 디버깅할 때 사용할 수 있는 고유 ID입니다.
  • OSID: 운영 체제의 스레드 ID입니다. Windows Task Manager나 top 등의 프로세스 모니터링 툴에서 이 ID로 스레드를 확인할 수 있습니다.
  • ThreadOBJ: 각 스레드의 .NET 내부 스레드 객체의 메모리 주소입니다.
  • State: 스레드의 현재 상태입니다. 다음과 같은 값들을 가집니다:
    • Preemptive: GC가 스레드를 언제든지 중단할 수 있는 상태.
    • Background: 백그라운드에서 실행 중인 스레드.
    • Wait: 스레드가 어떤 이벤트나 리소스를 기다리고 있는 상태.
    • Dead: 더 이상 실행되지 않는 스레드.
  • GC Mode: GC가 스레드를 중지할 수 있는지 여부를 나타냅니다.
    • Preemptive: GC가 스레드를 중지할 수 있는 상태.
    • Cooperative: GC가 스레드를 중지하지 못하고 협력 모드로 동작하는 상태.
  • GC Alloc Context: 스레드의 GC 할당 컨텍스트를 나타내는 주소입니다.
  • Domain: 해당 스레드가 속한 애플리케이션 도메인의 메모리 주소.
  • Exception: 스레드가 예외를 던진 경우, 여기서 예외 정보를 확인할 수 있습니다.

3. 상세 분석

각 스레드의 상태를 분석해 보겠습니다:

  1. 스레드 0 (ID: 1, OSID: 118bc)
    • 상태: 202a020 Preemptive
    • GC Mode: Preemptive
    • GC 할당 컨텍스트가 0으로 설정되어 있어 현재 메모리 할당을 기다리고 있지 않음.
    • 일반 MTA (멀티 스레딩 모델) 스레드로 보입니다.
  2. 스레드 3 (ID: 2, OSID: 118dc)
    • 상태: 2b220 Preemptive
    • Finalizer 스레드: 이 스레드는 .NET의 Finalizer 스레드로, GC가 수집한 객체의 소멸자를 실행하는 스레드입니다.
    • 이 스레드가 블로킹되면 프로그램이 종료되지 않을 수 있으므로 주의해야 합니다.
  3. 스레드 4 (ID: 4, OSID: 1190c)
    • 상태: 202b220 Preemptive
    • MTA 스레드
    • 현재 특별한 작업을 수행하지 않고 대기 중인 것으로 보입니다.
  4. 스레드 6 (ID: 6, OSID: 11920)
    • 상태: 302b220 Preemptive
    • MTA 스레드이며 Threadpool Worker로 등록되어 있습니다.
    • 이 스레드는 스레드 풀 내에서 작업을 수행하고 있으며, 현재 특정 작업을 수행하고 있지는 않습니다.
  5. XXXX 스레드들
    • 여러 스레드가 Ukn (Unknown) 상태로 보입니다.
    • 이 스레드들은 일반적으로 스레드 풀에서 할당된 후 사용되지 않은 상태이거나 이미 종료된 스레드일 가능성이 있습니다.
    • 상태 코드가 1039820으로 설정되어 있고, GC 할당 컨텍스트가 모두 0으로 되어 있으므로, 이 스레드들은 Dead 상태의 스레드입니다.
  6. 스레드 7~9 (ID: 11, 12, 13)
    • 상태: 102b220 Preemptive
    • 모두 Threadpool Worker 상태입니다.
    • 스레드 풀에서 생성된 MTA 스레드이며, 현재 대기 상태로 보입니다.
  7. 스레드 10 (ID: 17, OSID: 11b68)
    • 상태: 202b220 Preemptive
    • MTA 스레드
    • 특별한 작업을 수행하지 않고 대기 중인 상태입니다.
  8. 스레드 11 (ID: 18, OSID: 11b6c)
    • 상태: 202b220 Preemptive
    • 이 스레드는 다른 스레드와 다르게 GC Alloc Context가 설정되어 있습니다.
    • 특정 메모리 할당을 대기 중이거나 메모리 할당 작업을 수행 중일 수 있습니다.

4. 특이사항 요약

  • Dead 상태의 스레드: 8개의 스레드가 종료 상태 (DeadThread)로 나타나며, 이는 애플리케이션의 리소스 사용을 증가시킬 수 있으므로 필요하지 않은 경우 정리하는 것이 좋습니다.
  • Threadpool Worker 스레드: 대부분의 스레드가 Threadpool Worker로 등록되어 있으며, 현재는 활동하지 않고 대기 중입니다. Threadpool이 과도하게 확장되어 있는지 확인할 필요가 있습니다.
  • Finalizer 스레드 (ID: 2): Finalizer 스레드는 매우 중요한 스레드이므로 블로킹이나 대기 상태가 길어지면 문제가 될 수 있습니다. 이 스레드가 예외를 던지거나 블로킹된 상태가 아닌지 확인이 필요합니다.
  • Unknown 상태 스레드: Ukn (Unknown) 상태의 스레드가 많이 보이는데, 이는 주로 이미 종료되었거나 비활성화된 스레드일 가능성이 높습니다.

5. 다음 단계

현재 상태로는 스레드가 과도하게 생성된 듯 보이며, 특히 종료된 Dead 상태의 스레드가 많습니다. 이러한 스레드를 지속적으로 모니터링하고 필요하지 않다면 스레드풀 크기를 줄이거나 리소스를 해제해야 합니다.

추가로 !threads 명령어와 ~*kb를 사용하여 스택 트레이스를 확인하면, 각 스레드가 어떤 작업을 수행 중인지 더 자세히 파악할 수 있습니다.

반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band