[java] 프로덕션에서 Java G1 가비지 수집

Java 7은 기본적으로 새로운 G1 가비지 콜렉션을 사용하기 때문에 Java가 GC 일시 중지 시간을 “파괴적인”것으로 간주하지 않고 훨씬 더 큰 힙을 처리 할 수 ​​있습니까? 실제로 G1을 프로덕션에 구현 한 사람이 있습니까? 경험은 어땠습니까?

공평하게 말하면, 정말 긴 GC 일시 중지를 본 유일한 시간은 워크 스테이션보다 훨씬 더 큰 힙에 있습니다. 내 질문을 명확히하기 위해; G1은 수백 GB의 힙에 대한 게이트웨이를 열 것인가? 결핵?



답변

G1의 요점은 최대 일시 중지 시간 목표를 지정할 수있는 지점까지도 일시 중지 시간이 더 짧다는 것 같습니다.

가비지 수집은 단순한 “이봐, 꽉 찼습니다. 모든 것을 한 번에 옮기고 다시 시작합시다.”거래가 더 이상 아닙니다. 환상적으로 복잡한 다단계 백그라운드 스레드 시스템입니다. 일시 중지없이 백그라운드에서 대부분의 유지 관리를 수행 할 수 있으며, 대부분의 개체가 생성 된 직후 죽는다고 가정하는 것과 같이 런타임시 시스템의 예상 패턴에 대한 지식을 사용하여 도움을줍니다.

GC 일시 중지 시간은 향후 릴리스에서 악화되지 않고 계속 개선 될 것입니다.

편집하다:

다시 읽을 때 Java를 매일 사용한다는 생각이 들었습니다 .Eclipse, Azureus 및 내가 개발하는 앱은 잠시 멈춘 이후로 오랜만이었습니다. 중요한 일시 중지는 아니지만 전혀 일시 중지를 의미합니다.

Windows 탐색기를 마우스 오른쪽 버튼으로 클릭하거나 (가끔) 특정 USB 하드웨어를 연결할 때 일시 중지되는 것을 보았습니다.하지만 Java는 전혀 사용하지 않습니다.

GC는 여전히 누군가에게 문제가 되나요?


답변

나는 무거운 응용 프로그램으로 테스트했습니다. 60-70GB는 힙에 할당되고 20-50GB는 언제든지 사용됩니다. 이러한 종류의 응용 프로그램을 사용하면 마일리지가 다를 수 있다고 말하는 것은 과소 평가입니다. Linux에서 JDK 1.6_22를 실행하고 있습니다. 부 버전은 중요합니다. 약 1.6_20 이전에는 임의의 NullPointerExceptions를 유발하는 G1 버그가있었습니다.

나는 당신이 대부분의 시간에 주어진 일시 중지 목표를 유지하는 것이 매우 좋다는 것을 발견했습니다. 기본값은 100ms (0.1 초) 일시 중지로 보이며 그 절반을 수행하도록 지시했습니다 (-XX : MaxGCPauseMillis = 50). 그러나 메모리가 실제로 부족 해지면 패닉 상태가되고 가비지 컬렉션을 완전히 중지합니다. 65GB를 사용하면 30 초에서 2 분 정도 걸립니다. (CPU 수는 아마도 차이를 만들지 않을 것입니다. 아마도 버스 속도에 의해 제한 될 것입니다.)

CMS (기본 서버 GC는 아니지만 웹 서버 및 기타 실시간 애플리케이션 용이어야 함)와 비교할 때 일반적인 일시 중지는 훨씬 더 예측 가능하고 훨씬 더 짧게 만들 수 있습니다. 지금까지 나는 엄청난 멈춤에 대해 CMS에 더 나은 운을 보였지만 그것은 무작위 일 수있다. 24 시간마다 몇 번만보고 있습니다. 현재 내 프로덕션 환경에서 어느 것이 더 적합한 지 잘 모르겠지만 아마도 G1 일 것입니다. 오라클이 계속 튜닝한다면 G1이 궁극적으로 확실한 승자가 될 것이라고 생각합니다.

기존 가비지 수집기에 문제가 없다면 지금 당장 G1을 고려할 이유가 없습니다. GUI 응용 프로그램과 같이 지연 시간이 짧은 응용 프로그램을 실행하는 경우 MaxGCPauseMillis가 매우 낮게 설정된 G1이 올바른 선택 일 것입니다. 배치 모드 애플리케이션을 실행하는 경우 G1은 아무것도 사지 않습니다.


답변

프로덕션에서 G1을 테스트하지는 않았지만 GC가 “엄청난”힙이없는 케이스에 대해 이미 문제가 있다고 생각했습니다. 특히 2 또는 4 기가 만있는 서비스는 GC에 의해 심각한 영향을받을 수 있습니다. 젊은 세대의 GC는 일반적으로 한 자릿수 밀리 초 (또는 최대 두 자릿수)로 끝나므로 문제가되지 않습니다. 그러나 구세대 컬렉션은 1 기가 이상의 구세대 크기로 몇 초가 걸리기 때문에 훨씬 더 문제가 많습니다.

이제 : 이론상 CMS는 대부분의 작업을 동시에 실행할 수 있으므로 많은 도움이 될 수 있습니다. 그러나 시간이 지남에 따라이를 수행 할 수없고 “세상을 중지”컬렉션으로 돌아 가야하는 경우가 있습니다. 그리고 그 일이 발생하면 (예를 들어, 1 시간 후-자주는 아니지만 너무 자주), 글쎄, 당신의 빌어 먹을 모자를 붙잡 으십시오. 1 분 이상 걸릴 수 있습니다. 이는 최대 대기 시간을 제한하려는 서비스에서 특히 문제가됩니다. 요청을 처리하는 데 25 밀리 초가 걸리는 대신 이제 10 초 이상이 걸립니다. 모욕에 상처를 입히기 위해 클라이언트는 종종 요청 시간을 초과하고 재 시도하여 추가 문제 (일명 “똥 폭풍”)로 이어집니다.

