한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

게임 렉 백서 › L10 메모리

GC 스래싱 (힙 여유 부족) GC thrashing (heap nearly full)

원인 ID mem-gc-thrash · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

그림과 실험이 있는 원본 카드로 열기 →

살아 있는 데이터가 힙 한도에 가까워지면, GC가 돌아도 회수할 것이 거의 없어 GC가 쉬지 않고 반복됩니다.

왜 이벤트 인원 증가나 누수로 살아 있는 데이터가 힙 한도 가까이 참 → 그러면 GC가 조금밖에 회수하지 못해 곧바로 다시 Full GC, CPU 대부분을 GC가 씀 → 화면에서는 서버 전체가 몇 분간 슬로우모션·멈춤을 반복하다 메모리 부족으로 종료

증상
슬로우모션, 멈춤, 접속 끊김
요인
정체
누가 겪나
서버 전체
언제
저녁 피크 시간, 사람이 몰릴 때, 오래 켜 둘수록
담당
주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라
게임개발팀 할 일
힙을 피크 때 살아 있는 데이터보다 넉넉하게(보통 2배 이상) 설정, 오래 참조하는 데이터·누수 줄이기.
인프라팀 할 일
GC 시간 비율 경보, 버티지 말고 빨리 재시작, 힙을 키울 수 있게 메모리가 넉넉한 인스턴스.
수치 감각
실행 시간의 10% 넘게 GC가 쓰면 보통 위험 신호로 봅니다. Java의 일부 GC는 시간의 98%를 GC에 쓰고도 거의 회수하지 못하면 메모리 부족 오류를 냅니다.
그래프에서는
한도에 닿아 평평해짐 · GC 직후 힙, GC 시간 비율
확인할 곳
GC 직후 남은 힙이 최대 힙에 얼마나 가까운지와 GC에 쓴 시간 비율을 봄. Java는 -Xlog:gc 줄의 “GC 후(힙 크기)”와 Pause Full 줄의 빈도, .NET은 dotnet-counters(.NET 8 이하 % Time in GC since last GC, .NET 9 이후 dotnet.gc.pause.time 증가량), Go는 GODEBUG=gctrace=1 줄 사이 간격을 봄
이러면 맞음
GC 직후에도 힙이 최대치 가까이 남고 Full GC가 연달아 돌며 GC 시간 비율이 평소보다 크게(보통 10% 넘게) 올라감. 그동안 서버 전체 틱이 함께 느려짐
이러면 아님
GC 직후 힙에 여유가 있는데 멈춤만 길면 GC 방식·설정 쪽(mem-gc)
확인 수단
인프라 도구로 확인(게임 코드 불필요)

출처

  1. The Parallel Collector Oracle
    병렬 GC는 전체 시간의 98% 넘게 GC를 하고도 힙을 2% 미만 회수하면 OutOfMemoryError
  2. Garbage-First Garbage Collector Tuning Oracle
    G1은 기본(GCTimeRatio=12)으로 GC 시간을 전체의 약 8% 이하로 맞추도록 힙 크기를 정함, 힙 점유가 너무 높아 생긴 Full GC는 로그의 Pause Full (G1 Compaction Pause)로 찾음
  3. A Guide to the Go Garbage Collector Go
    기본 GOGC=100이면 목표 힙이 살아 있는 힙의 약 2배, 메모리 한도에 붙으면 GC가 쉬지 않고 도는 스래싱, GODEBUG=gctrace=1로 GC 추적 출력
  4. Garbage Collector Implementation Oracle
    -Xlog:gc 줄은 GC 종류(Pause Young, Pause Full)와 “GC 전 사용량->GC 후 사용량(힙 크기)”, 멈춘 시간
  5. dotnet-counters diagnostic tool .NET
    .NET 9 이후는 dotnet.gc.pause.time, .NET 8 이하는 % Time in GC since last GC로 표시

함께 보면 좋은 원인

같은 층: L10 메모리

같은 증상(슬로우모션)의 다른 층 원인

그림과 실험이 있는 원본 카드 보기