-
GC(Garbage Collection)가 자주 발생하면 왜 안좋을까?Develop/Java 2022. 8. 10. 15:30
1. GC란?
- Garbage Collection의 약자
- Java Runtime시 Heap 영역에 저장되는 객체 중에서 더 이상 사용하지 않는 객체를 청소하여 공간을 확보하는 작업
- 공간을 정리 하지 않으면 OOM(OutOfMemmory)이 발생하기 때문
- Garbage Collector(가비지 콜렉터)가 메모리 해제를 수행한다.
1-1. GC 동작 원리
1. 메모리 할당
2. 사용 중인 메모리 인식
3. 사용하지 않는 메모리인식
JVM Heap 구조 - Eden 부터 Survivor 영역까지를 Young 영역이라고 부른다.
- JDK 8 부터는 Young, Old, Permanent 구분이 사라졌다.
1-2. GC가 처리되는 과정
1) 객체가 생성되어 Eden 영역에 올라간다.
2) Eden 영역이 꽉 차면 Survior영역으로 넘어간다. 단 Survior 영역중 하나는 반드시 비어있어야 한다.
- 객체의 크기가 Survior영역의 크기보다 큰 경우 Old 영역으로 이동한다.
3) 이 과정에서 오랫동안 살아남은 객체는 Old 영역으로 이동한다.
- Old 영역에 들어간 객체는 풀 GC, 메이저GC가 발생하지 않는한 GC되지 않는다.
2. GC의 종류
메이저 GC : Old, Perm 영역에서 발생
마이너GC : Young 영역에서 발생
풀 GC : 메모리 전체를 대상으로 발생TLABs (Thread-Local Allocation Buffers : 스레드 로컬 할당 버퍼)
- GC가 발생하거나 객체가 각 영역에서 다른 영역으로 이동할 때 애플리케이션의 병목이 발생하면서 성능에 영향을 준다.
- 그래서 핫 스팟(Hot Spot) JVM에서는 스레드 로컬 할당 버퍼라는 것을 사용한다.
- 이를 통해 스레드별 메모리 버퍼를 사용하면 다른 스레드에 영향을 주지 않는 메모리 할당 작업이 가능해진다.
3. GC 방식
- JDK 5.0 이상에서 지원하는 GC에는 5가지 방식이 존재
1. Serial Collector
2. Parallel Collector (Throughput Collector)
3. CMS Collector (Concurrent Mark-Sweep Collector)
4. G1 Collector (Garbage First Collector)
5. Z Garbage CollectorSTW(Stop The World)
- STW는 Stop The World의 약자로 자바 어플리케이션은 GC를 실행하기 위한 Thread를 제외하고 이외의 모든 Thread는 멈추고 GC가 완료된 이후에나 다시 Thread가 실행 상태로 돌아가게 하는데 이 멈춤 현상
3-1. Serial Collector

- 하나의 CPU로 Young영역과 Old영역을 연속적(serial)으로 처리한다.
- GC를 처리하는 스레드 한개
- 컬렉션이 수행될 때 애플리케이션이 정지된다.(운영 서버에서 절대 사용하면 안되는 방식)
- MinorGC 뿐 아니라 Major GC인 경우도 올스탑(stop-the-world)
- 메모리가 적고, CPU 코어 개수가 적을 때 적합한 GC 방식
- Old 영역의 GC는 mark-sweep-compact 알고리즘을 사용
- 명시적지정: -XX:+UseSerialGC
GC 진행 흐름
1. 살아있는 객체는 Eden영역에 올라간다.
2. Eden영역이 꽉차면 To Servivor영역으로 '살아있는 객체'를 이동시킨다.
3. To Servivor영역이 꽉 찰경우 Eden, FromServivor영역에 남은 객체를 Old영역으로 이동시킨다.
Mark-sweep-compact 알고리즘
1) Old 영역으로 이동된 객체들 중 살아 있는 개체를 식별합니다. (Mark)
2) Old 영역의 객체들을 훑는 작업을 수행하여 쓰레기 객체를 식별합니다. (Sweep)
3) 필요 없는 객체들을 지우고 살아 있는 객체들을 한 곳으로 모은다 (Compact)3-2. Parallel Collector

