티스토리 뷰

728x90
반응형

 포스팅은 IBM 계열 JDK의 GC Log 분석 가이드입니다.


GCLog는 다양한 플랫폼 JVM의 Working 상태를 분석하고, 메모리 사용패턴을 진단하여 효율적인 Gabage Collector를 수집할 수 있도록 도와주는 역할을 합니다.


GC log

JAVA Memory 관리 구조

Java의 메모리는 기존의 C 언어와는 전혀 다른 구조로 사용되며 관리됩니다.

Java에서의 메모리 관리는 C 언어의 malloc과 같은 메모리 관련 메소드를 통하는 것이 아니라, Java 자체적으로 더 이상 사용하지 않는 메모리를 자동으로 해제해 주는 기능 (GC : Garbage Collection)이 제공됩니다.


GC LOG를 통해 분석이 필요한 경우

[OutOfMem 발생한 경우]

GC Log를 통해 Java 메모리를 분석해야 할 가장 중요한 시점은 OOM이 발생할 경우입니다.

OOM이 발생하는 경우는 말 그대로 Java Heap 메모리가 부족하여 더 이상 가용한 메모리가 경우라 할 수 있습니다이러한 OOM이 발생하는 경우는 두 가지 정도라고 할 수 있는데메모리 leak으로 인한 OOM과 순간적으로 과도한 메모리 할당으로 인해 발생하는 OOM 경우로 볼 수 있습니다

OOM이 발생할 경우 GC Log 분석을 통해 어느 경우에 의해 발생하였는지 확인 할 수 있으나두 경우 모두 실제 문제를 해결하기 위해서는 Heapdump 분석 등의 다른 분석 방법을 적용해야 합니다.

 

[사용자의 요청 처리 시간이 일정하지 않은 경우]

OOM으로 인해 프로세스에 장애가 발생할 수 있으나, GC로 인한 Java 프로세스 멈춤 현상이 발생할 수도 있습니다.

이러한 멈춤 현상은 짧게는 0.001초에서 길게는 수십 초가 걸릴 수도 있습니다.

사용자의 요청 처리가 빠르게 처리되다 간혹 느려지는 현상이 발생한다면여러 가지 원인이 있겠으나 GC로 인한 STW 현상도 의심해 봐야 할 것입니다.


IBM 계열의 메모리

메모리 구조

IBM 계열 java Heap 메모리 구조는 기본적으로 One Heap 구조이며, 1.5버전부터는 Sun 계열과 같이 Generation Heap 구조를 사용할 수 있습니다.

One Heap 구조는 Heapbase라고 하는 Heap메모리의 처음 주소에서 Heaptop 주소까지 확장이 가능하며 가변크기일 경우 현재까지 할당된 부분을 Heaplimit이라고 합니다.

Heapbase ~ Heaptop까지는 –Xmx 옵션으로 설정되는 값이며, Heapbase ~ Heaplimit 까지는 –Xms으로 설정되는 값입니다.


1.4 버전의 One Heap 구조입니다.


1.5 버전의 One Heap 구조입니다.

 

영역에 대한 내용은 다음과 같습니다.

- K Cluster, P Cluster

Pinned Class Object(K Cluster), Pinned Object(P Cluster)가 할당되는 곳으로 Default 1280개의 class entries가 저장 가능하며, Sun 계열 JVM Permanent 영역과 비슷한 역할을 합니다.

K Cluster가 꽉 차면 P Cluster에 할당되며 P Cluster가 꽉 차게 되면 2kbyte의 새로운 P Cluster가 할당 되는데이때 P Cluster 영역이 Heap의 영역에 임의적으로 생성되며 이로 인해 Heap Fragmentation이 발생하기도 합니다.

- Heap

생성된 object들이 저장되는 영역입니다.

- Cache

Cache Allocation을 위한 영역으로 Thread간의 경합을 피하기 위한 THL(Thread Local Heap) 512byte 이하의 작은 object를 할당하는데 사용됩니다여기서 Thread간의 경합이란 실제 이러한 Cache 영역이 없다면 Heap 영역에 대해 object를 할당하기 위해 Heap Lock을 발생시키게 됩니다이렇게 되면 Thread들간에 object를 할당하기 이해 Heap에 대한 Lock 경합이 발생하게 됩니다이러한 경합을 줄이기 위해 Cache를 이용하여 THL을 두어 해당 Thread가 할당할 수 있는 영역을 별도로 지정하는 것입니다.

