Java G1 Garbage Collection in der Produktion


91

Da Java 7 standardmäßig die neue G1-Garbage Collection verwendet, kann Java einen um eine Größenordnung größeren Heap verarbeiten, ohne dass die GC-Pausenzeiten "verheerend" sind? Hat jemand tatsächlich G1 in der Produktion implementiert? Welche Erfahrungen haben Sie gemacht?

Um fair zu sein, das einzige Mal, dass ich wirklich lange GC-Pausen gesehen habe, sind sehr große Haufen, viel mehr als eine Workstation. Um meine Frage zu klären; Wird G1 das Gateway für Haufen mit Hunderten von GB öffnen? TB?


15
Obwohl es genauer umformuliert werden könnte, ist dies keine schreckliche Frage. Ich wünschte wirklich, die Leute müssten sich besser erklären als "Keine Frage", wenn sie abstimmen, um zu schließen.
Bill K

Ich habe nicht für den Abschluss gestimmt, aber ich wünschte, das OP hätte seine Ziele mit dem aktuellen GC objektiver dargelegt. Außerdem ist "Java" eine Sprache, während er von einer Implementierung spricht, und ich weiß nicht, was "Implementierung von G1 in der Produktion" bedeutet, insbesondere angesichts der Zukunftsform des Restes der Frage. Wenn es in Java 7 sein wird, hat es sicherlich niemand in der Produktion verwendet?
Pascal Cuoq

6
@Pascal G1 ist eine experimentelle Funktion, die seit JDK 6 Update 14 im JDK verfügbar ist. Mit "Implementierung von G1 in der Produktion" meinte ich, dass er es tatsächlich verwenden wollte, ist nicht so schwer zu verstehen. Und obwohl ich damit einverstanden bin, dass G1 Teil von JDK 7 und nicht von Java ist, gibt eine Suche nach Java 7 bei Google die JDK 7-Homepage als erstes Ergebnis zurück, und beide Begriffe werden häufig synonym verwendet. @ Benju Ich würde den mit G1 erzielten Ergebnissen des aktuellen JDK nicht vertrauen, da es experimentell ist. Viele Dinge könnten sich von jetzt an bis zur offiziellen Veröffentlichung ändern.
Bis zum

2
Es scheint, dass JDK 7 einschließlich Update 1,2 und 3 das G1 gc standardmäßig nicht verwendet. Sie können es durch jinfo -flag UseG1GC pid
George

Antworten:


34

Es hört sich so an, als ob der Punkt von G1 kleinere Pausenzeiten haben soll, sogar bis zu dem Punkt, an dem es möglich ist, ein maximales Pausenzeitziel anzugeben.

Die Speicherbereinigung ist nicht mehr nur ein einfaches "Hey, es ist voll, lassen Sie uns alles auf einmal verschieben und von vorne beginnen" -Deal - es ist ein fantastisch komplexes, mehrstufiges Hintergrund-Thread-System. Es kann einen Großteil seiner Wartung im Hintergrund ohne Pausen durchführen und nutzt auch das Wissen über die erwarteten Muster des Systems zur Laufzeit, um zu helfen - beispielsweise die Annahme, dass die meisten Objekte direkt nach dem Erstellen sterben usw.

Ich würde sagen, dass sich die GC-Pausenzeiten mit zukünftigen Versionen weiter verbessern und nicht verschlechtern werden.

BEARBEITEN:

Beim erneuten Lesen fiel mir ein, dass ich täglich Java verwende - Eclipse, Azureus und die Apps, die ich entwickle, und es ist lange her, seit ich eine Pause sah. Keine nennenswerte Pause, aber ich meine überhaupt eine Pause.

Ich habe Pausen gesehen, wenn ich mit der rechten Maustaste auf Windows Explorer geklickt habe oder (gelegentlich) wenn ich bestimmte USB-Hardware angeschlossen habe, aber mit Java - überhaupt keine.

Ist GC immer noch ein Problem mit jemandem?


