멈춤이 짧은 GC(ZGC, Shenandoah, 목표 시간을 줄인 G1)를 실행 옵션으로 직접 지정, 할당 줄이기, 힙 크기 조정.
인프라팀 할 일
힙을 넉넉히 줄 수 있는 메모리의 인스턴스, 컨테이너에는 CPU 2개 이상·메모리 약 1.8GB 이상 배정(JDK 26 이하는 그보다 작으면 Serial GC를 기본으로 고름), GC 멈춤 시간 모니터링.
수치 감각
새 객체(Young 영역)만 수집하는 Minor GC는 수~수십 ms. 살아 있는 데이터가 수 GB인 힙 전체를 수집하는 Full GC는 1초를 넘기도 합니다. ZGC는 힙 크기와 거의 상관없이 1ms 미만이고 Shenandoah도 멈춤이 힙 크기에 비례하지 않아 짧습니다.
그래프에서는
일정 주기로 튐 · 서버 틱 시간, GC 멈춤 시간
확인할 곳
GC 로그를 켜서 멈춘 시각과 길이를 서버 틱 시간 그래프에 겹쳐 봄. Java는 시작 옵션 -Xlog:gc*(JDK 8 이하는 -XX:+PrintGCDetails)의 Pause 줄, .NET은 dotnet-counters의 GC 멈춤 지표(.NET 9 이후 dotnet.gc.pause.time, 8 이하 % Time in GC since last GC), Go는 GODEBUG=gctrace=1이 GC마다 남기는 줄을 봄
이러면 맞음
틱이 튄 시각과 GC 멈춤 시각이 겹치고 멈춤 길이가 튄 길이와 비슷함. 서버의 모든 존·채널이 같은 순간에 튐
이러면 아님
GC 로그에 긴 멈춤이 없는데도 틱이 튀면 락·동기 호출·디스크 쓰기 같은 다른 원인. 한 존만 튀면 스크립트 엔진의 GC(mem-script-gc)나 그 존의 부하
확인 수단
인프라 도구로 확인(게임 코드 불필요)
더 알아보기
Java의 G1은 한 번 멈춤 목표가 기본 200ms라, 20틱 서버에서는 틱 4개에 해당합니다. 컨테이너에 CPU를 2개 미만이나 메모리를 약 1.8GB 미만으로 주면 JDK 26 이하의 Java는 단일 스레드로 수집하는 Serial GC를 기본 GC로 골라 멈춤이 훨씬 길어집니다. C#(.NET) 서버는 보통 서버 GC와 백그라운드 GC를 켜지만 새 객체를 담는 0·1세대(Gen0·1) 수집과 압축을 동반한 Full GC는 여전히 모든 스레드를 멈춥니다. Go는 멈춤이 보통 1ms 미만이지만 할당이 많으면 메모리를 요청한 쪽이 GC 작업을 분담해야 해서 틱이 느려집니다. 어느 방식이든 할당이 수집보다 빠르면 결국 게임 스레드가 멈춥니다. G1은 Full GC로 넘어가고 ZGC는 메모리를 요청한 스레드를 수집이 끝날 때까지 멈춥니다.