2010-04-30 3 views
6

Linux 64 비트에서 8 코어 CPU와 6GB 메모리를 사용하는 애플리케이션 서버를 실행하고 있습니다.반응이 빠른 서버 애플리케이션을위한 튜닝 JVM (GC)

서버의 응답 성이 높아야합니다.

일부 검사를 한 후 서버에서 실행되는 응용 프로그램의 수명이 짧은 개체가 많아지고 메모리 누수가없는 한 수명이 약 200 ~ 400MB의 개체 만 있음을 알게되었습니다.

http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html 을 읽은 후 나는이 JVM 옵션

-server -Xms2g -Xmx2g -XX:MaxPermSize=256m -XX:NewRatio=1 -XX:+UseConcMarkSweepGC 

결과를 사용 마이너 GC는 주요 GC는 마이너 GC가 지속적으로 발생하는 1 ~ 3 초 소요, 0.01 ~ 0.02 초 걸립니다.

어떻게하면 JVM을 더 향상 시키거나 조정할 수 있습니까?

큰 힙 크기? GC에 더 많은 시간이 걸릴 것인가?

큰 NewSize 및 MaxNewSize (젊은 세대 용)?

다른 수집가? 병렬 GC?

주요 GC가 더 자주 발생하도록하는 것이 좋습니다. 그리고 어떻게?

답변

7

결과에서 볼 수 있듯이, 년 전에 약간 버그가 있었던 것으로 보인다했습니다 마이너 GC가 0.01 ~ 0.02 초 소요, 주요 GC는 작은 1 ~ 3 초 소요 GC는 끊임없이 발생합니다.

일시 중지를보고하지 않는 한, CMS 수집기가 요청한 작업을 수행하고 있다고 가정합니다. 정의에 따르면 CMS는 직렬 및 병렬 수집기보다 더 많은 CPU 백분율을 사용합니다. 낮은 일시 중지 시간에 대해 지불하는 벌금입니다.

1 초에서 3 초 사이에 일시 중지 번이 표시되면 튜닝을해야한다고 말하고 싶습니다. 저는 전문가가 아니지만 CMSInitiatingOccupancyFraction의 값을 기본값 92에서 줄이는 것으로 시작해야합니다.

힙 크기를 늘리면 GC의 "처리량"이 향상됩니다. 그러나 문제가 오래 지속되면 힙 크기를 늘리면 문제가 더욱 악화 될 수 있습니다.

2

동시에 마크 스윕 대신 낮은 일시 중지 Garbage-First collector을 시도해 볼 수 있습니다 (모든 컬렉션에서 성능이 더 좋아지는 것은 아니지만 최악의 경우가 더 좋음). 그것은 -XX:+UseG1GC에 의해 가능하고 정말 awesomesauce로되어 있지만 프로덕션 환경에서 사용하기 전에 철저한 평가를 원할 수 있습니다. 그것은 아마도 이후 개선하지만 Experience with JDK 1.6.x G1 (“Garbage First”)

+0

나는 Azul Zing jvm이 많은 경우에 "더 좋다"고 지적했다. 앱이 실행되는 동안 그들은 gC를하고 있습니다. 꽤 멋진 재료. 다시 말하지만, 무료는 아니지만, JVM을 조정할 필요성을 없애고 자하는 사람들은이 작업을 수행 할 수 있습니다. 나는 그들이 C4 수집 (동시, 연속, 압축, 컬렉터)이라고 부른다고 생각한다. 최근 Mike McCandless의 벤치 마크에서는 CMS에 대한 Apache Lucene/Solr에서이를 테스트했습니다. 확장 성에서 큰 결과 : http://blog.mikemccandless.com/2012/07/lucene-index-in-ram-with-azuls-zing-jvm.html 내가 게임을 바꿀 때 이것을 따라왔다. –

1

많은 CPU가있는 경우 가비지 수집이 프로그램과 병렬로 실행되는 것이 완벽합니다.

원하는 것은 가비지 수집이 주 프로그램을 일시 중지하는 시나리오에 빠지지 않도록 확실히하는 것입니다.

