Program Tip

Java 매우 큰 힙 크기

programtip 2020. 10. 14. 20:52
반응형

Java 매우 큰 힙 크기


누구든지 Java에서 12GB 이상의 매우 큰 힙을 사용한 경험이 있습니까?

  • GC로 인해 프로그램을 사용할 수 없습니까?
  • 어떤 GC 매개 변수를 사용합니까?
  • 어떤 JVM, Sun 또는 BEA가 이에 더 적합할까요?
  • 이러한 조건에서 어떤 플랫폼 (Linux 또는 Windows)이 더 잘 작동합니까?
  • Windows의 경우 이러한 높은 메모리로드에서 64 비트 Vista와 XP 사이에 성능 차이가 있습니까?

응용 프로그램이 대화 형이 아니고 GC 일시 중지가 문제가되지 않는 경우 64 비트 Java가 수백 GB에서도 매우 큰 힙을 처리하는 데 문제가 없어야합니다. 또한 Windows 또는 Linux에서 안정성 문제를 발견하지 못했습니다.

그러나 GC 일시 중지를 낮게 유지해야하는 경우 상황이 정말 심해집니다.

  1. 기본 처리량 인 stop-the-world GC는 잊어 버리십시오. 보통 힙 (<~ 30GB)의 경우 수십 초 동안 애플리케이션을 일시 중지하고 큰 힙 (> ~ 30GB)의 경우 몇 분 동안 애플리케이션을 일시 중지합니다. 더 빠른 DIMM을 구입하는 것은 도움이되지 않습니다.

  2. 가장 좋은 방법은 아마도 -XX : + UseConcMarkSweepGC에 의해 활성화 된 CMS 수집기 일 것입니다. CMS 가비지 수집기는 초기 표시 단계 및 설명 단계에 대해서만 응용 프로그램을 중지합니다. 4GB 미만과 같은 매우 작은 힙의 경우 일반적으로 문제가되지 않지만 많은 가비지와 큰 힙을 생성하는 애플리케이션의 경우 설명 단계에 시간이 많이 걸릴 수 있습니다. 일반적으로 완전히 중지하는 것보다 훨씬 적습니다. 하지만 매우 큰 힙의 경우 여전히 문제가 될 수 있습니다.

  3. CMS 가비지 수집기가 테너 세대가 가득 차기 전에 작업을 완료 할만큼 빠르지 않으면 표준 stop-the-world GC로 돌아갑니다. 16GB 크기의 힙에 대해 ~ 30 초 이상의 긴 일시 중지가 예상됩니다. 애플리케이션의 수명이 긴 쓰레기 생성 속도를 가능한 한 낮게 유지하는 것을 방지 할 수 있습니다. 응용 프로그램을 실행하는 코어 수가 많을수록 CMS는 하나의 코어 만 사용하므로이 문제가 더 커집니다. 분명히, CMS가 STW 수집기로 돌아 가지 않는다는 보장 없습니다 . 그럴 경우 일반적으로 최대 부하에서 발생하며 애플리케이션은 몇 초 동안 작동하지 않습니다. 이러한 구성에 대한 SLA에 서명하고 싶지 않을 것입니다.

  4. 글쎄요, 새로운 G1이 있습니다. 이론적으로 CMS의 문제를 방지하도록 설계되었지만 우리는이를 시도한 결과 다음과 같은 사실을 관찰했습니다.

    • 처리량은 CMS보다 나쁩니다.
    • 이론적으로는 인기있는 메모리 블록을 먼저 수집하는 것을 피해야하지만 곧 거의 모든 블록이 "인기있는"상태에 도달하고 단순히 작동을 멈춘다는 가정에 도달합니다.
    • 마지막으로 G1에 대한 stop-the-world 폴 백이 여전히 존재합니다. 해당 코드가 실행될 때 Oracle에 문의하십시오. "절대"라고 말하면 코드가있는 이유를 물어보십시오. 따라서 IMHO G1은 Java의 거대한 힙 문제를 해결하지 않고 (논의의 여지없이) 조금 더 작게 만듭니다.
  5. 큰 메모리를 가진 큰 서버에 돈이 있다면 Azul이 제공하는 것과 같은 좋은 상용 하드웨어 가속, 일시 중지없는 GC 기술에 대해서도 돈이있을 것입니다. 우리는 384GB RAM을 가진 서버 중 하나를 가지고 있으며 실제로 잘 작동합니다. GC에서 멈추지 않고 0 라인의 세계 중지 코드입니다.

  6. LinkedIn이 소셜 그래프 처리에서했던 것처럼 C ++로 많은 메모리를 필요로하는 애플리케이션의 망할 부분을 작성하세요. 이렇게하면 (예 : 힙 조각화) 모든 문제를 피할 수는 없지만 일시 중지를 낮게 유지하는 것이 확실히 더 쉬울 것입니다.


