본문 바로가기
JAVA & JVM

Garbage Collection Algorithm(가비지 컬렉션 알고리즘)

by 샤워하다돌면워싱턴 2022. 8. 30.
반응형
(Sun) GC 
우리가 GC를 Application에 맞도록 최적화 한다는 것은 결국 GC가 어떠한 방식으로 동작하고 어떤 성격을 지니고 있는지를 이해하는 것이 가장 중요하다.
Serial Collection은 가장 기본적인 GC이며 Default이다. 하지만 메모리의 용량이 점점 커지게 되면서, Heap의 크기도 자연스레 점점 크게 설정할 수 있게 되었다. 그러면서 Serial Collector의 한계가 나타나면서 GC를 수행하던 중 멈춤현상이 나타났다. - heap이 커짐에 따라-recycle

우리가 GC를 Application에 맞도록그래서 나온것이 모든 리소스를 투입하여 gc를 빨리 끝내자는 parallel gc이다.

Serial GC (-XX:+UseSerialGC)

mark-sweep-compact이라는 알고리즘을 사용한다. serial GC는 적은 메모리와 CPU 코어 개수가 적을 때 적합한 방식이다.
  1. Old 영역에 살아 있는 객체를 식별(Mark)하는 것이다. 
  2. 힙(heap)의 앞 부분부터 확인하여 살아 있는 것만 남긴다(Sweep). 
  3. 각 객체들이 연속되게 쌓이도록 힙의 가장 앞 부분부터 채워서 객체가 존재하는 부분과 객체가 없는 부분으로 나눈다(Compaction). 
 
it환경이 발전되면서 메모리 용량이 늘어날수 있게 되는 기술이 발전되었고, heap의 처리량이 늘어나면서 당연하게 크기가 커지게 되었고 gc를 하는 동안 suspend가 더 오랫동안 발생하는 현상이 두들어졌다. 또한 실시간에 가까운 성능을 요구하고 있었다.

Parallel GC (-XX:+UseParallelGC)

Serial GC는 GC를 처리하는 스레드가 하나인 것에 비해, Parallel GC는 GC를 처리하는 쓰레드가 여러 개이다. 
그렇기 때문에 Serial GC보다 빠른게 객체를 처리할 수 있다. 
Parallel GC는 메모리가 충분하고 코어의 개수가 많을 때 유리하다. Parallel GC는 Throughput GC라고도 부른다.
메모리의 특성상 같은 메모리 공간을 두 thread 혹은 process가 접근하게 되면 corruption(손실)이 발생할 수 있다.
메모리 손실 측면에서 손실을 피하기 위해선 동기화 작업이 있어야 하는데 이경우 promotion의 성능이 떨어지게 된다.
이를 위해 PLAB(parallel local allocation buffer)이라는 promotion buffer를 마련.
각 thread마다 메모리(old 영역)의 일부분을 할당 해놓고 (1024bytes)다쓰면 다시 buffer를 재할당 받음.
그러나 이로 인해 old영역에 fragmentation 문제가 발생 가능함.
buffer를 할당받고 안쓰거나, 사용하면서 남는 부분이 생기는 공간이 heap의 단편화 원인이 될 수도 있다.
이 경우 gc thread를 감소시키거나 old영역의 사이즈를 늘리는 방법으로 해결할 수 있다.
 
-XX:+UseParallelGC
:  이 gc를 선택하는 옵션
-XX:ParallelGCThreads=<value>
: gc를 수행할 collector thread 개수를 설정. default는 cpu의 개수와 동일
-XX:+AlwaysTenure
: eden영역의 reachabl object를 바로 old영역으로 promotion
-XX:+NeverTenure
: survivor area가 full인 경우를 제외하고 promotion이 되지않게함.
-XX:+UseAdaptiveSizePolicy
: gc의 횟수, 각 영역의 비율, free heap size등의 정보를 바탕으로 young과 old 영역의 크기를 자동으로 설정.
 
////young영역과 old영역 확장 비율 설정 가능////
-XX:GCHeapFreeLimit=<value>
:Garbage Collection으로 확보해야 하는 최소 Free Space를 설정. 최대 heap사이즈에 대한 비율이며 default는 5%
:-XX:+UseParallelGC 옵션과 함께 사용할 경우 gc도중 발생 가능한 oom을 방지하는데 도움
-XX:GCTimeLimit=<value>
:gc에 사용할 수 있는 시간의 상한선을 설정. 전체 수행 시간에 대한 비율로 default는 90%
:-XX:+UseParallelGC 옵션과 함께 사용할 경우 gc도중 발생 가능한 oom을 방지하는데 도움
 
 