Stimmen Sie zu - das einzige Mal, dass ich GC-Pausen gesehen habe, ist, wenn ich sie absichtlich oder versehentlich mit massiv parallelem Code zum Erstellen von Müll provoziert habe .....
mikera

28
Ja, GC ist immer noch ein großes Problem, wenn Sie anfangen, mit großen Haufen (> 16 GB) umzugehen, insbesondere mit großen Generationen.
Der Alchemist

2
@ the-alchemist wow, ich habe deinen Kommentar ein paar Mal nebenbei gesehen und es ist mir nur aufgefallen, dass du 16 GB gesagt hast !! Obwohl ich absolut sicher bin, dass Sie Recht haben, dass dies zu großen Verzögerungen führen kann, möchte ich überprüfen, ob Sie ALLES Austauschen deaktiviert haben. Auf einem großen Speichersystem wird jedes Austauschen von Java Ihr System absolut töten (da GC sehr austauschunfreundlich ist). Ich bin mir sicher, dass Sie dies bereits getan haben, aber ich wollte es nur erwähnen - weil es einen so großen Unterschied machen würde. Ich habe noch nie einen PC mit so viel RAM gesehen - wie viel hast du? 32g?
Bill K

8
Ja, GCs sind für Services insofern problematisch, als sie es SEHR schwierig machen, die TP99.9-Grenzwerte (und höhere Grenzwerte) zu verbessern. Insbesondere GCs der "alten Generation" können Todesfallen sein, die JVM (und den Dienst) für mehrere Sekunden so gut wie einfrieren. und für Dienste, die Anforderungen normalerweise in einstelligen (oder niedrigen zweistelligen) Millisekunden bedienen, ist dies problematisch. Für das, was es wert ist, war dies ein praktisches Problem mit dem Backend-Speicher, der vom Simple Queue-Dienst von Amazon verwendet wird (kann nicht auf viele Details eingehen, da es AWS-intern ist).
StaxMan

21
Das Ärgerliche an GC ist, dass Azul vor Jahren einen ausgeklügelten GC-Algorithmus (Azul C4) erfunden hat, der Hunderte von Gigabyte ohne merkliche Pausenzeiten problemlos bewältigen kann, indem er die Speicherhardware des Prozessors sehr geschickt einsetzt. Aber niemand weiß das und es wird nicht bald in den wichtigsten Java-Versionen implementiert, da es vom Betriebssystem unterstützt werden muss. Und die Anbieter von Betriebssystemen werden nichts tun, bis die Leute den Algorithmus kennen und Druck auf die Anbieter von Betriebssystemen ausüben. Siehe azulsystems.com/zing/pgc , manageruntime.org
Hans-Peter Störr

58

Ich habe es mit einer umfangreichen Anwendung getestet: 60-70 GB sind dem Heap zugeordnet, wobei 20-50 GB jederzeit verwendet werden. Bei diesen Arten von Anwendungen ist es eine Untertreibung zu sagen, dass Ihr Kilometerstand variieren kann. Ich verwende JDK 1.6_22 unter Linux. Die Nebenversionen sind wichtig - vor ungefähr 1.6_20 gab es Fehler in G1, die zufällige NullPointerExceptions verursachten.

Ich habe festgestellt, dass es sehr gut ist, innerhalb des Pausenziels zu bleiben, das Sie ihm die meiste Zeit geben. Die Standardeinstellung scheint eine Pause von 100 ms (0,1 Sekunden) zu sein, und ich habe ihr gesagt, dass sie die Hälfte davon machen soll (-XX: MaxGCPauseMillis = 50). Sobald jedoch der Arbeitsspeicher knapp wird, gerät es in Panik und führt eine vollständige Speicherbereinigung durch. Bei 65 GB dauert das zwischen 30 Sekunden und 2 Minuten. (Die Anzahl der CPUs macht wahrscheinlich keinen Unterschied; sie ist wahrscheinlich durch die Busgeschwindigkeit begrenzt.)

