it-swarm.com.de

Java sehr große Heap-Größen

Hat jemand Erfahrung mit der Verwendung von sehr großen Heaps, 12 GB oder mehr in Java?

  • Macht das GC das Programm unbrauchbar?
  • Welche GC-Parameter verwenden Sie?
  • Welche JVM, Sun oder BEA wäre dafür besser geeignet?
  • Welche Plattform, Linux oder Windows, funktioniert unter solchen Bedingungen besser?
  • Gibt es bei Windows einen Leistungsunterschied zwischen 64-Bit-Vista und XP bei derart hohen Speicherauslastungen?
74
pdeva

Wenn Ihre Anwendung nicht interaktiv ist und GC-Pausen für Sie kein Problem sind, sollte 64-Bit-Java kein Problem damit haben, sehr große Heaps zu verarbeiten, selbst in Hunderten von GB. Auch unter Windows oder Linux sind keine Stabilitätsprobleme aufgetreten.

Wenn Sie jedoch die GC-Pausen niedrig halten müssen, werden die Dinge wirklich böse:

  1. Vergessen Sie den Standarddurchsatz, Stop-the-World-GC. Die Anwendung wird für mäßige Heaps (<~ 30 GB) mehrere zehn Sekunden und für große (> ~ 30 GB) einige Minuten angehalten. Der Kauf schnellerer DIMMs hilft nicht.

  2. Die beste Wette ist wahrscheinlich der CMS-Collector, der von -XX: + UseConcMarkSweepGC aktiviert wird. Der CMS-Garbage-Collector stoppt die Anwendung nur für die erste Markierungsphase und die Bemerkungsphase. Für sehr kleine Heaps wie <4 GB ist dies normalerweise kein Problem, aber für eine Anwendung, die viel Müll und einen großen Haufen erzeugt, kann die Remarking-Phase ziemlich lange dauern - in der Regel weniger als Full Stop-the-World , kann aber für sehr große Haufen immer noch ein Problem sein.

  3. Wenn der CMS-Garbage Collector nicht schnell genug ist, um den Betrieb zu beenden, bevor die Dauergeneration voll ist, fällt er auf die Standard-Stop-the-World-GC zurück. Erwarten Sie etwa 30 Sekunden oder mehr Pausen für Heaps der Größe 16 GB. Sie können versuchen, dies zu vermeiden, um die langlebige Müllproduktionsrate Ihrer Anwendung so gering wie möglich zu halten. Je höher die Anzahl der Kerne ist, auf denen Ihre Anwendung ausgeführt wird, desto größer wird dieses Problem, da der CMS nur einen Kern verwendet. Vorsicht, es gibt keine Garantie, dass das CMS nicht auf den STW-Collector zurückgreift. Wenn dies der Fall ist, geschieht dies normalerweise bei den Spitzenlasten, und Ihre Anwendung ist für einige Sekunden tot. Sie möchten wahrscheinlich keine SLA für eine solche Konfiguration signieren.

  4. Nun, da ist das neue G1-Ding. Es ist theoretisch darauf ausgelegt, die Probleme mit CMS zu vermeiden, aber wir haben es ausprobiert und festgestellt, dass:

    • Sein Durchsatz ist schlechter als der von CMS.
    • Es sollte theoretisch vermieden werden, die populären Speicherblöcke zuerst zu sammeln, erreicht jedoch bald einen Zustand, in dem fast alle Blöcke "beliebt" sind und die Annahmen, auf denen es basiert, einfach aufhören zu arbeiten.
    • Schließlich gibt es noch den Stop-the-World-Fallback für G1; Fragen Sie Oracle, wann der Code ausgeführt werden soll. Wenn sie "nie" sagen, fragen Sie sie, warum der Code da ist. Daher lässt IMHO G1 das riesige Heap-Problem von Java wirklich nicht verschwinden, sondern lässt es (wohl) nur etwas kleiner werden.
  5. Wenn Sie viel Geld für einen großen Server mit großem Speicher haben, haben Sie wahrscheinlich auch eine gute, kommerziell für Hardware beschleunigte, pausenlose GC-Technologie, wie sie von Azul angeboten wird. Wir haben einen ihrer Server mit 384 GB RAM und es funktioniert wirklich gut - keine Pausen, 0 Zeilen des Stop-the-World-Codes im GC. 

  6. Schreiben Sie den verdammten Teil Ihrer Anwendung, der in C++ viel Speicher benötigt, wie es LinkedIn bei der Verarbeitung von Social Graphen tat. Sie vermeiden zwar immer noch nicht alle Probleme (z. B. Heap-Fragmentierung), aber es wäre definitiv einfacher, die Pausen gering zu halten.

