[JAVA] 공식문서로 공부하는 Garbage Collection - Ch 4. Factors Affecting Garbage Collection Performance

예름·2025년 3월 17일
3

Java

목록 보기
5/9

Oracle의 공식문서 HotSpot Virtual Machine Garbage Collection Tuning Guide을 참고했습니다.

📍 전체 힙(Total Heap) 성능 개선 방법
📍 Young Generation 성능 개선 방법

📍 개요

가비지 컬렉션 성능에 영향을 미치는 가장 중요한 두 가지 요소는 사용 가능한 전체 메모리와 Young Generation에 할당된 힙 비율이다.


🔎 전체 힙 (Total Heap)

가비지 컬렉션 성능에 영향을 미치는 가장 중요한 요소는 사용 가능한 전체 메모리(Total Heap Size)이다.
세대(Generation)가 가득 차면 가비지 컬렉션이 실행되므로, 힙 크기가 클수록 처리량(Throughput)이 높아진다.

❓ 왜 힙 크기가 클수록 처리량이 높아질까?

힙 크기가 클수록 GC 발생 횟수가 줄어들어 애플리케이션이 더 많은 작업을 수행할 수 있다.

참고: 아래 설명에서는 Serial GC를 예시로 들어 설명한다.
다른 가비지 컬렉터도 유사한 메커니즘을 사용하지만, 세부 사항은 다를 수 있다.

✅ 힙 크기에 영향을 주는 옵션 (Heap Options Affecting Generation Size)

JVM의 힙 크기는 여러 옵션에 의해 영향을 받는다.
아래 그림(Figure 4-1)은 커밋된 공간(Committed Space)가상 공간(Virtual Space)의 차이를 나타낸다.

JVM이 실행될 때 힙의 전체 공간이 예약(Reserved) 된다.

  • -Xmx 옵션을 사용하여 이 예약된 공간의 크기를 지정할 수 있다.
  • -Xms 값이 -Xmx 값보다 작다면, 예약된 공간의 일부만 즉시 커밋된다.
  • 커밋되지 않은 공간은 “Virtual” 공간으로 표시된다.

❓ Reserved vs Committed

  • Reserved: JVM이 사용할 힙 공간을 미리 확보해 놓음. 하지만 운영체제(OS)에서 실제로 이 메모리를 즉시 할당하지는 않음.

  • Committed: JVM이 실제로 운영체제에서 메모리를 할당받아 사용하는 공간.

JVM이 힙을 어떻게 예약하고 사용할지를 결정하는 대표적인 옵션이 -Xmx와 -Xms이다.

🛠️ 예제

java -Xms512m -Xmx2g MyApp
  • -Xms512m: 초기 실행 시 512MB만큼 메모리를 즉시 할당(Committed)
  • -Xmx2g: 최대 2GB까지 힙 공간을 확장할 수 있음 (Reserved)

각 세대(Young/Old Generation)는 필요할 때 가상 공간까지 확장할 수 있다.

  • -XX:NewRatio: Old Generation과 Young Generation의 크기 비율을 조정하는 옵션
  • 예) -XX:NewRatio=3 → Young Generation이 전체 힙의 1/4이 됨

✅ 힙 크기에 대한 기본 옵션 값 (Default Option Values for Heap Size)

JVM은 각 가비지 컬렉션 이후 힙 크기를 동적으로 조정한다.
즉, 할당된 객체와 여유 공간 비율을 일정 범위 내에서 유지하려고 한다.

이 범위는 다음 옵션으로 조정할 수 있다.

  • -XX:MinHeapFreeRatio=<최소값>
  • -XX:MaxHeapFreeRatio=<최대값>
  • 전체 크기는 -Xms<최소 힙 크기> ~ -Xmx<최대 힙 크기> 내에서 유지됨

📌 기본 동작

  • 여유 공간이 40% 이하라면 → 힙을 확장하여 40% 유지
  • 여유 공간이 70% 이상이라면 → 힙을 축소하여 70% 유지
  • 단, 힙 확장은 -Xmx 값까지만, 축소는 -Xms 값까지만 가능

📌 서버 애플리케이션 힙 크기 가이드라인

1. 메모리가 충분하다면 -Xmx 값을 가능한 크게 설정

  • 기본 설정값은 대개 너무 작아서, 애플리케이션 성능을 저하시킬 가능성이 있음

2. -Xms-Xmx를 동일하게 설정하면 예측 가능성이 높아짐

  • JVM이 힙 크기를 처음부터 고정시키므로, 동적으로 조정하는 과정에서 발생하는 오버헤드가 사라짐
  • 단, 설정값이 적절하지 않다면 JVM이 동적으로 조정할 수 없음