Im Vergleich zu CMS (das nicht der Standard-Server-GC ist, aber für Webserver und andere Echtzeitanwendungen gelten sollte) sind typische Pausen viel vorhersehbarer und können viel kürzer gemacht werden. Bisher habe ich mit CMS mehr Glück für die großen Pausen, aber das kann zufällig sein; Ich sehe sie nur ein paar Mal alle 24 Stunden. Ich bin mir nicht sicher, welches im Moment in meiner Produktionsumgebung besser geeignet ist, aber wahrscheinlich G1. Wenn Oracle es weiter optimiert, wird G1 vermutlich letztendlich der klare Gewinner sein.

Wenn Sie kein Problem mit den vorhandenen Garbage Collectors haben, gibt es derzeit keinen Grund, G1 in Betracht zu ziehen. Wenn Sie eine Anwendung mit geringer Latenz ausführen, z. B. eine GUI-Anwendung, ist G1 wahrscheinlich die richtige Wahl, da MaxGCPauseMillis sehr niedrig eingestellt ist. Wenn Sie eine Batch-Modus-Anwendung ausführen, kauft Ihnen G1 nichts.


14

Obwohl ich G1 nicht in der Produktion getestet habe, dachte ich, ich würde sagen, dass GCs bereits für Fälle ohne "riesige" Haufen problematisch sind. Insbesondere Services mit beispielsweise 2 oder 4 Gigs können durch GC stark beeinträchtigt werden. GCs der jungen Generation sind normalerweise nicht problematisch, da sie in einstelligen Millisekunden (oder höchstens zweistellig) enden. Sammlungen der alten Generation sind jedoch viel problematischer, da sie bei Größen der alten Generation von 1 Gig oder mehr mehrere Sekunden dauern.

Jetzt: Theoretisch kann CMS dort sehr hilfreich sein, da es den größten Teil seines Betriebs gleichzeitig ausführen kann. Im Laufe der Zeit wird es jedoch Fälle geben, in denen dies nicht möglich ist und auf die Sammlung "Stop the World" zurückgegriffen werden muss. Und wenn das passiert (nach etwa 1 Stunde - nicht oft, aber immer noch zu oft), halten Sie sich an Ihren verdammten Hüten fest. Es kann eine Minute oder länger dauern. Dies ist besonders problematisch für Dienste, die versuchen, die maximale Latenz zu begrenzen. Anstatt beispielsweise 25 Millisekunden zu benötigen, um eine Anfrage zu bearbeiten, dauert es jetzt zehn Sekunden oder länger. Um Beleidigungen für beleidigende Kunden hinzuzufügen, wird die Anforderung dann häufig abgelaufen und erneut versucht, was zu weiteren Problemen führt (auch bekannt als "Shit Storm").

Dies ist ein Bereich, in dem G1 viel helfen sollte. Ich habe für ein großes Unternehmen gearbeitet, das Cloud-Services für die Speicherung und den Versand von Nachrichten anbietet. und wir konnten CMS nicht verwenden, da es zwar die meiste Zeit besser funktionierte als parallele Sorten, aber diese Zusammenbrüche aufwies. Für ungefähr eine Stunde waren die Dinge schön; und dann traf das Zeug den Fan ... und da der Dienst auf Clustern basierte, folgten normalerweise andere, wenn ein Knoten in Schwierigkeiten geriet (da GC-induzierte Zeitüberschreitungen dazu führten, dass andere Knoten glaubten, der Knoten sei abgestürzt, was zu Umleitungen führte).

Ich denke nicht, dass GC ein so großes Problem für Apps darstellt, und vielleicht sind sogar nicht geclusterte Dienste weniger häufig betroffen. Aber immer mehr Systeme werden geclustert (insbesondere dank NoSQL-Datenspeichern) und die Größe der Heaps wächst. OldGen-GCs sind superlinear mit der Heap-Größe verbunden (was bedeutet, dass die Verdoppelung der Heap-Größe die GC-Zeit mehr als verdoppelt, vorausgesetzt, die Größe des Live-Datensatzes verdoppelt sich ebenfalls).


13

