Heim  >  Artikel  >  Java  >  JVM-Speicherverwaltung ------Garbage Collector verfeinert (damit Sie problemlos in der Welt der Garbage Collectors spielen können)

JVM-Speicherverwaltung ------Garbage Collector verfeinert (damit Sie problemlos in der Welt der Garbage Collectors spielen können)

黄舟
黄舟Original
2016-12-28 15:51:341077Durchsuche

Einführung

Im vorherigen Kapitel haben wir die Implementierung des Garbage Collectors auf Hotspot besprochen. Es gibt insgesamt sechs Implementierungen und sechs Kombinationen. Dieses Mal wird LZ mit Ihnen die Leistungsfähigkeit jedes dieser sechs Kollektoren und die Leistungsfähigkeit ihrer Kombination besprechen.
Um Ihnen die Betrachtung und den Vergleich zu erleichtern, hat sich LZ entschieden, die beim Schreiben des Designmusters verwendete Methode zu verwenden und diese Kollektoren für einige Kollektoren in mehreren Dimensionen zu erklären.

Client-Modus und Server-Modus

Bevor ich den Inhalt dieses Kapitels vorstelle, möchte ich über die beiden Modi von JVM sprechen, einen ist der Client-Modus und der andere ist der Server-Modus. Der Modus, den wir normalerweise für die Entwicklung verwenden, ist standardmäßig der Client-Modus. Sie können auch den Befehlszeilenparameter -server verwenden, um die Aktivierung des Server-Modus zu erzwingen. Der größte Unterschied zwischen den beiden besteht darin, dass die JVM viele Optimierungen im Server vorgenommen hat Modus.
JAVA-Anwendungen im Servermodus starten langsam, aber aufgrund der Optimierung der JVM im Servermodus wird die Laufgeschwindigkeit immer schneller, wenn das Programm über einen längeren Zeitraum ausgeführt wird. Im Gegenteil: Obwohl JAVA-Anwendungen im Client-Modus schnell starten, sind sie nicht für die Langzeitausführung geeignet. Bei langer Laufzeit ist die Leistung deutlich geringer als im Server-Modus.

Ausführliche Erklärung der Sammler

Im Folgenden werden wir zunächst den relevanten Inhalt eines einzelnen Garbage Collectors besprechen und abschließend kurz auf die Eigenschaften jeder Kombination nach der anderen eingehen.

Serieller Garbage Collector

Algorithmus: Kopieralgorithmus verwenden
Speicherbereich: Entwickelt für die neue Generation
Ausführungsmethode: Einzelthread, seriell
Ausführungsprozess: neue Generation Wann Der Speicher reicht nicht aus. Halten Sie zuerst alle Benutzerprogramme an und starten Sie dann einen GC-Thread, um den Kopieralgorithmus zum Sammeln von Müll zu verwenden. In diesem Prozess werden möglicherweise einige Objekte auf die alte Generation heraufgestuft.
Eigenschaften: Aufgrund von Single-Thread Betrieb und der gesamte GC Das Benutzerprogramm muss in jeder Phase angehalten werden, was dazu führt, dass die Anwendung lange anhält. Dies eignet sich jedoch sehr gut für kleine Programme.
Anwendbare Szenarien: tägliche Verwendung von Entwicklungs- und Debug-Programmen sowie interaktive Programme für Desktop-Anwendungen.
Offene Parameter: -XX:+UseSerialGC (Standardwert im Client-Modus)

Serial Old Garbage Collector

Hier listen wir nicht mehr die Merkmale jeder Dimension für den seriellen Old Collector auf, weil Es unterscheidet sich vom seriellen Kollektor. Der Unterschied besteht darin, dass er für die alte Generation entwickelt wurde und daher einen Markierungs-/Sortierungsalgorithmus verwendet. In den übrigen Abmessungsmerkmalen entspricht der Serien-Alt exakt dem Serien-Kollektor.

