Garbage Collection
GC (Garbage Collection) 이란?
힙 메모리를 살펴보고 사용 중인 개체와 사용하지 않은 객체를 식별하고 사용하지 않는 객체를 삭제하는 프로세스이다.
Java에서 메모리 할당 해제 프로세스는 GC (가비지 컬렉션)에 의해 자동으로 처리된다.
기본 동작 방식
Step 1: Marking (마킹)
사용 중인 메모리 조각과 사용하지 않는 메모리 조각을 식별하는 단계
Step 2: Normal Deletion (일반 삭제)
일반 삭제는 참조되지 않은 개체를 제거하여 참조된 개체와 포인터를 여유 공간으로 남김
Step 2a: Deletion with Compacting (삭제 및 압축)
성능을 더욱 향상시키기 위해 참조되지 않은 개체를 삭제하는 것 외에도 참조된 나머지 개체를 압축할 수도 있다. 참조된 개체를 함께 이동하면 새 메모리 할당이 훨씬 쉽고 빨라진다.
JVM 사용 이유
JVM의 모든 개체를 표시하고 압축하는 것은 비효율적이다. 더 많은 개체가 할당됨에 따라 개체 목록이 늘어나고 가비지 수집 시간이 점점 더 길어지기 때문이다. 응용 프로그램에 대한 경험적 분석에 따르면 대부분의 개체는 수명이 짧기 때문이다.
JVM 구조
영역 | 설명 |
New/Young 영역 | 모든 새로운 객체가 할당되고 에이징 되는 공간이다. New영역이 가득차면 GC가 발생하여 Old영역으로 이동한다. |
Old 영역 | New/Young 영역에서 옮겨진 오래된 객체를 저장하는 공간이다. |
Perm 영역 | Class, Method 등의 코드와 JVM이 필요로 하는 메타 데이터를 저장하는 공간이다. |
GC 동작방식
1. Object Allocation
Eden 영역에 새 객체가 할당된다. survivor 영역의 S0, S1 영역은 모두 비어있다.
2. Filling the Eden Space
Eden 공간이 가득차면 Garbage Collection이 실행된다.
3. Copying Referenced Objects
참조된 객체는 S0영역으로 이동됩니다. 참조되지 않은 객체는 Eden 영역이 지워지면 삭제된다.
4. Object Aging
Minor GC에서 동일한 일이 Eden 영역에 대한 GC가 발생한다. 참조되지 않은 객체는 삭제되고 참조된 객체는 생존 공간으로 이동한다. 단, 이 경우 2차 생존공간(S1)으로 이동한다. 또한 첫 번째 생존 공간(S0)에 있는 마지막 마이너 GC의 객체는 S1으로 이동합니다. 살아남은 모든 객체가 S1으로 이동되면 S0과 Eden 영역이 모두 지워진다.
5. Additional Aging
Minor GC에서 동일한 프로세스가 반복된다. 이번에는 생존자 영역이 바뀐다.
참조된 개체는 S0으로 이동된다.
6. Promotion
Minor GC 후 오래된 객체가 특정 연령 임계값(ex) 8)에 도달하면 해당 개체는 Young 영역에서 Old 영역으로 이동된다.
7. Promotion
Minor GC가 계속 발생함에 따라 객체는 계속해서 Old 영역으로 이동된다.
8. GC Process Summary
결국 주요 GC는 해당 공간을 정리하고 압축하는 Old 영역에서 수행된다.
GC 종류
The Serial GC (직렬 GC - 기본)
설명
직렬 수집기는 Java SE 5 및 6에서 클라이언트 스타일 시스템의 기본값이다. 직렬 GC를 사용하면 주요 GC 동작이 모두 직렬로 수행된다.(단일 가상 CPU 사용). 또한 mark-compact 수집 방식을 사용한다. 이 방법은 이전 메모리를 힙의 시작 부분으로 이동하여 새 메모리 할당이 힙 끝에서 단일 연속 메모리 청크로 만들어진다. 이렇게 메모리를 압축하면 새 메모리 청크를 힙에 더 빠르게 할당할 수 있다.
사용사례
일시 중지 시간 요구 사항이 낮지 않고 클라이언트 스타일 시스템에서 실행되는 대부분의 응용 프로그램에서 선택하는 GC이다.
사용방법 (-XX:+UseSerialGC)
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar
The Parallel GC (병렬 GC)
설명
여러 스레드를 사용하여 젊은 세대 GC를 수행한다. 기본적으로 N개의 CPU가 있는 호스트에서 N개의 GC 스레드를 사용한다.
사용사례
여러 CPU를 사용하여 애플리케이션 처리 속도를 높일 수 있다. 많은 작업을 수행해야 하고 긴 일시 중지가 허용되는 경우에 사용한다. 예를 들어 보고서 또는 청구서 인쇄 또는 많은 수의 데이터베이스 쿼리 수행과 같은 일괄 처리.
사용방법 (-XX:+UseParallelGC)
Old 영역의 단일 스레드 압축을 수행합니다.
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseParallelGC -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar
사용방법 (-XX:+UseParallelOldGC)
Old 영역의 단일 스레드 압축을 수행하지 않는다.
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseParallelOldGC -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar
The Concurrent Mark Sweep (CMS) Collector
설명
Concurrent Mark Sweep(CMS) 수집기(동시 낮은 일시 중지 수집기라고도 함)라고 한다. GC로 인한 일시 중지를 최소화하려고 사용한다.
사용사례
CMS 수집기는 일시 중지 시간이 짧고 GC와 리소스를 공유할 수 있는 응용 프로그램에 사용해야 한다. 예를 들면 이벤트에 응답하는 데스크탑 UI 애플리케이션, 요청에 응답하는 웹 서버 또는 쿼리에 응답하는 데이터베이스가 있다.
사용방법 (-XX:+UseConcMarkSweepGC)
- CMS 수집기를 활성화 옵션 : -XX:+UseConcMarkSweepGC
- 스레드 수를 설정 : -XX:ParallelCMSThreads=<n>
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseConcMarkSweepGC -XX:ParallelCMSThreads=2 -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar
GC 파라미터
전체 힙 크기 조정 옵션
전체 힙 크기는 최소(-ms) 최대(-mx)로 힙 사이즈의 영역을 조정할 수 있다.
예) -ms 512m -mx 1024m
Perm 크기 조정 옵션
자바 클래스, 메소드 등이 로딩되는 영역이다. 일반적인 애플리케이션에서는 64 ~ 256m 사이가 적절하다.
예) -XX:MaxPermSize=128m
New 영역과 Old 영역의 조정
NewRatio Old/New Size 비율 값이다.
전체 힙의 크기가 768m 일 경우 NewRatio=2이면 New가 256M, Old 영역이 512M가 설정된다.
-XX:NewSize=128m 옵션을 이용해서 직접 New 영역의 크기를 지정하는 것도 가능하다.
예) -XX:NewRatio=2 또는 -XX:NewSize=128m
-server와 -client 옵션
내부에서 돌아가는 Hotspot Compiler 에 대한 최적화 방법과 메모리 구조가 다르다.
-server 옵션은 애플리케이션 서버와 같은 서버에 최적화된 옵션이고 -client 옵션은 워드프로세스와 같은 클라이언트 애플리케이션에 최적화 된 옵션이다.
'백엔드 > 성능 최적화' 카테고리의 다른 글
FastAPI 동기/비동기 동작 방식 분해해보기 (0) | 2024.04.05 |
---|---|
메모리 할당 기법 ptmalloc2 vs tcmalloc vs hoard vs jemalloc 비교 (0) | 2023.07.26 |
JVM 성능을 최적화 방법 (0) | 2022.04.08 |
K6 성능 테스트 툴 (0) | 2022.03.31 |
인프라 관점의 성능 최적화 (0) | 2022.03.30 |