서버 VM (Sun JVM 용)을 원한다는 것을 제외하고 단순히 플래그를 지정하지 않은 채로 시도한 다음 서버가 과부하로 작동하는 모습을 보았습니까?옵션으로 팅커 링하면 어떤 개선점이 생기면 그때 만 볼 수 있습니다.

1

이것은 실제로 처리량 응용 프로그램과 같으며 처리량 수집기를 사용해야합니다. 나는 새로운 세대의 크기를 균형있게 조정하여 GC를 너무 자주 만들지 않고 오래도록 멈추지 않도록 충분히 작게 만듭니다. 20ms는 나에게 길게 사소한 GC처럼 들린다. 나는 또한 당신의 생존자 공간이 너무 커서 단지 낭비되고 있다고 생각합니다. 오래된 세대에서 생존력이별로 없다면, 사소한 GC에서 그다지 생존 할 수 없습니다.

결국 jvmstat와 VisualGC를 사용하여 앱에서 메모리를 사용하는 방식에 대한 느낌을 실제로 얻어야합니다.

2

조심하십시오 .... 신중하지 않으면 GC가 털이 많은 수 있습니다. 모든 런타임 (Java 용 JVM/.Net 용 CLR)에는 몇 가지 프로세스가 있습니다. 일반적으로 메모리의 초기 단계 최적화가 있습니다 (Young Generational Garbage Collection/Young Gen GC & Old Generational Garbage Collection/Old Gen GC). 젊은 세대는 정기적으로 발생하며 일반적으로 작은 일시 중지/딸꾹질에 기인합니다. 오래된 genc는 일반적으로 긴 "세계 정지"가 멈추는 것을 볼 때 진행되고있는 일입니다.

왜 물어볼 수 있습니까? 런타임/JVM에서 일시 중지되는 이유는 런타임이 힙을 정리할 때 위상 변경이라고 불리는 것을 거쳐야한다는 것입니다. 포인터를 표시하고 스왑하여 사용 가능한 메모리를 최적화하기 위해 응용 프로그램을 실행하는 스레드를 중지합니다. 용인은 주로 일시적인 물건 만 풀어주기 때문에 빠릅니다. 그러나 늙은 세대는 힙에있는 모든 객체를 평가하고 메모리가 부족하면 많은 메모리를 필요로합니다.

왜주의해야할까요? Old gen은 일시 중지 시간에 더 많은 힙을 사용할 때 기하 급수적으로 나 빠지게됩니다. 총 힙 크기가 2-4GB 인 Java 6 (JDK 1.6+)와 같은 최신 런타임에서는 괜찮습니다. 일단 threashold를 초과하면 일시 중지 시간이 기하 급수적으로 증가합니다. 서버를 다시 시작해야하는 일부 클라이언트가 실행되었습니다. 드문 경우이지만 힙이 큰 GC 일시 중지 시간은 전체 다시 시작보다 오래 걸릴 수 있습니다.

거기에 몇 가지 새로운 도구가 꽤 멋지며 GC가 당신의 고통인지 평가하는 데 최첨단을 제공 할 수 있습니다. JHiccup은 하나이며 azulsystems 웹 사이트에서 무료입니다. 현재로서는 리눅스 용이라고 생각합니다. 또한 JVM에는 재구성 된 GC 알고리즘이있어 일시 중지가 발생하지 않지만 비 핵심 응용 프로그램을 사용하는 단일 서버 배포에서는 비용 효과적이지 않을 수 있습니다 (무료는 아닙니다).

요약하면 런타임/JVM/CLR 힙이 2GB 미만이면 더 많은 메모리를 추가하면 도움이됩니다. 약간의 간접비를 주어야합니다. 가능한 경우 힙 크기/메모리 크기를 100 %로 맞추고 싶지는 않습니다. 그것은 긴 멈춤이 가장 길 때입니다. 자신이 필요하다고 생각하는 것 이상으로 20 % 이상의 추가 메모리를 확보하십시오. 그렇게하면 GC 알고리즘이 최적화를 위해 객체를 움직일 여지가 있습니다. 혹시 커질 계획이라면 1990 년경 JVM 기술 (Azul Systems Zing JVM)을 수정하는 도구가 있지만 무료는 아닙니다. 그들은 GC 문제를 진단하기위한 오픈 소스 도구를 제공합니다. JVM은 (내가 해보았을 때) 오버 헤드없이 누출, 버그 또는 로크 (JVM이 이미 다루고있는 데이터를 언젠가 처리하고 타임 스탬핑)를 사용하지 않고보고 할 수있는 실용적인 스레드 레벨 가시성 도구를 가지고있다. 그로 인해 dev 테스트 시간이 많이 절약되었지만 작은 응용 프로그램에는 적합하지 않습니다.