70

Ich bin CEO von Azul Systems und bin meiner Meinung zu diesem Thema offensichtlich voreingenommen! :) Das wird gesagt ...

Gil Tene, CTO von Azul, hat einen Überblick über die Probleme, die mit der Garbage Collection verbunden sind, und eine Übersicht über verschiedene Lösungen in seinem Grundlegendes zu Java Garbage Collection und Was Sie dagegen tun können Präsentation. Weitere Informationen finden Sie in diesem Artikel: http://www.infoq.com/articles/azul_gc_in_detail .

Der C4-Müllsammler von Azul in unserer Zing-JVM ist sowohl parallel als auch gleichzeitig und verwendet den gleichen GC-Mechanismus für die neue und die alte Generation, der gleichzeitig arbeitet und in beiden Fällen kompaktiert. Am wichtigsten ist, dass C4 keinen Halt für die Welt hat. Die gesamte Komprimierung wird gleichzeitig mit der laufenden Anwendung ausgeführt. Wir haben Kunden, die sehr große Laufzeiten haben (Hunderte von GB), wobei die GC-Pausenzeiten im schlimmsten Fall <10 ms und je nach Anwendung oftmals weniger als 1-2 ms betragen.

Das Problem bei CMS und G1 besteht darin, dass der Java-Heap-Speicher zu einem bestimmten Zeitpunkt komprimiert werden muss und dass beide Speicherbereiniger die Welt/STW anhalten (d. H. Die Anwendung anhalten), um die Komprimierung durchzuführen. Während also CMS und G1 STW-Pausen herausdrücken können, werden sie nicht beseitigt. Azuls C4 eliminiert jedoch vollständig die STW-Pausen, weshalb Zing selbst für gigantische Heap-Größen so niedrige GC-Pausen aufweist.

17
Scott Sellers

Wir haben eine Anwendung, der wir 12-16 GB zuweisen, aber im normalen Betrieb erreicht sie wirklich nur 8-10. Wir verwenden die Sun JVM (IBMs ausprobiert und es war ein bisschen eine Katastrophe, aber das war vielleicht Unwissenheit auf unserer Seite ... Ich habe Freunde, die darauf schwören - diese Arbeit bei IBM). Solange Sie Ihrer App Raum zum Atmen geben, kann die JVM große Heap-Größen mit nicht zu viel GC verarbeiten. Viel "zusätzlicher" Speicher ist der Schlüssel.
Linux ist fast immer stabiler als Windows, und wenn es nicht stabil ist, ist es viel einfacher, den Grund dafür herauszufinden. Solaris ist auch absolut solide und Sie erhalten auch DTrace :) Warum würden Sie mit dieser Art von Lasten Vista oder XP verwenden? Sie bitten nur um Ärger. Wir machen mit den GC-Parametern nichts Besonderes. Wir setzen die minimale Zuweisung auf das Maximum, sodass nicht ständig versucht wird, die Größe zu ändern, aber das ist es. 

15
Ichorus

Ich habe über 60 GB Heap-Größen für zwei verschiedene Anwendungen unter Linux bzw. Solaris verwendet, wobei 64-Bit-Versionen (offensichtlich) der Sun 1.6 JVM verwendet wurden.

Ich habe nie Probleme mit der Garbage Collection mit der Linux-basierten Anwendung erlebt, es sei denn, es wurde nahe der Heap-Größengrenze nach oben geschoben. Um die mit diesem Szenario verbundenen Thrash-Probleme (zu viel Zeit für die Speicherbereinigung) zu vermeiden, habe ich die Speichernutzung im gesamten Programm so optimiert, dass die Spitzenauslastung etwa 5-10% unter einer Heap-Größengrenze von 64 GB lag.