- Wilderness OR LOA

Large Object의 할당을 효과적으로 하기 위한 공간으로 주로 64kbyte object의 할당에 사용됩니다항상 64kbyte 이상의 object가 할당되는 것이 아니라, Heap Fragmentation등의 이유로 Heap영역에 object 할당이 불가능할 경우 64kbyte보다 작은 일반 object들도 할당되기도 합니다.

 

버전 간 Heap 구조의 차이점은 K Cluster, P Cluster 영역(합쳐서 pinned cluster 영역)이 있느냐 없느냐의 차이입니다.

이렇게 바뀌게 된 이유는 pinned object로 인한 Heap Fragmentation 문제에 있습니다.

 

[pinned object ?]

pinned object란 고정된 object라는 것으로 원칙적으로 Java에서 모든 object들은 Garbage Collector를 통해 object의 이동이 가능하도록 되어 있습니다그러나 일부 특수한 경우는 Garbage Collector가 이동시키지 못하는 object들이 발생합니다예들 들어 JNI(Java Native Interface)에서 사용하는 object들은 JNI에서 직접 unpinned 될때까지 고정이 됩니다또한 class에 대한 메타 정보들도 고정영역으로 지정됩니다.

이러다 보니 실제 pinned object들은 GC에 의해 compaction 작업이 불가능합니다이러한 이유로 pinned cluster라는 영역을 두어 해당 영역에 pinned object들을 저장하게 됩니다

문제는 이러한 pinned cluster 영역 보다 많은 pinned object가 발생하게 되면 pinned object를 저장하기 위해 JVM Heap 영역에 pinned object를 위한 공간을 임의로 지정합니다이러한 공간이 임시 성일 수도 있고 영구적인 공간이 될 수도 있습니다

이런 현상(pinned cluster영역이 부족할 경우)이 발생하게 되면 Heap 영역에 한번에 할당할 수 있는 일련 된 순서의 메모리가 점점 줄어들게 되어 나중에는 별로 크지 않는 object를 할당 하려고 해도 allocation failure(AF)이 발생하게 됩니다.