저는 Azul Systems의 CEO이므로이 주제에 대한 제 의견에 편견이 있습니다! :) 그 말은 ...

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 일시 중지가 그렇게 낮은 이유입니다.


우리는 12-16Gb를 할당하는 애플리케이션이 있지만 실제로는 정상 작동 중에 8-10에 도달합니다. 우리는 Sun JVM을 사용합니다 (IBM을 시도했고 약간의 재앙 이었지만 우리 쪽에서는 무지했을 수도 있습니다 ... 저는 IBM에서 일하는 친구가 있습니다). 앱에 숨쉬는 공간을 제공하는 한 JVM은 너무 많은 GC로 큰 힙 크기를 처리 할 수 ​​있습니다. 많은 '추가'메모리가 핵심입니다.
Linux는 거의 항상 Windows보다 안정적이며 안정적이지 않은 경우 이유를 파악하기가 훨씬 쉽습니다. 솔라리스도 견고하고 DTrace도 얻을 수 있습니다. :) 이런 종류의 부하로 인해 도대체 왜 Vista 또는 XP를 사용합니까? 당신은 단지 문제를 요구하고 있습니다. 우리는 GC 매개 변수로 멋진 일을하지 않습니다. 최소 할당량을 최대 값과 동일하게 설정하여 지속적으로 크기를 조정하지 않고 그게 전부입니다.


저는 64 비트 버전 (분명히)의 Sun 1.6 JVM을 사용하여 Linux와 Solaris의 서로 다른 두 응용 프로그램에서 60GB 이상의 힙 크기를 사용했습니다.

힙 크기 제한에 근접 할 때를 제외하고는 Linux 기반 응용 프로그램에서 가비지 수집 문제가 발생하지 않았습니다. 해당 시나리오에 내재 된 스 래싱 문제 (가비지 수집에 너무 많은 시간이 소요됨)를 방지하기 위해 프로그램 전체에서 메모리 사용량을 최적화하여 최대 사용량이 64GB 힙 크기 제한보다 약 5-10 % 낮았습니다.

그러나 솔라리스에서 실행되는 다른 응용 프로그램에서는 많은 수정 작업이 필요한 심각한 가비지 수집 문제가 발생했습니다. 이것은 주로 세 단계로 구성됩니다.

  1. -XX : + UseParallelGC -XX : + UseParallelOldGC JVM 옵션을 통해 병렬 가비지 수집기의 사용을 활성화 / 강제 설정하고 -XX : ParallelGCThreads 옵션을 통해 사용되는 GC 스레드 수를 제어합니다. 자세한 내용은 " Java SE 6 HotSpot Virtual Machine Garbage Collection Tuning "을 참조하십시오.

  2. 더 이상 필요하지 않은 지역 변수를 "null"로 광범위하고 우스꽝스럽게 설정합니다. 이들 중 대부분은 범위를 벗어난 후 가비지 수집에 적합해야하는 변수였으며 참조가 복사되지 않았기 때문에 메모리 누수 상황이 아닙니다. 그러나 가비지 수집을 지원하기위한이 "핸드 홀딩"전략은 문제의 Solaris 플랫폼에서이 응용 프로그램에 대해 설명 할 수없는 이유로 필요했습니다.

  3. 장기간의 임시 객체 할당 후 키 코드 섹션에서 System.gc () 메서드 호출을 선택적으로 사용합니다. 이러한 호출을 사용하는 것에 대한 표준 경고와 일반적으로 불필요해야한다는 주장을 알고 있지만 메모리 집약적 인 애플리케이션을 실행할 때 가비지 수집을 길들이는 데 중요하다는 것을 알았습니다.

위의 세 단계를 통해 제어 할 수없는 128GB 힙 크기 제한까지 확장하는 대신이 애플리케이션을 포함하고 약 60GB 힙 사용량으로 생산적으로 실행할 수있었습니다. 특히 병렬 가비지 수집기는 많은 개체가있을 때 주요 가비지 수집주기가 비싸기 때문에 매우 유용했습니다. 즉, 주요 가비지 수집에 필요한 시간은 힙의 개체 수에 따라 달라집니다.

I cannot comment on other platform-specific issues at this scale, nor have I used non-Sun (Oracle) JVMs.