Gil Tene, CTO von Azul, hat einen schönen Überblick über die mit der Garbage Collection verbundenen Probleme und einen Überblick über verschiedene Lösungen in seiner Präsentation Grundlegendes zur Java Garbage Collection und was Sie dagegen tun können. Weitere Informationen finden Sie in diesem Artikel: http: // www.infoq.com/articles/azul_gc_in_detail .

Azul's C4 Garbage Collector in unserer Zing JVM ist sowohl parallel als auch gleichzeitig und verwendet für die neue und die alte Generation denselben GC-Mechanismus, der in beiden Fällen gleichzeitig arbeitet und komprimiert. Am wichtigsten ist, dass C4 keinen Rückfall hat. Die gesamte Komprimierung wird gleichzeitig mit der laufenden Anwendung durchgeführt. Wir haben Kunden, die sehr groß sind (Hunderte von GByte), mit GC-Pausenzeiten im schlimmsten Fall von <10 ms und je nach Anwendung oft weniger als 1-2 ms.

Das Problem mit CMS und G1 besteht darin, dass der Java-Heapspeicher irgendwann komprimiert werden muss und beide Garbage Collectors die Welt stoppen / STW (dh die Anwendung anhalten), um die Komprimierung durchzuführen. Während CMS und G1 STW-Pausen auslösen können, werden sie nicht beseitigt. Azul's C4 eliminiert jedoch STW-Pausen vollständig und deshalb hat Zing selbst für gigantische Heap-Größen so niedrige GC-Pausen.

Um eine in einer früheren Antwort gemachte Aussage zu korrigieren, benötigt Zing keine Änderungen am Betriebssystem. Es läuft wie jede andere JVM unter unveränderten Linux-Distributionen.


3
Ich frage mich nur, wie Azul's C4 das erreicht hat, was Sie gesagt haben und warum Sun oder Oracle dies nicht können. Gibt es ein großes Geheimnis oder ist dies nur ein Kompromiss?
George

5
Der C4 von Azul verfügt über eine einzigartige Technologie, die ihren Ursprung in den Hardware-Compute-Appliances von Azul hat (die spezielle Prozessoren für die Ausführung von Java-Unternehmensanwendungen verwenden) und für die Ausführung auf regulären x86-Servern unter Linux entwickelt wurde. Jeder andere Garbage Collector der Enterprise-Klasse (ob von Oracle oder IBM) muss irgendwann Stop-the-World-Pausen einlegen - das einzigartige Attribut von Azul's C4 ist, dass diese problematischen STW-Pausen niemals ausgeführt werden. Wenn Sie neugierig sind, haben die Erfinder des C4-Sammlers einen Artikel über seine Funktionsweise veröffentlicht: dl.acm.org/citation.cfm?id=1064988 .
Scott Sellers

Scott, ich habe hier blog.mikemccandless.com/2012/07/… gelesen, dass Azul ein Kernelmodul ausliefert , das Speicher für die JVM-Nutzung vorab zuweist . Ist das nicht wahr? Wenn dies zutrifft, handelt es sich nicht um eine Kernel-Modifikation, sondern um eine Modifikation.
Dan Pritts

4
George, zwei Wörter: patentgeschützt. Dan, wenn Sie Zing kaufen, ist ein Teil dessen, wofür Sie bezahlen, dass die Support-Mitarbeiter es für Ihre Anwendung optimieren - und dazu gehört auch die Zuweisung der gesamten Systemspeicherauslastung. Das Kernelmodul selbst verhindert Schreibvorgänge in einen Speicherblock, der durch Speicherbereinigung erfasst wird. Das ist die geheime Sauce, die es "pausenlos" macht: Threads pausieren nur, wenn sie versuchen, in einen dieser Blöcke zu schreiben, und dann nur so lange, bis dieser Block komprimiert ist.
David Leppik

13

Wir verwenden G1GC bereits seit fast zwei Jahren. Es funktioniert hervorragend in unserem geschäftskritischen Transaktionsverarbeitungssystem und hat sich als hervorragende Unterstützung für hohen Durchsatz, niedrige Pausen, Parallelität und optimierte Speicherverwaltung erwiesen.