ParNew Garbage Collector

Algorithmus: Kopieralgorithmus verwenden
Speicherbereich: Entwickelt für die neue Generation
Ausführungsmethode: Multithreaded, parallel
Ausführungsprozess: aktuelle Generation Speicher Wenn dies nicht ausreicht, halten Sie zunächst alle Benutzerprogramme an und starten Sie dann mehrere GC-Threads, um den Kopieralgorithmus zur parallelen Durchführung der Speicherbereinigung zu verwenden. Während dieses Vorgangs werden möglicherweise einige Objekte auf die alte Generation heraufgestuft
Funktionen: Multi -Threads werden zur parallelen Ausführung verwendet, daher ist es empfindlich gegenüber der Anzahl der Kernprozessoren im System. Es sind mindestens mehrere Prozessoren erforderlich, um mehrere Threads zu öffnen (die Anzahl der Threads kann jedoch gesteuert werden). Der Parameter -XX:ParallelGCThreads=) ist daher nur für Mehrkern- und Mehrprozessorsysteme geeignet. Obwohl das Benutzerprogramm während der gesamten GC-Phase immer noch angehalten werden muss, führt die parallele Multithread-Verarbeitung nicht zu einer zu langen Pause. Daher ist ParNew in Bezug auf den Durchsatz größer als seriell. Je mehr Prozessoren vorhanden sind, desto offensichtlicher ist der Effekt. Dies gilt jedoch nicht absolut, da die Leistung von ParNew aufgrund des Overheads der parallelen Ausführung (z. B. Synchronisierung) geringer ist als die des seriellen Kollektors. Nicht nur bei Verwendung eines einzelnen Prozessors, sondern auch bei Verwendung eines Heaps mit geringerer Kapazität oder sogar bei Verwendung von zwei Prozessoren ist die Leistung von ParNew nicht unbedingt höher als die von Serial.
Anwendbares Szenario: Auf einem mittleren bis großen Heap und das System verfügt über mindestens einen Prozessor
Parameter aktivieren: -XX:+UseParNewGC

Parallel Scavenge Garbage Collector

Dieser Collector ist fast identisch mit ParNew. Beide sind parallele Kollektoren, die für die neue Generation entwickelt wurden und Replikationsalgorithmen verwenden. Der größte Unterschied zu ParNew besteht darin, dass die einstellbaren Parameter unterschiedlich sind, was uns eine genauere Steuerung der GC-Pausenzeit und des Durchsatzes ermöglicht.
Zu den vom Parallel Scavenge Collector bereitgestellten Parametern gehören hauptsächlich die Steuerung der maximalen Pausenzeit (mithilfe von -XX:MaxGCPauseMillis=) und die Steuerung des Durchsatzes (mithilfe von -XX:GCTimeRatio=). Daraus ist ersichtlich, dass Parallel Scavenge ein Kollektor ist, der eine Durchsatzkontrolle ermöglicht.
Aber denken Sie nicht, dass je kleiner die maximale Pausenzeit, desto besser oder je größer der Durchsatz, desto besser. Bei der Verwendung des Parallel-Scavenge-Kollektors gibt es drei Hauptleistungsindikatoren: maximale Pausenzeit, Durchsatz und Neues Erzeugungsbereich.
Der parallele Scavenge-Kollektor verfügt über eine entsprechende Anpassungsstrategie. Er gibt dem Erreichen des Ziels der maximalen Pausenzeit Priorität, gefolgt vom Durchsatz und schließlich dem Minimalwert des neuen Generationsbereichs.
Wenn Sie also die maximale Pausenzeit zu klein einstellen, opfern Sie den Gesamtdurchsatz und die Größe der neuen Generation, um Ihre egoistischen Wünsche zu befriedigen. Die Handflächen und Handrücken sind voller Fleisch, deshalb sollten wir das besser nicht tun. Parallel Scavenge verfügt jedoch über einen Parameter, der es dem Parallel Scavenge Collector ermöglicht, die Anpassung der Speicherbereichsgröße vollständig zu übernehmen. Dazu gehört auch das Alter der Heraufstufung auf die alte Generation (kann mit -XX:MaxTenuringThreshold=n angepasst werden). Verwenden Sie also -XX: UseAdaptiveSizePolicy aktiviert die Richtlinie zur adaptiven Speicherbereichsgröße.
Der parallele Scavenge-Kollektor kann mit dem Parameter -XX:+UseParallelGC aktiviert werden. Er ist auch der Standard-Kollektor der neuen Generation im Servermodus.