1.5 버전에서는 이러한 문제점을 해결하기 위해 pinned object의 저장을 Java Heap이 아닌 System Heap에 저장하도록 변경하였습니다. 1.4 버전에서 발생하는 Heap Fragmentation 문제는 K Cluster P Cluster의 크기를 조정을 통해(-Xk, -Xp 옵션 사용해결할 수 있습니다.

 

[Generational Heap 구조]

Generational Heap 구조가 Sun 계열 Java에서는 기본적인 구조이지만 IBM 계열 Java에서는 옵션을 통해 지정할 수 있으며 GC에 대한 Policy 옵션중의 하나입니다.

Generational Heap 구조를 사용하기 위해서는 -Xgcpolicy:gencon 옵션을 사용합니다.


- Allocation Space

새롭게 생성되는 object가 할당되는 영역이며, Sun 계열 JVM Eden 영역이라 할 수 있습니다.

- Survivor Space

Alive object가 저장되는 공간이며, 실제로 Scavenge로 인한 GC 수행 시 live object들이 copy되는 공간입니다. Sun 계열 JVM Survivor 영역이라 할 수 있습니다.

- Tenured Space

Nursery 영역에 저장되어 있었던 object 중에 오래된 object가 이동되어 저장되는 영역입니다.


One-heap 구조 GC 동작 방식

One Heap 구조의 GC Mark -> Sweep -> Compact 단계를 거쳐 GC가 이루어지게 됩니다.

- Mark 단계

모든 live object들에 대한 mark 작업을 수행합니다. 즉 참조계수(Reference count)가 1이상인 object는 mark 되며 나머지는 garbage로 간주됩니다. mark된 live object는 markbit vector에 주소가 저장됩니다.

Parallel Mark 기능을 사용할 수 있으며, 다수개의 Thread가 Mark 단계를 수행하기 위해 기동됩니다. 이렇게 Parallel Mark를 위해서는 -Xgcthreads 옵션으로 설정이 가능합니다.

또한 GC로 인한 STW(Stop The World) 시간을 감소시키기 위해 Concurrent Mark 기능을 사용할 수 있습니다.

-Xgcpolicy:optavgpause 옵션 설정을 통해 사용 가능합니다.

[Mark 단계를 위한 GC Policy 설정을 위한 옵션]

- optthruput

Concurrent mark disable 시킵니다. GC로 인해 멈추는 시간에 문제가 없다면(어플리케이션 수행 응답시간에 영향이 없을때), 이 옵션은 최상의 Throughput을 낼 수 있습니다해당 옵션은 gcpolicy의 기본 값입니다.

- optavgpause

Concurrent mark enable 시킵니다. GC로 인해 어플리케이션의 응답시간에 문제가 있다면응답시간을 줄이기 위해 사용할 수 있습니다그 대신 전체적인 Throughput이 감소할 수 있습니다.

- gencon 

GC로 인한 멈춤 시간을 최소화하기 위해 Concurrent mark Generational Heap을 사용할 수 있습니다.

- subpool

Concurrent mark disable 시킵니다. Heap object를 할당할 때 더 성능을 향상하키기 위해 개선된 object 할당 알고리즘을 사용하는 것입니다이 옵션은 16Core 이상의 SMP 시스템상에서 사용해야 성능을 향상시킬 수 있습니다.

 

옵션을 선택하는 기준은 해당 시스템의 업무 특성에 따라 다릅니다예를 들어 GC로 인해 멈추는 현상이 특정 시간이 넘으면 절대 안 되는 그런 시스템의 경우(공장MES 같이 일정한 응답이 이루어져야 하는 경우) optavgpause를 사용하여 전체적인 Throughput이 떨어지더라도 GC로 인한 응답시간은 보장받을 수 있습니다.

 

- Sweep 단계

Mark 단계에서 live object의 주소 저장소인 markbit vector와 모든 allocation object의 주소 저장소인 allocbit vector와 교차 비교하여 live object외의 garbage object를 삭제하는 작업을 수행합니다.

Parallel Bitwise Sweep 기능을 사용할 수 있으며, Parallel Mark와 같이 다수개의 Thread Sweep단계를 수행하기 위해 기동할 수 있습니다. 이러한 Parallel sweep을 위한 thread수는 -Xgcthreadn 옵션을 설정이 가능합니다.

또한 Mark 단계와 같이 Concurrent sweep을 사용할 수 있으며, GC Policy optavgpause 옵션을 설정하여 사용 가능합니다.

 

- Compaction 단계

Sweep 단계에서 garbage object들이 삭제되고 나면, compaction 단계에서는 heap 상의 삭제된 garbage object들의 공간에 대해 재정렬 작업을 수행합니다. 이러한 compaction 작업을 수행함으로써 연속된 free memory 공간을 확보할 수 있습니다.

compaction 작업은 object들이 heap memory상에서 이동이 발생하며 이 경우 모든 reference의 변경이 발생할 수 있어 수행 시간이 오래 걸립니다.

compaction 작업은 -Xnocompactgc 이 설정되어 있지 않고 다음과 같은 상황일 경우 발생할 수 있습니다.

- "-Xcompactgc"가 설정된 경우

- Sweep 단계 이후 object 할당을 위한 가용한 free space가 충분하지 않을 경우

- System.gc() -Xcompactexplicitgc가 설정되어 있을 때 발생할 경우

적어도 이전에 가용한 메모리의 절반이 THL allocation에 사용되었고평균 THL 크기가 1024byte 아래로 떨어질 경우

가용한 heap이 5% 이하일 경우

가용한 heap 128kb 이하일 경우


Generational 구조 GC 동작 방식

-Xgcpolicy:gencon으로 설정 가능한  Generational Heap 구조는 Sun 계열의 GC 방식과 유사하게 동작합니다.


scavenge 단계에서 Nursery 영역의 Allocate space Survivor space를 이용하여 GC를 수행합니다.

그 방식은 allocate space가 가득 찰 경우 GC가 발생되며, allocate space garbage는 삭제되며, live object Survivor space로 복사됩니다이러한 단계를 여러 번 거치면서 live object Tenured space로 옮겨지게 됩니다.


GC Tuning은 성능에 지대한 영향을 주는 요소 중 하나입니다. 다양한 Policy를 적용해 보고 이를 적재적소에 반영하는 것은 경험과 환경 그리고 Application을 분석할 수 있는 능력에서 나온다고 볼 수 있습니다.

728x90
반응형