- Serial GC와 기본적인 알고리즘은 같으나, Parallel GC는 GC를 처리하는 쓰레드가 여러 개
- 메모리가 충분하고 코어의 개수가 많을 때 적합한 GC 방식
- MinorGC 뿐 아니라 Major GC인 경우도 올스탑(stop-the-world)
- Old 영역의 GC는 mark-sweep-compact 알고리즘을 사용
- 명시적지정: -XX:+UseParallelGC
3-3. CMS Collector

- 2개 이상의 CPU를 사용하는 서버에 적합한 GC 방식이다.
- 장점
- stop-the-world 시간이 짧다
- 단점
- 다른 GC 방식보다 CPU 리소스를 많이 사용
- Compaction 단계가 기본적으로 제공되지 않는다.
- 메모리 파편화로 인해, Compaction 수행 시 다른 GC 방식보다 stop-the-world 시간이 더 길어진다.
- 장점
1) Initial Mark 단계 : class loader에서 가장 가까운 객체 중 살아 있는 객체만 찾는다.(mark)
2) Concurrent Mark 단계 : 올스탑(stop-the-world)없이 살아있다고 확인한 객체에서 참조하고 있는 객체를 확인한다.
3) Remark 단계 : Concurrent Mark 단계에서 새로 추가되거나 참조가 끊긴 객체를 확인한다.
4) Concurrent Sweep 단계 : 올스탑(stop-the-world)없이 참조 되지 않는 객체를 정리한다.3-4. G1 Collector

- 바둑판의 각 region(영역)에 객체를 할당하고 GC를 실행한다. 해당 영역이 꽉 차면 다른 영역에서 객체를 할당하고 GC를 실행한다.
- CMS Collector의 CPU리소스 및 메모리 파편화의 단점을 해결하기 위해 만들어진 방식이다.
- 가장 많은 공간이 있는 곳 부터 메모리 회수 진행하기 때문에 Garbage First 라는 이름이 붙었다
- G1 Collector의 가장 큰 장점은 어떤 GC 방식보다도 빠르다는 점이다.
- Young의 세가지 영역 (Eden 영역, 2개의 Survivor 영역)에서 데이터가 Old 영역으로 이동하는 단계가 사라진 GC 방식이다.
- JDK 6에서는 early access라고 부르며 시험삼아 사용할 수 있고, JDK 7에서 정식으로 사용 가능한 방식이다.
- CMS Collector의 CPU리소스 및 메모리 파편화의 단점을 해결하기 위해 만들어진 방식이다.
3-5. Z Garbage Collector

- GC 일시 정지 시간이 10ms 미만의 애플리케이션을 위한 GC
- 테라 바이트(tb) 큐모의 매우 큰 heap을 사용하는 애플리케이션을 위한 GC
- 객체를 가리키는 변수의 포인터에서 64bit 을 활용하기 때문에 64bit 운영체제에서만 사용가능
- JDK 11 부터 실험적으로 도입 되었으며 region으로 간단한 힙 메모리 구조가 G1과 유사하다.
4. GC 발생으로 인한 애플리케이션 성능 비교
- for문 안에서 gc를 수행 하여 애플리케이션 성능 분석
StopWatch stopWatch = new StopWatch(); stopWatch.start(); for (int i = 0; i < 10; i++) { String str = "abcdefghijklmnopqrstuvwxyz"; for (int j = 0; j < 10; j++) { str += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; } System.gc(); } stopWatch.stop(); System.out.println(stopWatch.getTotalTimeMillis());구분 응답 시간 GC를 수행 한 경우 30 ~ 50 ms GC를 수행 하지 않는 경우 0.08 ~ 0.16 ms 결론
- GC가 자주 수행 되는 경우 STW로 인하여 애플리케이션의 성능이 저하된다는 것을 알 수 있다.
출처