Parallel Old Garbage Collector

Die Beziehung zwischen Parallel Old und ParNew oder Parallel Scavenge ist wie bei Serial und Serial Old. Der Unterschied zwischen ihnen ist nicht groß, aber Parallel Old ist es für ältere Menschen ist lediglich ein paralleler Kollektor, der in modernen Zeiten entwickelt wurde und daher einen Markierungs-/Sortierungsalgorithmus verwendet.
Eine weitere wichtige Bedeutung des Parallel Old Collectors besteht darin, dass er neben Serial Old der einzige Collector der alten Generation ist, der mit Parallel Scavenge arbeiten kann. Um zu verhindern, dass Serial Old den Ruf des kontrollierbaren Durchsatzes von Parallel Scavenge beeinträchtigt, wird parallel vorgegangen old dient als echter Partner der parallelen Aufräumaktion.
Es kann mit dem Parameter -XX:-UseParallelOldGC aktiviert werden, aber nach JDK6 ist es nach dem Aktivieren des parallelen Aufräumens auch der Standard-Collector der alten Generation.

Concurrent Mark Sweep Garbage Collector

Der Concurrent Mark Sweep (im Folgenden als CMS bezeichnet) Collector ist der einzige, der Anwendungen und GC-Threads wirklich so implementiert, dass sie zusammenarbeiten (zusammen für Kunden). stimmt nicht unbedingt zusammen, es kann sich um einen schnell wechselnden Kollektor handeln.
CMS ist ein Collector, der für die alte Generation entwickelt wurde und einen Mark/Clear-Algorithmus verwendet. Es ist auch der einzige Collector, der einen Mark/Clear-Algorithmus der alten Generation verwendet.
Der Mark/Clear-Algorithmus wird aufgrund seiner speziellen Verarbeitungsmethode verwendet, die in vier Stufen unterteilt ist.
1. Erstmarkierung: Es ist notwendig, die Anwendung zu unterbrechen und die überlebenden Objekte schnell zu markieren.
2. Gleichzeitige Markierung: Stellen Sie die Anwendung wieder her und verfolgen Sie GC Roots gleichzeitig.
3. Erneut markieren: Sie müssen die Anwendung anhalten und die von der Verfolgung übersehenen Objekte erneut markieren.
4. Gleichzeitiges Löschen: Stellen Sie die Anwendung wieder her und löschen Sie nicht markierte Müllobjekte gleichzeitig.
Er ist etwas komplizierter als der ursprüngliche Markierungs-/Löschalgorithmus und zeigt sich hauptsächlich in den beiden Phasen der gleichzeitigen Markierung und des gleichzeitigen Löschens. Diese beiden Phasen sind jedoch auch die zeitaufwändigsten Phasen in der gesamten GC-Phase. aufgrund dieser beiden Phasen werden gleichzeitig mit der Anwendung ausgeführt, sodass die vom CMS-Kollektor verursachte Pausenzeit sehr kurz ist. Das ist relativ einfach zu verstehen.
Allerdings sollten die Mängel kurz erwähnt werden, die wichtigsten sind wie folgt.