Wir verwenden folgende JVM-Einstellungen:

-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

Aktualisiert

-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

5
Unter Java 8 müssen Sie nicht -XX: + UseCompressedOops oder -XX: + DoEscapeAnalysis festlegen. Der Stand ist standardmäßig aktiviert. Siehe: docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
Mirko Ebert

8

Der G1-Kollektor reduziert die Auswirkungen vollständiger Sammlungen. Wenn Sie eine Anwendung haben, bei der Sie den Bedarf an vollständigen Sammlungen bereits reduziert haben, ist der Concurrent Map Sweep-Sammler genauso gut und hat meiner Erfahrung nach kürzere kleinere Erfassungszeiten.


"Beachten Sie, dass die Verwendung von G1 in der Produktion nur zulässig ist, wenn ein Java-Supportvertrag erworben wurde.", groups.google.com/forum/#!topic/javaposse/Vm0a4H-QY54 , also ein Mythos oder nicht?
Christophe Roussy

1
@ChristopheRoussy Ich weiß nicht mehr, ob dies wahr ist (oder habe tatsächlich den Beweis, dass es jemals wahr war). Es erfordert nicht die -XX: + UnlockCommercialFeatures, daher vermute ich, dass G1 keine Lizenz benötigt.
Peter Lawrey


5

Vor kurzem bin ich umgezogen

CMS zu G1GC mit 4G Heap & 8 Core Prozessor auf Servern mit JDK 1.7.45 .

(JDK 1.8.x G1GC wird gegenüber 1.7 bevorzugt, aber aufgrund einiger Einschränkungen muss ich mich an die Version 1.7.45 halten.)

Ich habe die folgenden Schlüsselparameter konfiguriert und alle anderen Parameter auf den Standardwerten gehalten.

-XX:G1HeapRegionSize=n, XX:MaxGCPauseMillis=m, -XX:ParallelGCThreads=n, 
-XX:ConcGCThreads=n apart from -Xms and -Xmx

Wenn Sie diese Parameter optimieren möchten, lesen Sie diesen Orakelartikel .

Wichtige Beobachtungen:

  1. Die Speichernutzung entspricht G1GC im Gegensatz zu High & Lows mit CMS
  2. Die maximale GC-Pausenzeit ist im Vergleich zu CMS geringer
  3. Die für die Speicherbereinigung aufgewendete Zeit ist in G1GC im Vergleich zu CMS etwas hoch.
  4. Die Anzahl der Hauptsammlungen ist im Vergleich zu CMS nahezu vernachlässigbar
  5. Die Anzahl der kleineren Sammlungen liegt im Vergleich zu CMS am oberen Ende

Trotzdem bin ich froh, dass die maximale GC-Pausenzeit kürzer ist als bei CMS. Ich habe die maximale GC-Pausenzeit auf 1,5 Sekunden eingestellt und dieser Wert wurde noch nicht überschritten.

Verwandte SE-Frage:

Garbage Collection und Dokumentation für Java 7 (JDK 7) auf G1


4

CMS kann zu einer langsam verschlechterten Leistung führen, selbst wenn Sie es ausführen, ohne festsitzende Objekte anzusammeln. Dies liegt an der Speicherfragmentierung, die G1 angeblich vermeidet.

Der Mythos über G1, der nur mit bezahlter Unterstützung verfügbar ist, ist genau das, ein Mythos. Sun und jetzt Oracle haben dies auf der JDK-Seite klargestellt.


4

G1 GC soll besser funktionieren. Wenn Sie jedoch -XX: MaxGCPauseMillis zu aggressiv einstellen, wird der Müll zu langsam gesammelt. Und deshalb wurde in David Leppiks Beispiel eine vollständige GC ausgelöst.


4

Ich habe gerade G1 Garbage Collector in unserem Terracotta Big Memory-Projekt implementiert. Bei der Arbeit an verschiedenen Sammlertypen erzielte G1 mit einer Reaktionszeit von weniger als 600 ms die besten Ergebnisse.