3. 코어 수가 증가하면 힙 크기도 증가시키는 것이 좋음

  • 병렬 할당이 원활해지고, 가비지 컬렉션 발생 빈도를 줄일 수 있음
  • 특히 멀티스레드 애플리케이션에서는 메모리 부족 문제를 방지하기 위해 충분한 힙 크기 설정이 중요함

✅ 최소 힙 크기를 설정하여 동적 메모리 사용량 절감 (Conserving Dynamic Footprint by Minimizing Java Heap Size)

애플리케이션의 최대 RAM 소비량을 줄이려면 힙 크기를 최소화해야 한다.
특히 Java SE Embedded 환경에서는 메모리 절약이 중요하다.

📌 최적화 방법

  • -XX:MaxHeapFreeRatio=10%
  • -XX:MinHeapFreeRatio=<값>
  • -XX:-ShrinkHeapInSteps: 힙을 한 번에 축소하는 옵션
    • 단, 성능 저하 가능성 있음

🔎 Young Generation

전체 사용 가능한 메모리 이후, 가비지 컬렉션 성능에 가장 큰 영향을 주는 두 번째 요소는 Young Generation의 크기 비율이다.

💡 Young Generation이 클수록

  • Minor GC 발생 빈도가 줄어듦

💡 Young Generation이 작을수록

  • Old Generation이 커져서 Major GC 발생 빈도가 증가

즉, Young Generation 크기는 애플리케이션 객체의 수명에 따라 최적의 값을 찾아야 한다.

✅ Young Generation 크기 옵션 (Young Generation Size Options)

  • -XX:NewRatio
    • Young Generation과 Old Generation의 크기 비율
    • 예) -XX:NewRatio=3 → Young Generation이 전체 힙의 1/4이 됨
  • -XX:NewSize, -XX:MaxNewSize
    • Young Generation의 최소/최대 크기 설정

-XX:NewSize-XX:MaxNewSize를 같은 값으로 설정하면 Young Generation 크기가 고정됨

✅ Survivor Space 크기 조정 (Survivor Space Sizing)

Survivor Space 크기는 -XX:SurvivorRatio 옵션을 사용하여 조정할 수 있다.
하지만 대부분의 애플리케이션에서는 Survivor Space 크기가 성능에 큰 영향을 주지 않음

  • -XX:SurvivorRatio=<값>
    • Eden과 Survivor Space의 비율을 조정
    • 예) -XX:SurvivorRatio=6 → Eden:Survivor = 6:1

Survivor Space가 너무 작으면 → 객체가 바로 Old Generation으로 넘어가게 됨
Survivor Space가 너무 크면 → 대부분의 공간이 비어 있어 낭비됨

❓ Survivor Space란?

서바이버 스페이스(Survivor Space) 는 JVM의 Young Generation(젊은 세대) 내에서 임시로 객체를 보관하는 공간이다.

Eden Space: 새로 생성된 객체가 할당되는 공간
Survivor Space (S0, S1): Eden에서 살아남은 객체가 일시적으로 저장되는 공간
➡️ Young Generation = Eden + Survivor(두 개, S0/S1)

❓ Survivor Space가 필요한 이유

JVM에서는 객체가 생성될 때 Eden 공간에 먼저 할당된다.
하지만 일정 시간이 지나도 살아남은 객체는 가비지 컬렉션(Minor GC)에서 제거되지 않고 계속 필요할 수도 있다.

이때 바로 Old Generation(오래된 객체 영역)으로 이동하면 비효율적이기 때문에, Survivor Space를 거쳐서 일정 횟수 이상 살아남은 객체만 Old Generation으로 이동시킨다.

✅ 기본 옵션 값 (Default Option Values for Survivor Space Sizing)

옵션기본값
-XX:NewRatio2
-XX:NewSize1310 MB
-XX:MaxNewSize제한 없음
-XX:SurvivorRatio8

📌 Young Generation 크기 조정 가이드라인

  1. 최대 힙 크기(-Xmx)를 먼저 결정한 후, Young Generation 크기를 조정

  2. 메모리가 충분하면 Young Generation을 크게 설정

  3. Young Generation을 키우면 Old Generation이 줄어듦 → Old Generation이 감당할 수 있을 만큼만 키울 것

  4. 코어 수가 많을수록 Young Generation을 크게 설정하는 것이 유리

  • 객체 할당이 병렬로 처리될 수 있기 때문

참고문헌
🔗 오라클 공식문서

profile
안정적인 쳇바퀴를 돌리는 삶

0개의 댓글