2007. 1. 4. 13:31
60초 마다 Full GC가 발생한다. Tuning2007. 1. 4. 13:31
현재 수행 중인 프로젝트가 막바지에 다다라 부하 테스트를 하고 있는데 이 넘들이 60초 마다 Full GC가 발생하는 문제를 보였다. 이 글에서는 이러한 문제의 원인 및 해결책에 대해 기록해 보고자 한다.
먼저 이상적인 Full GC 상황은 아래와 같다.
- 1일 5회 미만 발생
- 발생시 3-4초 이하 동안 수행 완료
근데 우리 어플리케이션은 60초 마다 Full GC를 수행하고, GC 수행 속도도 보통 4-5초, 최대 7초 정도가 걸리고 있었다.
먼저 60초 마다 Full GC가 발생한 이유는 웹에서 찾아 보니 아래와 같았다.
. 60초 마다 Full GC가 발생하는 이유
- http://java.sun.com/docs/hotspot/gc1.4.2/index.html#5.%20Other%20Considerations|outline 를 보면 왜 주기적으로 Full GC가 일어났는지 알 수 있다.
- RMI를 이용하고 있거나
- 특정 모듈/라이브러리에서 주기적으로 System.gc()를 호출하고 있는 경우
이외에 지속적으로 Full GC를 유발하는 다른 경우로는 Permanent 영역의 크기가 적어서 코드가 로드/언로드되는 경우가 발생한다면 Full GC를 수행해도 Permanent 영역을 확보할 수 없음에도 불구하고 Full GC가 지속적으로 수행되는 경우가 있다.
jmap -heap pid
위의 명령으로 Full GC가 빈번하게 발생하는 어플리케이션의 힙 상태를 조사해 볼 필요가 있다.
이번 문제에 대한 나의 해결책은 -XX:+DiableExplicitGC이다. 이 옵션을 지정함으로써 System.gc()에 의해 발생하는 explicit한 gc를 없애고, jvm이 수행하는 implicit한 gc만을 허용하여 Full GC로 인한 오버헤드를 없애는 것이다.
추가적으로 Full GC가 있어날 때 다음과 같은 메시지가 있었다.
Unloading class sun.reflect.Generatedxxx
이에 대한 해결칙으로는 아래와 같이 Permanent 영역의 크기/최대 크기를 동일한 값으로 설정하여 해결하고자 하였다.
CATALINA_OPTS="${CATALINA_OPTS} -XX:PermSize=128m "
CATALINA_OPTS="${CATALINA_OPTS} -XX:MaxPermSize=128m "
또 RMI가 60초 마다 GC를 수반하는 것 관계해서 아래의 옵션을 추가하였다.
CATALINA_OPTS="${CATALINA_OPTS} -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 "
아직 결과는 안 나왔지만 잘 될 것이라고 생각한다. 만일 안 좋은 결과가 지속된다면 이 글을 더 보강하도록 하겠다.
먼저 이상적인 Full GC 상황은 아래와 같다.
- 1일 5회 미만 발생
- 발생시 3-4초 이하 동안 수행 완료
근데 우리 어플리케이션은 60초 마다 Full GC를 수행하고, GC 수행 속도도 보통 4-5초, 최대 7초 정도가 걸리고 있었다.
먼저 60초 마다 Full GC가 발생한 이유는 웹에서 찾아 보니 아래와 같았다.
. 60초 마다 Full GC가 발생하는 이유
- http://java.sun.com/docs/hotspot/gc1.4.2/index.html#5.%20Other%20Considerations|outline 를 보면 왜 주기적으로 Full GC가 일어났는지 알 수 있다.
- RMI를 이용하고 있거나
- 특정 모듈/라이브러리에서 주기적으로 System.gc()를 호출하고 있는 경우
이외에 지속적으로 Full GC를 유발하는 다른 경우로는 Permanent 영역의 크기가 적어서 코드가 로드/언로드되는 경우가 발생한다면 Full GC를 수행해도 Permanent 영역을 확보할 수 없음에도 불구하고 Full GC가 지속적으로 수행되는 경우가 있다.
jmap -heap pid
위의 명령으로 Full GC가 빈번하게 발생하는 어플리케이션의 힙 상태를 조사해 볼 필요가 있다.
이번 문제에 대한 나의 해결책은 -XX:+DiableExplicitGC이다. 이 옵션을 지정함으로써 System.gc()에 의해 발생하는 explicit한 gc를 없애고, jvm이 수행하는 implicit한 gc만을 허용하여 Full GC로 인한 오버헤드를 없애는 것이다.
추가적으로 Full GC가 있어날 때 다음과 같은 메시지가 있었다.
Unloading class sun.reflect.Generatedxxx
이에 대한 해결칙으로는 아래와 같이 Permanent 영역의 크기/최대 크기를 동일한 값으로 설정하여 해결하고자 하였다.
CATALINA_OPTS="${CATALINA_OPTS} -XX:PermSize=128m "
CATALINA_OPTS="${CATALINA_OPTS} -XX:MaxPermSize=128m "
또 RMI가 60초 마다 GC를 수반하는 것 관계해서 아래의 옵션을 추가하였다.
CATALINA_OPTS="${CATALINA_OPTS} -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 "
아직 결과는 안 나왔지만 잘 될 것이라고 생각한다. 만일 안 좋은 결과가 지속된다면 이 글을 더 보강하도록 하겠다.