1. Da der GC-Thread und das Anwendungsprogramm bei gleichzeitiger Ausführung CPU-Ressourcen beanspruchen, verringert sich der Gesamtdurchsatz. Mit anderen Worten: In Bezug auf die Durchsatzindikatoren ist der CMS-Kollektor schwächer als der Parallel-Scavenge-Kollektor. LZ ist hier ein Auszug aus einer Beschreibung des CMS von der offiziellen Website von Oracle, in der die Beziehung zwischen der CMS-Leistung und der Anzahl der CPUs erwähnt wird.
Da während der gleichzeitigen Phasen mindestens ein Prozessor für die Garbage Collection verwendet wird, bietet der gleichzeitige Collector auf einem Uniprozessor-Rechner (Single-Core) normalerweise keinen Vorteil. Es ist jedoch ein separater Modus verfügbar, der niedrige Pausen erreichen kann auf Systemen mit nur einem oder zwei Prozessoren; Einzelheiten siehe unten im Inkrementalmodus.

LZs Englisch ist sehr durchschnittlich (ich habe Level 4 nicht bestanden, schade, 0,0), aber ich kann es mit der Hilfe grob übersetzen von Werkzeugen Die Bedeutung dieser Passage ist wie folgt.
Chinesisches Wesentliches: Da die Garbage Collection in der gleichzeitigen Phase mindestens einen Prozessor verwendet, werden Sie keinen Nutzen aus der Verwendung eines gleichzeitigen Collectors auf einem einzelnen Prozessor ziehen. Es gibt jedoch eine unabhängige Möglichkeit, auf Ein- oder Zwei-Prozessor-Systemen effektiv niedrige Pausen zu erreichen. Weitere Informationen finden Sie weiter unten im Inkrementalmodus.
Offensichtlich weist die Dokumentation von Oracle darauf hin, dass im Fall eines einzelnen Prozessors der gleichzeitige Kollektor aufgrund der Vorbelegung des Prozessors zu Leistungseinbußen führt. Abschließend wird eine Möglichkeit zum Umgang mit dem inkrementellen Modus angegeben, im Buch „In-Depth Understanding of the JAVA Virtual Machine“ wird jedoch darauf hingewiesen, dass der inkrementelle Modus als nicht empfohlen definiert wurde. Da die offizielle Einführung von LZ auf der Einführung von JDK5.0 basiert und sich das Buch „In-Depth Understanding of JAVA Virtual Machine“ auf die Version von JDK6.0 bezieht, vermutet LZ vorläufig, dass der inkrementelle Modus in JDK6 liegt. 0 Es wurde zum Zeitpunkt seiner Veröffentlichung aufgegeben, aber der Zeitpunkt oder die Version dieses Abbruchs ist eigentlich nicht mehr wichtig.
2. Ein großer Nachteil von Mark/Clear ist die Existenz einer Speicherfragmentierung. Daher stellt die JVM den Parameter -XX:+UseCMSCompactAtFullCollection zur Durchführung der Defragmentierung nach dem globalen GC (vollständiger GC) bereit. Da sich die Defragmentierung nach jedem globalen GC stark auf die Pausenzeit auswirkt, stellt die JVM auch den Parameter -XX:CMSFullGCsBeforeCompaction zur Verfügung, um dies zu steuern Defragmentierung nach mehreren globalen GCs.
3. Das letzte Manko von CMS beinhaltet einen Begriff: Concurrent Mode Failure. Dies ist die offizielle Erklärung für diesen Begriff.
Wenn der gleichzeitige Collector nicht in der Lage ist, die Rückgewinnung der nicht erreichbaren Objekte abzuschließen, bevor die Tenured-Generation voll ist, oder wenn eine Zuweisung mit den verfügbaren freien Speicherplatzblöcken in der Tenured-Generation nicht erfüllt werden kann, wird die Anwendung angehalten und die Sammlung mit allen abgeschlossen Anwendungsthreads wurden gestoppt. Die Unfähigkeit, eine Sammlung gleichzeitig abzuschließen, wird als Fehler im gleichzeitigen Modus bezeichnet und weist darauf hin, dass die Parameter des gleichzeitigen Kollektors angepasst werden müssen.
Chinesische Bedeutung: Wenn der gleichzeitige Kollektor nicht abgeschlossen werden kann, bevor die alte Generation gefüllt ist, ist dies der Fall Nicht erreichbares (nicht erreichbares) Objektrecycling oder der tatsächliche freie Speicherplatz in der alten Generation kann eine bestimmte Speicherzuweisungsanforderung nicht erfüllen. Zu diesem Zeitpunkt wird die Anwendung angehalten und die Speicherbereinigung wird während dieses Suspendierungszeitraums nicht gestartet fortgesetzt, bis das Recycling abgeschlossen ist. Dieser Fehler beim gleichzeitigen Abschluss der Sammlung wird als Fehler im gleichzeitigen Modus bezeichnet. Das Auftreten dieser Situation bedeutet auch, dass wir die Parameter des gleichzeitigen Kollektors anpassen müssen.
Die beiden oben genannten Situationen wirken ein wenig repetitiv. Ist die Nichterfüllung der Speicherzuweisungsanforderung nicht darauf zurückzuführen, dass das Objektrecycling nicht abgeschlossen werden konnte, bevor die alte Generation aufgefüllt ist?
LZs persönliches Verständnis hier ist, dass die Unfähigkeit, das Objektrecycling abzuschließen, bevor die alte Generation aufgefüllt ist, dazu führt, dass die alte Generation während der gleichzeitigen Löschphase nicht rechtzeitig gelöscht wird, was zu unzureichendem freien Speicher führt. Die Unfähigkeit, Speicherzuweisungsanforderungen zu erfüllen, hängt hauptsächlich damit zusammen, dass einige Zuweisungen nicht erfüllt werden können, wenn die neue Generation zur alten Generation heraufgestuft wird, da zu viele Speicherfragmente in der alten Generation vorhanden sind.
Wenn der gleichzeitige Modus fehlschlägt, wird Serial Old als alternativer Kollektor verwendet, um eine globale GC (Full GC) durchzuführen, sodass Serial Old auch als „Ersatz“ für CMS angesehen werden kann. Offensichtlich wird durch das Eingreifen von Serienaltgeräten eine große Pausenzeit verursacht.
Um Fehler im gleichzeitigen Modus so weit wie möglich zu vermeiden, können wir den Parameter -XX:CMSInitiatingOccupancyFraction= anpassen, um zu steuern, wie viel Speichernutzung die alte Generation erreicht (N %), und dann den gleichzeitigen Modus starten Sammler beginnt mit dem Recycling der alten Generation.