4GB 이하로 유지하십시오. 여분의 헤드 룸을 제공하십시오. 자바/JVM의 GC를 모니터링 할이 플래그를 켤 수 있습니다 원한다면 :

java -verbose:gc myProgram 
java -Xloggc:D:/log/myLogFile.log -XX:+PrintGCDetails myProgram 

당신은 핫스팟이 사용하는 다른 수집가의 일부를 시도 할 수 있습니다. 하나 이상이 있습니다.

Linux를 사용하는 경우 JHiccup 도구를 사용해보십시오. 공짜 야.

1

응답이 빠른 서버 응용 프로그램의 경우 주요 GC가 자주 발생하지 않는지 확인하고 싶습니다. 매개 변수 목록이 도움이 될 것입니다.

-XX : + CMSParallelRemarkEnabled
-XX : + CMSScavengeBeforeRemark
-XX : + UseCMSInitiatingOccupancyOnly
-XX : CMSInitiatingOccupancyFraction =
-XX 50 : CMSWaitDuration = 300,000 -XX
: GCTimeRatio = 40

힙 크기가 클수록 앱의 메모리가 부족하지 않으면 잠시 멈추어도 도움이되지 않을 수 있습니다.

큰 NewSize 및 MaxNewSize는 처리량에 도움이되며, 잠시 멈추는 데 도움이되지 않을 수 있습니다. 이 방법을 선택하면 -XX : GCTimeRatio를 낮게 설정하여 GC 스레드에 더 많은 실행 시간을 부여 할 수 있습니다. 요점은 JVM을 조정할 때 전체 론적 인 것을 기억하는 것입니다.

0

필자는 이전 포스터가 뭔가 명확하지 않았다고 생각합니다. Perm Generation 크기가 너무 낮습니다. 시스템에서 영구 생성으로 200-400 MB를 사용하는 경우 Max Perm Gen을 400 MB로 설정하는 것이 가장 좋습니다. PerGen 크기도 같은 값으로 설정해야합니다. 그러면 영구 생성 공간을 다 써 버릴 수 없습니다.

현재 JVM이 영구 생성 세대 안팎으로 객체를 이동하는 데 많은 시간을 소비해야하는 것처럼 보입니다. 시간이 걸릴 수 있습니다. JVM은 인접한 메모리 영역을 Java 객체에 할당하려고 시도합니다. 이렇게하면 하드웨어 수준 기능으로 인해 메모리 액세스 속도가 빨라집니다. 그렇게하기 위해 메모리에 많은 버퍼를 갖는 것이 매우 유용합니다. 영구 생성이 거의 가득 차면 새로 발견 된 영구 개체를 분할하거나 기존 개체를 섞어 야합니다. 이것이 전체 GC를 트리거하는 것은 물론 전체 GC 일시 중지를 초래합니다.

영원한 세대 크기가 이미 측정되었다는 질문에이 질문에 대해서는 도구를 사용하여 측정해야합니다. 이 도구는 verboseGC 옵션이 켜진 상태에서 JVM에 의해 생성 된 로그를 처리합니다.

위에 나열된 모든 마크 및 스윕 옵션은이 기본적인 개선에 필요하지 않을 수 있습니다.

사람들은 GC 옵션을 실제 용도로 얼마나 성숙했는지 평가하지 않고 솔루션으로 던집니다.

+0

나는 너를 생각한다. 영원한 세대에 대해 혼란 스럽습니다. 객체를 보관하지 않으며, 클래스 정의, 클래스 메타 데이터 등을 보유합니다. –