이것은 G1이 많은 도움을 주길 바랬던 영역입니다. 저는 스토리지 및 메시지 발송을위한 클라우드 서비스를 제공하는 대기업에서 일했습니다. 그리고 우리는 CMS를 사용할 수 없었습니다. 대부분의 경우 병렬 품종보다 더 잘 작동했지만 이러한 붕괴가 있었기 때문입니다. 그래서 약 한 시간 동안 일이 좋았습니다. 그런 다음 물건이 팬에 부딪 혔습니다. 서비스가 클러스터를 기반으로했기 때문에 한 노드가 문제가 발생했을 때 다른 노드가 일반적으로 뒤따 랐습니다 (GC로 인한 시간 초과로 인해 다른 노드가 노드가 충돌 한 것으로 믿고 경로를 다시 지정하기 때문입니다).

나는 GC가 앱의 문제라고 생각하지 않으며 클러스터되지 않은 서비스조차도 영향을 덜받는다고 생각합니다. 그러나 점점 더 많은 시스템이 클러스터링되고 (특히 NoSQL 데이터 저장소 덕분에) 힙 크기가 증가하고 있습니다. OldGen GC는 힙 크기와 매우 선형 적으로 관련되어 있습니다 (즉, 힙 크기를 두 배 이상 늘리면 GC 시간이 두 배가되고 라이브 데이터 세트의 크기도 두 배가된다고 가정).


답변

Azul의 CTO 인 Gil Tene은 가비지 수집과 관련된 문제에 대한 멋진 개요와 Java 가비지 수집의 이해 및 이에 대해 할 수있는 작업 프레젠테이션 에서 다양한 솔루션에 대한 검토를 제공합니다 .이 문서에는 http : // www.infoq.com/articles/azul_gc_in_detail .

Zing JVM에있는 Azul의 C4 가비지 수집기는 병렬 및 동시 적이며 새로운 세대와 이전 세대 모두에 동일한 GC 메커니즘을 사용하여 동시에 작동하고 두 경우 모두 압축합니다. 가장 중요한 것은 C4가 세상을 멈출 수 없다는 것입니다. 모든 압축은 실행중인 응용 프로그램과 동시에 수행됩니다. 우리는 고객이 매우 큰 (수백 GBytes) 실행 중이며 최악의 경우 GC 일시 중지 시간이 10msec 미만이고 애플리케이션에 따라 종종 1-2msec 미만의 시간이 소요됩니다.

CMS 및 G1의 문제점은 어느 시점에서 Java 힙 메모리를 압축해야하고 이러한 가비지 수집기 모두 압축을 수행하기 위해 세계 / STW를 중지 (즉, 응용 프로그램 일시 중지)해야한다는 것입니다. 따라서 CMS와 G1은 STW 일시 중지를 푸시 할 수 있지만 제거하지는 않습니다. 그러나 Azul의 C4는 STW 일시 중지를 완전히 제거하므로 Zing이 거대한 힙 크기에서도 GC 일시 중지가 낮은 이유입니다.

그리고 이전 답변에서 작성한 진술을 수정하기 위해 Zing은 운영 체제를 변경할 필요가 없습니다. 수정되지 않은 Linux 배포판에서 다른 JVM처럼 실행됩니다.


답변

우리는 거의 2 년 동안 이미 G1GC를 사용하고 있습니다. 미션 크리티컬 트랜잭션 처리 시스템에서 뛰어난 성능을 발휘하며 높은 처리량, 낮은 일시 중지, 동시성 및 최적화 된 대용량 메모리 관리에 대한 훌륭한 지원임을 입증했습니다.

다음 JVM 설정을 사용하고 있습니다.

-server -Xms512m -Xmx3076m -XX:NewRatio=50 -XX:+HeapDumpOnOutOfMemoryError -XX:+UseG1GC -XX:+AggressiveOpts -XX:+UnlockExperimentalVMOptions -XX:MaxGCPauseMillis=400 -XX:GCPauseIntervalMillis=8000 -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime

업데이트 됨

-d64 -server -Xss4m -Xms1024m -Xmx4096m -XX:NewRatio=50 -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:-DisableExplicitGC -XX:+AggressiveOpts -Xnoclassgc -XX:+UseNUMA -XX:+UseFastAccessorMethods -XX:ReservedCodeCacheSize=48m -XX:+UseStringCache -XX:+UseStringDeduplication -XX:MaxGCPauseMillis=400 -XX:GCPauseIntervalMillis=8000


답변

G1 수집기는 전체 수집의 영향을 줄입니다. 이미 전체 컬렉션의 필요성을 줄인 애플리케이션이있는 경우 Concurrent map Sweep 컬렉터도 마찬가지로 좋으며 경험상 마이너 컬렉션 시간이 더 짧습니다.


답변

JDK7u4를 시작하는 G1이 마침내 공식적으로 지원되는 것 같습니다 . JDK7u4
http://www.oracle.com/technetwork/java/javase/7u4-relnotes-1575007.html을 참조하십시오 .

여전히 큰 JVM에 대한 테스트에서 CMS는 여전히 G1보다 더 잘 작동하지만 더 잘 성장할 것이라고 생각합니다.