Die Kraft der Kombinationen

Wir haben oben die Eigenschaften jedes Kollektors kurz vorgestellt. Nachfolgend stellt LZ Ihnen drei typische Kombinationen vor. Die anderen drei Kombinationen werden im Allgemeinen nicht häufig verwendet.

seriell & seriell alt

Diese Kombination ist eine unserer häufigsten Kombinationen und auch die Standard-Garbage-Collector-Kombination im Client-Modus. Sie können zum Erzwingen auch den Parameter -XX:+UseSerialGC verwenden es an.
Da es relativ einfach zu implementieren ist und keinen zusätzlichen Thread-bezogenen Overhead hat (hauptsächlich Thread-Umschaltung und -Synchronisierung), eignet es sich sehr gut für kleine Anwendungen, die auf dem Client-PC ausgeführt werden, oder für Desktop-Anwendungen (z. B. in geschriebene Benutzeroberflächenprogramme). Swing) sowie unsere übliche Entwicklung, Fehlerbehebung, Tests usw.
Die oben genannten drei Situationen haben alle gemeinsame Merkmale.
1. Da sie alle auf dem PC ausgeführt werden, ist die Konfiguration im Allgemeinen nicht zu hoch bzw. die Anzahl der Prozessoren ist nicht zu hoch.
2. Die Anwendungen werden in den oben genannten Situationen nicht zu lange ausgeführt.
3. Der Maßstab wird nicht zu groß sein, das heißt, der Heap wird relativ klein sein, die Sammlung wird schneller sein und die Pausenzeit wird kürzer sein.