Bei einer anderen Anwendung, die unter Solaris ausgeführt wird, bin ich jedoch auf erhebliche Probleme mit der Müllsammlung gestoßen, was viele Optimierungen erforderlich machte. Dies bestand hauptsächlich aus drei Schritten:

  1. Aktivieren/Erzwingen der Verwendung des parallelen Garbage Collector über die Option -XX: + UseParallelGC -XX: + UseParallelOldGC JVM sowie Steuern der Anzahl der verwendeten GC-Threads über die Option -XX: ParallelGCThreads. Weitere Informationen finden Sie unter " Java SE 6 HotSpot - Garbage Collection-Optimierung für virtuelle Maschinen ".

  2. Umfangreiche und scheinbar lächerliche Einstellung lokaler Variablen auf "null", nachdem sie nicht mehr benötigt werden. Bei den meisten dieser Variablen handelte es sich um Variablen, die nach dem Erlöschen des Gültigkeitsbereichs für die Speicherbereinigung in Frage kamen, und es handelte sich nicht um Speicherlecks, da die Referenzen nicht kopiert wurden. Diese "Hand-Holding" -Strategie zur Unterstützung der Speicherbereinigung war jedoch aus irgendeinem Grund für diese Anwendung unter der fraglichen Solaris-Plattform unerklärlich notwendig.

  3. Selektive Verwendung des System.gc () - Methodenaufrufs in Schlüsselcodeabschnitten nach längeren Zeiträumen der temporären Objektzuordnung. Ich kenne die Standardvorbehalte gegen die Verwendung dieser Aufrufe und das Argument, dass sie normalerweise unnötig sein sollten, aber ich habe festgestellt, dass sie beim Sammeln der Speicherbereinigung beim Ausführen dieser speicherintensiven Anwendung kritisch sind.

Die drei obigen Schritte machten es möglich, diese Anwendung bei einer Heap-Auslastung von etwa 60 GB zu halten und produktiv zu betreiben, anstatt sich außer Kontrolle zu setzen, bis zu der 128-GB-Heap-Größenbegrenzung, die vorhanden war. Insbesondere der parallele Speicherbereiniger war sehr hilfreich, da große Speicherbereinigungszyklen teuer sind, wenn viele Objekte vorhanden sind, d. H. Die für die Speicherbereinigung benötigte Zeit hängt von der Anzahl der Objekte im Heap ab.

Ich kann zu dieser Plattform keine weiteren plattformspezifischen Probleme kommentieren und auch keine JVMs anderer Hersteller (Oracle) verwenden.

9
Joel Hoff

12 GB sollten mit einer anständigen JVM-Implementierung wie Suns Hotspot kein Problem darstellen. Ich würde Ihnen empfehlen, den Concurrent-Markierungs- und Sweep-Colllector (-XX: + UseConcMarkSweepGC) zu verwenden, wenn Sie eine Sun-VM verwenden. 

Das Betriebssystem sollte für die GC-Leistung keinen großen Unterschied machen. 

Sie benötigen natürlich ein 64-Bit-Betriebssystem und eine Maschine mit ausreichend physischem RAM. 

8
kohlerm

Ich empfehle außerdem, einen Heap-Dump zu erstellen, um zu sehen, wo die Speichernutzung in Ihrer App verbessert werden kann, und den Dump in etwas wie Eclipse's MAT zu analysieren. Es gibt einige Artikel auf der MAT-Seite, in denen Sie nach Speicherverlusten suchen. Sie können jmap verwenden, um den Speicherauszug mit etwas wie ... zu erhalten.

jmap -heap:format=b pid
5
jlintz

Wenn Sie ein nicht interaktives Programm haben, sollte der standardmäßige (komprimierende) Garbage Collector (GC) gut funktionieren. Wenn Sie über ein interaktives Programm verfügen und Sie (1) keinen Speicher schneller zuweisen, als der GC mithalten kann, und (2) keine temporären Objekte (oder Sammlungen von Objekten) erstellen, die zu groß sind (relativ zur Gesamtsumme) maximaler JVM-Speicher), damit der GC umgehen kann, dann ist CMS für Sie.

Sie haben Probleme, wenn Sie ein interaktives Programm haben, bei dem der GC nicht genügend Atemraum hat. Das ist unabhängig davon, wie viel Speicher Sie haben, aber je mehr Speicher Sie haben, desto schlechter wird es. Dies liegt daran, dass dem CMS zu wenig Speicherplatz zur Verfügung steht, während die komprimierenden GCs (einschließlich G1) alles anhalten, bis der gesamte Speicher auf Papierkorb geprüft wurde. Diese Stop-the-World-Pause wird umso größer, je mehr Speicher Sie haben. Vertrauen Sie mir, Sie wollen nicht, dass Ihre Servlets länger als eine Minute stehen bleiben. Ich habe eine detaillierte StackOverflow-Antwort zu diesen Pausen in G1 geschrieben.

Seitdem ist meine Firma zu Azul Zing gewechselt. Es kann immer noch nicht mit dem Fall umgehen, dass Ihre App wirklich mehr Speicher benötigt, als Sie haben, aber bis zu diesem Moment läuft sie wie ein Traum.

Natürlich ist Zing nicht frei und seine Spezialsauce ist patentiert. Wenn Sie weit mehr Zeit als Geld haben, schreiben Sie Ihre App in einen Cluster von JVMs um.