Die Testergebnisse (insgesamt 26) finden Sie hier

Ich hoffe es hilft.


3

Ich habe kürzlich einen Teil von Twicsy auf einen neuen Server mit 128 GB RAM migriert und mich für 1.7 entschieden. Ich habe angefangen, dieselben Speichereinstellungen wie bei 1.6 zu verwenden (ich habe mehrere Instanzen, die verschiedene Aufgaben ausführen, von 500 MB Heap bis zu 15 GB, und jetzt eine neue mit 40 GB), und das hat überhaupt nicht gut funktioniert . 1.7 scheint mehr Heap als 1.6 zu verwenden, und ich hatte in den ersten Tagen viele Probleme. Zum Glück hatte ich viel RAM zum Arbeiten und habe den RAM für die meisten meiner Prozesse aufgestockt, hatte aber immer noch einige Probleme. Mein normales MO bestand darin, eine sehr kleine minimale Heap-Größe von 16 m zu verwenden, selbst bei einem maximalen Heap von mehreren Gigabyte, und dann die inkrementelle GC einzuschalten. Dies hielt die Pausen auf ein Minimum. Das funktioniert jetzt allerdings nicht und ich musste die Mindestgröße auf ungefähr das erhöhen, was ich im Durchschnitt auf dem Haufen erwartet hatte. und das hat sehr gut geklappt. Ich habe immer noch inkrementelle GC aktiviert, aber ich werde es ohne versuchen. Keine Pausen mehr und die Dinge scheinen sehr schnell zu laufen. Ich denke also, die Moral der Geschichte ist, dass Sie nicht erwarten, dass Ihre Speichereinstellungen perfekt von 1,6 auf 1,7 übersetzt werden.


2

G1 macht die Anwendung viel agiler: Die Latanz der Anwendung steigt - die App kann als "Soft-Real-Time" bezeichnet werden. Dies erfolgt durch Ersetzen von zwei Arten von GC-Läufen (kleine kleinere und eine große bei Tenured Gen) durch gleich große kleine.

Weitere Informationen finden Sie unter: http://geekroom.de/java/java-expertise-g1-fur-java-7/


1

Ich arbeite mit Java für kleine und große Heaps, und die Frage nach GC und Full GC wird jeden Tag gestellt, da die Einschränkungen möglicherweise strenger sind als in anderen: In bestimmten Umgebungen töten 0,1 Sekunden Scavenger GC oder Full GC Es ist wichtig, einfach die Funktion zu haben und eine feinkörnige Konfiguration und Fähigkeit zu haben (CMS, iCMS, andere ... das Ziel ist es, die bestmögliche Reaktionszeit mit der nahezu Echtzeitbehandlung zu erzielen (hier beträgt die Echtzeitbehandlung häufig 25 ms). Grundsätzlich sind Verbesserungen der GC-Ergonomie und der Heuristik willkommen!


1

Ich verwende G1GC unter Java 8 und auch mit Groovy (auch Java 8), und ich mache verschiedene Arten von Workloads, und insgesamt funktioniert G1GC folgendermaßen:

  • Die Speichernutzung ist sehr gering, z. B. 100 MB anstelle von 500 MB im Vergleich zu den Standardeinstellungen für Java

  • Die Reaktionszeit ist konsistent und sehr gering

  • Die Leistung zwischen Standardeinstellungen und G1GC verlangsamt sich um 20%, wenn G1GC im schlimmsten Fall verwendet wird (ohne Optimierung, Single-Threaded-Anwendung). Angesichts der guten Reaktionszeit und der geringen Speichernutzung ist dies nicht viel.

  • Wenn Sie mit Tomcat arbeiten, das Multithread-fähig ist, ist die Gesamtleistung um 30% besser und die Speichernutzung ist viel geringer, und die Antwortzeiten sind viel geringer.

Insgesamt ist G1GC bei Verwendung sehr unterschiedlicher Workloads ein sehr guter Collector für Java 8 für Multithread-Anwendungen, und selbst für Single-Threaded-Anwendungen gibt es einige Vorteile.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.