12Gb should be no problem with a decent JVM implementation such as Sun's Hotspot. I would advice you to use the Concurrent Mark and Sweep colllector ( -XX:+UseConcMarkSweepGC) when using a SUN VM.Otherwies you may face long "stop the world" phases, were all threads are stopped during a GC.

The OS should not make a big difference for the GC performance.

You will need of course a 64 bit OS and a machine with enough physical RAM.


I recommend also considering taking a heap dump and see where memory usage can be improved in your app and analyzing the dump in something such as Eclipse's MAT . There are a few articles on the MAT page on getting started in looking for memory leaks. You can use jmap to obtain the dump with something such as ...

jmap -heap:format=b pid

As mentioned above, if you have a non-interactive program, the default (compacting) garbage collector (GC) should work well. If you have an interactive program, and you (1) don't allocate memory faster than the GC can keep up, and (2) don't create temporary objects (or collections of objects) that are too big (relative to the total maximum JVM memory) for the GC to work around, then CMS is for you.

You run into trouble if you have an interactive program where the GC doesn't have enough breathing room. That's true regardless of how much memory you have, but the more memory you have, the worse it gets. That's because when you get too low on memory, CMS will run out of memory, whereas the compacting GCs (including G1) will pause everything until all the memory has been checked for garbage. This stop-the-world pause gets bigger the more memory you have. Trust me, you don't want your servlets to pause for over a minute. I wrote a detailed StackOverflow answer about these pauses in G1.

Since then, my company has switched to Azul Zing. It still can't handle the case where your app really needs more memory than you've got, but up until that very moment it runs like a dream.

But, of course, Zing isn't free and its special sauce is patented. If you have far more time than money, try rewriting your app to use a cluster of JVMs.

On the horizon, Oracle is working on a high-performance GC for multi-gigabyte heaps. However, as of today that's not an option.


If you switch to 64-bit you will use more memory. Pointers become 8 bytes instead of 4. If you are creating lots of objects this can be noticeable seeing as every object is a reference (pointer).

I have recently allocated 15GB of memory in Java using the Sun 1.6 JVM with no problems. Though it is all only allocated once. Not much more memory is allocated or released after the initial amount. This was on a Linux but I imagine the Sun JVM will work just as well on 64-bit Windows.


an article from sun on java 6 can help you : http://java.sun.com/developer/technicalArticles/javase/troubleshoot/


You should try running visualgc against your app. It´s a heap visualization tool that´s part of the jvmstat download at http://java.sun.com/performance/jvmstat/

It is a lot easier than reading GC logs.

It quickly helps you understand how the parts (generations) of the heap are working. While your total heap may be 10GB, the various parts of the heap will be much smaller. GCs in the Eden portion of the heap are relatively cheap, while full GCs in the old generation are expensive. Sizing your heap so that that the Eden is large and the old generation is hardly ever touched is a good strategy. This may result in a very large overall heap, but what the heck, if the JVM never touches the page, it´s just a virtual page, and doesn´t have to take up RAM.


A couple of years ago, I compared JRockit and the Sun JVM for a 12G heap. JRockit won, and Linux hugepages support made our test run 20% faster. YMMV as our test was very processor/memory intensive and was primarily single-threaded.


here's an article on gc FROM one of Java Champions -- http://kirk.blog-city.com/is_your_concurrent_collector_failing_you.htm

Kirk, the author writes "Send me your GC logs

I'm currently interested in studying Sun JVM produced GC logs. Since these logs contain no business relevent information it should be ease concerns about protecting proriatary information. All I ask that with the log you mention the OS, complete version information for the JRE, and any heap/gc related command line switches that you have set. I'd also like to know if you are running Grails/Groovey, JRuby, Scala or something other than or along side Java. The best setting is -Xloggc:. Please be aware that this log does not roll over when it reaches your OS size limit. If I find anything interesting I'll be happy to give you a very quick synopsis in return. "


The max memory that XP can address is 4 gig(here). So you may not want to use XP for that(use a 64 bit os).


sun has had an itanium 64-bit jvm for a while although itanium is not a popular destination. The solaris and linux 64-bit JVMs should be what you should be after.
Some questions

1) is your application stable ?
2) have you already tested the app in a 32 bit JVM ?
3) is it OK to run multiple JVMs on the same box ?

I would expect the 64-bit OS from windows to get stable in about a year or so but until then, solaris/linux might be better bet.

참고URL : https://stackoverflow.com/questions/214362/java-very-large-heap-sizes

반응형