Am Horizont arbeitet Oracle an einem Hochleistungs-GC für Multi-Gigabyte-Heaps. Allerdings ist das heute keine Option.

2
David Leppik

ein Artikel von Sun auf Java 6 kann Ihnen dabei helfen: http://Java.Sun.com/developer/technicalArticles/javase/troubleshoot/

1
anjanb

hier ist ein Artikel über gc FROM eines der Java Champions - http://kirk.blog-city.com/is_your_concurrent_collector_failing_you.htm

Kirk, der Autor schreibt "Schicken Sie mir Ihre GC-Protokolle

Ich interessiere mich derzeit für das Studium der von Sun JVM erstellten GC-Protokolle. Da diese Protokolle keine geschäftsrelevanten Informationen enthalten, sollten Bedenken hinsichtlich des Schutzes vorläufiger Informationen bestehen. Alles, was ich mit dem Protokoll frage, erwähnen Sie das Betriebssystem, vollständige Versionsinformationen für die JRE und alle heap/gc-bezogenen Befehlszeilenschalter, die Sie festgelegt haben. Ich würde auch gerne wissen, ob Sie Grails/Groovey, JRuby, Scala oder etwas anderes als oder neben Java betreiben. Die beste Einstellung ist -Xloggc :. Bitte beachten Sie, dass dieses Protokoll nicht überschrieben wird, wenn es die Größe Ihres Betriebssystems erreicht. Wenn ich etwas Interessantes finde, gebe ich Ihnen gerne eine sehr kurze Übersicht. "

1
anjanb

Vor ein paar Jahren habe ich JRockit und die Sun JVM mit einem 12G-Haufen verglichen. JRockit hat gewonnen, und die Unterstützung von Linux-Riesenseiten hat unseren Testlauf um 20% beschleunigt. YMMV als unser Test war sehr prozessor-/speicherintensiv und war hauptsächlich Single-Threading.

1
ShabbyDoo

Wenn Sie auf 64-Bit wechseln, benötigen Sie mehr Speicher. Zeiger werden statt zu 4 Bytes. Wenn Sie viele Objekte erstellen, kann dies auffällig sein, da jedes Objekt eine Referenz ist (Zeiger).

Ich habe kürzlich 15 GB Speicher in Java mithilfe der Sun 1.6 JVM ohne Probleme zugewiesen. Es wird zwar alles nur einmal vergeben. Nach dem ursprünglichen Betrag wird nicht viel mehr Speicher zugewiesen oder freigegeben. Dies war unter Linux, aber ich kann mir vorstellen, dass die Sun JVM auch unter 64-Bit-Windows gut funktioniert.

1
Chris de Vries

Sie sollten versuchen, VisualGC mit Ihrer App auszuführen. Es ist ein Heap-Visualisierungstool, das Teil des jvmstat-Downloads unter http://Java.Sun.com/performance/jvmstat/ ist.

Es ist viel einfacher als das Lesen von GC-Protokollen.

Es hilft Ihnen schnell zu verstehen, wie die Teile (Generationen) des Heap funktionieren. Während Ihr gesamter Heapspeicher möglicherweise 10 GB beträgt, sind die verschiedenen Teile des Heapspeichers viel kleiner. GCs im Eden-Teil des Haufens sind relativ billig, während volle GCs in der alten Generation teuer sind. Den Haufen so zu bemessen, dass das Eden groß ist und die alte Generation kaum jemals berührt wird, ist eine gute Strategie. Dies kann zu einem sehr großen Gesamthaufen führen, aber was solls, wenn die JVM die Seite nie berührt, dann handelt es sich lediglich um eine virtuelle Seite, die nicht den Arbeitsspeicher beansprucht.

1
tpgould

Sun hatte eine 64-Bit-Version von Itanium für eine Weile, obwohl Itanium kein beliebtes Ziel ist. Die 64-Bit-JVMs von Solaris und Linux sollten genau das sein, wonach Sie suchen.
Einige Fragen

1) Ist Ihre Bewerbung stabil?
2) Haben Sie die App bereits in einer 32-Bit-JVM getestet?
3) Ist es in Ordnung, mehrere JVMs auf derselben Box auszuführen? 

Ich würde erwarten, dass das 64-Bit-Betriebssystem von Windows in etwa einem Jahr stabil wird, aber bis dahin könnte Solaris/Linux die bessere Wahl sein.

0
anjanb

Der maximale Speicher, den XP adressieren kann, beträgt 4 Gig ( hier ). Daher möchten Sie möglicherweise XP nicht verwenden (verwenden Sie ein 64-Bit-Betriebssystem).

0
Milhous