CMS GC (-XX:+UseConcMarkSweepGC)

minor gc : parallel copy 알고리즘
full gc : concurent mark-sweep 알고리즘
Initial Mark 단계에서는 클래스 로더에서 가장 가까운 객체 중 살아 있는 객체만 찾는 것으로 끝낸다. 
single thread만이 사용되는 serial phase이다. application에서 직접 참조되는 살아 있는 객체만 빠르게 구별해낸다.
직접 참조의 의미는 root set에서 한 단계의 reference관계가 있다는 것을 의미.
initial mark phase는 serial phase이며 heap은 일지정지된다. 하지만 root set에서 직접 참조되는 객체만을 대상하기 때문에 시간은 최소화됨
Concurrent Mark 단계에서는 살아있다고 확인한 객체에서 참조하고 있는 객체들을 따라가면서 확인한다. (싱글 스레드가 수행하는 serial단계)
  • 이 단계의 특징은 다른 스레드가 실행 중인 상태에서 동시에 gc스레드들도 수행된다는 것이다.
Remark 단계에서는 Concurrent Mark 단계에서새로 추가되거나 참조가 끊긴 객체를 확인한다. 
Parallel처럼 모든 thread들이 gc에 동원된다. 그렇기에 stop-the-world가 발생
remark는 이 전의 단계에서 작업된 변경사항을 반영하기 위한 작업. 
각 스레드들이 이미 marking된 object를 다시 추적하여 생존여부를 확정지음
initial mark보다 작업량이 많기 때문에 모든 스레드를 투입하여 수행시간을 단축하는데 목표
마지막으로 Concurrent Sweep 단계에서는 쓰레기를 정리하는 작업을 실행한다. 
  • 이 작업도 다른 스레드가 실행되고 있는 상황에서 진행한다.
이 역시 동시 작업 가능
최종적으로 생존이 확정된 객체를 제외한 죽은 객체를 지움. 하지만 compaction작업은 하지 않는다.
이것은 최대한 application의 수행을 보장하고 이를 통해 gc의 충격을 완화한다는 장점
 
이런 단계로 진행되는 GC 방식이기 때문에 stop-the-world 시간이 매우 짧다. 
모든 애플리케이션의 응답 속도가 매우 중요할 때 CMS GC를 사용하며, Low Latency GC라고도 부른다.
그런데 CMS GC는 stop-the-world 시간이 짧다는 장점에 반해 다음과 같은 단점이 존재한다.
 
  • 다른 GC 방식보다 메모리와 CPU를 더 많이 사용한다.
  • Compaction 단계가 기본적으로 제공되지 않는다.
  • 반복된 seep는 연속된 free space가 감소되는 부작용으로 단편화현상 유발가능.
조각난 메모리가 많아 Compaction 작업을 실행하면 다른 GC 방식의 stop-the-world 시간보다 stop-the-world 시간이 더 길기 때문에 Compaction 작업이 얼마나 자주, 오랫동안 수행되는지 확인해야 한다.
 
이를 위해 freelist를 사용하여 promotion된 객체의 크기를 계속해서 통계화 하여 best fit을 찾아 freelist를 탐색하는 과정에 추가되기 때문에 시간이 걸림(promotion이 빈번하지 않을 경우 이득)
 

G1 GC (-XX:+UseG1GC)

JDK1.6에서 처음 출시되었으며, cms에 비해 정지시간이 개선된 방식이다.
old영역의 단편화나 freelist의 사용으로 인한 문제점, suspendtime이 길어지는 현상등으로
결국 compaction으로 회귀할 수 밖에 없는 상황이 되었다.
물리적인 영역의 구분을 없애고 1Mbytes씩 Region으로 구분하며, GC를 Region단위(각 스레드)로 한다.
전체 heap의 5%는 각 Region의 참조정보를 저장하는 공간이다.
이는 마킹작업 시 trace의 일량을 줄여주어 gc의 효율을 높여주며,
minor gc는 근처 비어있는 Region로 copy되는 방식이며 곧바로 old oc가 일어난다.
반응형

'JAVA & JVM' 카테고리의 다른 글

JAVA Memory Option  (0) 2022.08.30
ParallelGCThreads, ParallelCMSThreads 계산법  (0) 2022.08.30
JAVA란?  (0) 2022.08.30
JAVA의 4가지 기술  (0) 2022.08.30
JVM(Java Virtual Machine)의 정의와 특징, 구조  (0) 2022.08.30

댓글