Parallel Scavenge & Parallel Old

Diese Kombination kommt in unserer üblichen Entwicklung nicht vor, aber es ist eine Kombination, die einen hohen Durchsatz erfordert Wahl für Anwendungen, die keine hohe Pausenzeit (Pausenzeit) erfordern, und diese Kombination ist die Standardkombination im Servermodus (JDK6 oder nach JDK6). Natürlich kann es auch mit dem Parameter -XX:+UseParallelGC zwangsweise aktiviert werden.
Diese Kombination nutzt die parallele Sammlung sowohl in der neuen als auch in der alten Generation, sodass die Pausenzeit kürzer und der Gesamtdurchsatz des Systems höher ist. Es eignet sich für einige Hintergrundprogramme, die über einen längeren Zeitraum ausgeführt werden müssen und bestimmte Durchsatzanforderungen haben.
Diese im Hintergrund laufenden Programme weisen die folgenden Eigenschaften auf.
1. Die Systemkonfiguration ist relativ hoch, normalerweise mindestens vier Kerne (basierend auf dem aktuellen Hardware-Level).
2. Die Durchsatzanforderungen sind hoch oder es muss ein bestimmter Wert erreicht werden.
3. Die Ausführung der Anwendung dauert lange.
4. Die Anwendungsgröße ist groß, normalerweise ein mittlerer bis großer Heap.

ParNew & CMS (Serial Old als Ersatz)

Diese Kombination ist die gleiche wie die oben genannte Parallelkombination. Sie ist in der täglichen Entwicklung nicht üblich und für die Reaktionszeit die erste Wahl für anspruchsvollere Anwendungen. Diese Kombination muss mit dem Parameter -XX:+UseConcMarkSweepGC aktiviert werden.
Diese Kombination verwendet einen Parallelkollektor der neuen Generation, sodass die GC-Geschwindigkeit der neuen Generation sehr hoch und die Pausenzeit sehr kurz ist. Der GC der jungen Generation verwendet die gleichzeitige Sammlung. Während des größten Teils der Garbage Collection wird der GC-Thread gleichzeitig mit der Anwendung ausgeführt, sodass die Pausenzeit immer noch sehr kurz ist. Es eignet sich für einige Hintergrundprogramme, die über einen längeren Zeitraum ausgeführt werden müssen und bestimmte Anforderungen an die entsprechende Zeit stellen.
Die Eigenschaften dieser im Hintergrund ausgeführten Programme sind den Hintergrundprogrammen im Parallelmodus sehr ähnlich. Der zweite Punkt ist, dass Hintergrundanwendungen, die die Kombination von ParNew und CMS verwenden, im Allgemeinen bestimmte Anforderungen haben Dies ist unsere WEB-Anwendung.

Fazit

Diesmal hat LZ die Eigenschaften jedes Kollektors und die Eigenschaften jeder Kombination geklärt. Darüber hinaus gibt es drei verbleibende Kombinationen, die LZ hier nicht erwähnt hat. Der Grund dafür ist, dass diese drei Kombinationen nicht besonders häufig verwendet werden sagte, dass diese drei Kombinationen den Menschen alle ein unterschiedliches Gefühl geben und die Wirkung tatsächlich nicht gut ist.
Ich hoffe, dieser Artikel kann Ihnen helfen, vielen Dank fürs Zuschauen.

Das Obige ist der Inhalt der JVM-Speicherverwaltung ------ Verfeinerung des Garbage Collectors (damit Sie problemlos in der Welt des Garbage Collectors spielen können. Weitere verwandte Inhalte finden Sie in PHP). Chinesische Website (www.php.cn)!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn