Eingehende Analyse des G1-Garbage Collectors und Leistungsoptimierung

In diesem Artikel werden die Parameterkonfiguration des G1-Garbage Collectors, die Durchführung der Leistungsoptimierung sowie die Analyse und Bewertung der GC-Leistung ausführlich vorgestellt.

0. Einführung in G1

Der vollständige Name von G1 lautet Garbage First Garbage Collector . Dabei handelt es sich um einen serverseitigen Garbage Collector, der in der HotSpot-JVM integriert ist.
G1 verwendet den [Generierungsalgorithmus], um den GC-Prozess in mehrere gleichzeitige und parallele Phasen zu zerlegen und die Pausenzeit aufzuteilen, wodurch niedrige Latenzeigenschaften erreicht und ein guter Durchsatz aufrechterhalten werden.
Solange G1 glaubt, dass eine Speicherbereinigung durchgeführt werden kann, wird ein GC ausgelöst. Natürlich wird G1 der Wiederherstellung von Bereichen mit weniger überlebenden Daten Priorität einräumen.
Weniger überlebende Daten bedeuten mehr Müllobjekte im Inneren, was auch der Ursprung des Namens Garbage First ist.

Der Garbage Collector ist im Wesentlichen ein Speicherverwaltungstool. Der G1-Algorithmus implementiert die automatische Speicherverwaltung hauptsächlich auf folgende Weise:

  • [Generation] Weisen Sie der jungen Generation neue Objekte zu, und Objekte, die ein bestimmtes Alter erreichen, werden zur alten Generation befördert.
  • [Parallelität] Durchlaufen Sie alle überlebenden Objekte der alten Generation während der gleichzeitigen Markierungsphase. Immer wenn die Gesamtnutzung des Heap-Speichers in Java einen Schwellenwert überschreitet, löst HotSpot einen Markierungszyklus aus.
  • [Organisation] Organisieren Sie verbleibende Objekte durch paralleles Kopieren, um verfügbaren Speicher freizugeben.

In GC bezieht sich parallel (parallel) auf die Zusammenarbeit mehrerer GC-Threads, und gleichzeitig (concurrent) bezieht sich auf die gleichzeitige Ausführung von GC-Threads und Geschäftsthreads.

In diesem Artikel wird zunächst kurz erläutert, wie G1-Parameter konfiguriert werden, und anschließend wird erläutert, wie die GC-Leistung analysiert und bewertet wird.
Wenn Sie eine GC-Optimierung durchführen möchten, müssen Sie zumindest über ein gewisses Verständnis des Garbage-Collection-Mechanismus von Java verfügen .

G1 ist ein inkrementeller Generations-Garbage Collector. Was ist ein Inkrement?
G1 unterteilt den Heap-Speicher in viele [kleine Bereiche, kleine Blöcke] (Regionen) gleicher Größe.
Beim Start der JVM wird die Größe jeder Region entsprechend der Konfiguration des Heap-Speichers bestimmt. Die Größe der Region beträgt 1MBbis zu 32MB, und die Gesamtzahl überschreitet im Allgemeinen nicht 2048.

In G1 sind die neue Generation (Eden), der Überlebensbereich (Survivor) und die alte Generation (alte Generation) logische Konzepte, die aus diesen Regionen bestehen, und diese Regionen müssen nicht kontinuierlich sein.

https://img-blog.csdn.net/20170205235146220

Sie können Parameter festlegen, um die „erwartete maximale Pausenzeit“ anzugeben, und G1 versucht, diesen weichen Echtzeitzielwert zu erreichen.
Während der Speicherbereinigung im [reinen jungen Modus (jung)] kann G1 die Größe der jungen Generation (eden + survivor) dynamisch anpassen, um diese weiche Echtzeit-Zielpausenzeit zu erreichen.
Im [gemischten Modus (gemischt)] Garbage Collection-Prozess kann G1 die Anzahl der Altersregionen, die in diesem GC recycelt werden müssen, abhängig von der [Gesamtzahl der zu recycelnden Regionen] und [dem Prozentsatz der Überlebenden] anpassen Objekte in jeder Region] und [Verhältnis der zulässigen Verschwendung von Heap-Speicher] und anderen Daten.

G1 verwendet [Inkrementelle Parallelkopie], um die [Heap-Speicher-Defragmentierungsfunktion] zu implementieren, und kopiert die verbleibenden Objekte in der Sammlung in die neue Region. Die Gruppe der beteiligten Regionen.
Das Ziel besteht darin, so viel Heap-Speicher wie möglich aus freien Regionen zurückzugewinnen und gleichzeitig zu versuchen, die gewünschte Pausenzeitmetrik zu erreichen.

G1 richtet für jede Region einen separaten [Speichersatz] ein. Der englische Name ist Remembered Set, kurz RSet, der zum Verfolgen und Aufzeichnen von Referenzen aus anderen Regionen auf diese Region dient.
Durch diese Regionsaufteilung und die unabhängige RSet-Datenstruktur kann G1 parallel eine inkrementelle Speicherbereinigung durchführen, ohne den gesamten Heap-Speicher zu durchlaufen.
Da Sie nur das RSet scannen müssen, können Sie wissen, welche regionsübergreifenden Referenzen auf diese Region verweisen, und diese Regionen dann recyceln.
G1 verwendet [Post-Write-Barriere] (Post-Write-Barriere), um die Änderungsinformationen des Heap-Speichers aufzuzeichnen und ist für die Aktualisierung von RSet verantwortlich.

1. Einführung in die Garbage-Collection-Phase

Beim reinen Young-Generation-Modus-GC des G1-Garbage Collectors und beim Mixed-Mode-GC gibt es neben der STW-Phase der Transferpause (Evakuierungspause) parallele, gleichzeitige Markierungszyklen, die aus mehreren Unterphasen bestehen.
G1 verwendet den Start-Snapshot-Algorithmus (SATB, Snapshot-At-The-Beginning), um zu Beginn des Markierungszyklus einen Snapshot der verbleibenden Objektinformationen im Heap-Speicher zu erstellen.
Die Gesamtzahl der überlebenden Objekte umfasst dann die überlebenden Objekte im Start-Snapshot sowie neu erstellte Objekte seit Beginn der Markierung.
Der Markierungsalgorithmus von G1 verwendet [Pre-Write-Barriere] (Pre-Write-Barriere), um Objekte aufzuzeichnen und zu markieren, die logisch zu diesem Snapshot gehören.

2. Garbage Collection im reinen Young-Generation-Modus

G1 sendet die meisten Speicherzuweisungsanforderungen an den Eden-Bereich.
Während des Garbage Collection-Prozesses im Young-Generation-Modus sammelt G1 den Eden-Bereich und den Überlebensbereich, die vom vorherigen GC verwendet wurden.
Und kopieren/übertragen Sie die überlebenden Objekte in einige neue Regionen, wobei das spezifische Kopieren vom Alter der Objekte abhängt;
wenn ein bestimmtes GC-Alter erreicht wird, werden sie an die alte Generation übertragen/befördert, andernfalls werden sie an übertragen der Überlebensbereich.
Der Überlebensbereich wird dieses Mal zum CSet des nächsten GC/Mixed-Mode-GC der jungen Generation hinzugefügt.

3. Garbage Collection im gemischten Modus

Nachdem der gleichzeitige Markierungszyklus ausgeführt wurde, wechselt G1 vom reinen Jugendmodus in den gemischten Modus.
Bei der Durchführung einer Garbage Collection im gemischten Modus wählt G1 einen Teil der Region der alten Generation aus, um ihn der Recycling-Sammlung hinzuzufügen. Natürlich umfasst jede Recycling-Sammlung alle Eden-Bereiche und Überlebensbereiche.
Insbesondere wird später erläutert, wie viele Regionen der alten Generation gleichzeitig hinzugefügt werden und welche Parameter von ihnen bestimmt werden.
Nach mehreren Garbage Collections im gemischten Modus wurden viele Regionen der alten Generation verarbeitet, und dann wechselt G1 zurück in den reinen Modus der jungen Generation, bis der nächste gleichzeitige Markierungszyklus abgeschlossen ist.

4. Phasen des Markierungszyklus

Der Markierungszyklus von G1 besteht aus folgenden Phasen:

  • [Erste Markierungsphase] ( Initial mark phase): Die Markierung der GC-Wurzeln in dieser Phase wird normalerweise zusätzlich zu einer regulären GC der jungen Generation durchgeführt.
  • [Scannen Sie den Bereich, in dem sich die GC-Wurzel befindet] ( Root region scanning phase): Scannen Sie entsprechend den in der anfänglichen Markierungsphase ermittelten GC-Wurzelelementen den Bereich, in dem sich diese Elemente befinden, erhalten Sie Verweise auf die alte Generation und markieren Sie die referenzierten Objekte. Diese Phase wird gleichzeitig mit Anwendungsthreads, also ohne STW-Pausen, ausgeführt und muss abgeschlossen sein, bevor der nächste GC der jungen Generation startet.
  • [Gleichzeitige Markierungsphase] ( Concurrent marking phase)“: Durchlaufen Sie den gesamten Heap, um alle erreichbaren überlebenden Objekte zu finden. Diese Phase wird gleichzeitig mit dem Anwendungsthread ausgeführt und darf auch vom GC der jungen Generation unterbrochen werden.
  • 【Neumarkierungsphase】( Remark phase): In dieser Phase gibt es eine STW-Pause, um den Markierungszyklus abzuschließen. G1 löscht den SATB-Puffer, verfolgt unerreichte überlebende Objekte und führt eine Referenzverarbeitung durch.
  • 【Bereinigungsphase】( Cleanup phase): Dies ist die letzte Unterphase. G1 wird eine STW-Pause haben, wenn Statistiken durchgeführt und RSet bereinigt werden. Während des statistischen Prozesses werden vollständig inaktive Regionen markiert, und auch Kandidatenregionen, die für Mixed-Mode-GC geeignet sind, werden markiert. Ein Teil der Bereinigungsphase wird gleichzeitig durchgeführt, beispielsweise wenn freie Regionen zurückgesetzt und zur freien Liste hinzugefügt werden.

5. Allgemeine Parameter und Standardwerte

G1 ist ein adaptiver Garbage Collector. Die meisten Parameter haben Standardwerte. Im Allgemeinen kann er ohne große Konfiguration effizient ausgeführt werden.
Nachfolgend sind häufig verwendete Parameter und entsprechende Standardwerte aufgeführt. Bei besonderen Anforderungen können Sie die JVM-Startparameter anpassen, um bestimmte Leistungsindikatoren zu erfüllen.

-XX:G1HeapRegionSize=n

Wird verwendet, um die Größe der G1-Region festzulegen. Muss 2的幂(Potenz von x) sein, zulässiger Bereich ist 1MBbis 32MB. Der Standardwert dieses Parameters wird dynamisch entsprechend der Anfangsgröße ( ) und dem Maximalwert ( )
des Heap-Speichers angepasst , um den Heap-Speicher in etwa 2048 Bereiche zu unterteilen.-Xms-Xmx

-XX:MaxGCPauseMillis=200

Die gewünschte maximale Pausenzeit. Der Standardwert beträgt 200 Millisekunden. Dieser Wert wird nicht automatisch angepasst, es handelt sich um den beim Start eingestellten Wert.

-XX:G1NewSizePercent=5

Legen Sie das minimale Speicherplatzverhältnis der jungen Generation fest. Der Standardwert 5entspricht mindestens 5 % des Heap-Speichers, der von der jungen Generation verwendet wird.
Dieser Parameter überschreibt -XX:DefaultMinNewGenPercent.
Dies ist ein experimenteller Parameter und kann sich in nachfolgenden Versionen ändern.

-XX:G1MaxNewSizePercent=60

Stellen Sie das maximale Raumverhältnis der jungen Generation ein. Der Standardwert 60entspricht maximal 60 % des Heap-Speichers, der als junge Generation verwendet wird.
Diese Einstellung hat Vorrang -XX:DefaultMaxNewGenPercent.
Dies ist ein experimenteller Parameter und kann sich in nachfolgenden Versionen ändern.

-XX:ParallelGCThreads=n

Legen Sie die Anzahl der parallelen Arbeitsthreads in der STW-Phase fest.

  • Wenn die Anzahl der logischen Prozessoren kleiner oder gleich 8 ist, nentspricht sie standardmäßig der Anzahl der logischen Prozessoren.
  • Wenn die Anzahl der logischen Prozessoren größer als 8 ist, nentspricht der Standardwert ungefähr der Anzahl der Prozessoren 5/8+ 3.
  • Wenn es sich um ein SPARC-System mit hoher Konfiguration handelt, nentspricht der Standardwert ungefähr der Anzahl der logischen Prozessoren 5/16.
  • Verwenden Sie in den meisten Fällen den Standardwert.
  • Es gibt eine Ausnahme: Im Docker-Container wird eine niedrige Version von JDK verwendet. Als Fallreferenz: JVM-Fehlerbehebung und -Analyse Teil II (Fallkampf) .

-XX:ConcGCThreads=n

Legt die Anzahl der GC-Threads für die gleichzeitige Markierung fest. Der Standardwert entspricht ungefähr ParallelGCThreadsdem Wert von 1/4.

-XX:InitiatingHeapOccupancyPercent=45

Legt den Auslöseschwellenwert für den Markierungszyklus fest, der den Prozentsatz der Java-Heap-Speichernutzung darstellt. Der Standard-Triggerschwellenwert ist der gesamte Java-Heap 45%.

-XX:G1MixedGCLiveThresholdPercent=65

Bestimmen Sie bei der Durchführung von Mixed-Mode-GC anhand der Nutzungsrate der Region der alten Generation, ob diese in die Sammlung aufgenommen werden soll. Der Schwellenwert ist standardmäßig auf 65%.
Diese Einstellung hat Vorrang -XX:G1OldCSetRegionLiveThresholdPercent.
Dies ist ein experimenteller Parameter und kann sich in nachfolgenden Versionen ändern.

-XX:G1HeapWastePercent=10

Legt den tolerierbaren Prozentsatz der Heap-Speicherverschwendung fest.
Wenn das Verhältnis des wiederverwendbaren Heap-Speichers unter diesem Schwellenwert liegt, startet HotSpot keine GC im gemischten Modus.
Der Standardwert ist 10%.

-XX:G1MixedGCCountTarget=8

Wie viele Mixed-Mode-GCs werden voraussichtlich ausgeführt, nachdem ein Markierungszyklus abgeschlossen ist, bis der Anteil der Live-Daten unter fällt G1MixedGCLiveThresholdPercent.
Standardmäßig werden 8 Mixed-Mode-GCs durchgeführt. Die Anzahl der konkreten Ausführungen liegt im Allgemeinen unter diesem Wert.

-XX:G1OldCSetRegionThresholdPercent=10

Bei der Mixed-Mode-GC ist dies die Obergrenze für die Anzahl der jeweils verarbeiteten alten Regionen. Der Standardwert ist der Java-Heap 10%.

-XX:G1ReservePercent=10

Legen Sie einen bestimmten Prozentsatz des reservierten Speicherplatzes fest, um ihn freizuhalten und to空间das Risiko von unzureichendem Speicher zu verringern. Der Standardwert ist 10%.
Obwohl es sich um einen Prozentsatz handelt, wird er tatsächlich einer bestimmten Größe zugeordnet. Wenn Sie also den Prozentsatz erhöhen oder verringern, ist es am besten, die Gesamtgröße des Java-Heaps um dieselbe Größe anzupassen.

6. So entsperren Sie experimentelle JVM-Parameter

Um den Wert eines experimentellen JVM-Parameters zu ändern, muss dieser zunächst deklariert werden.
Wir können es explizit in den Befehlszeilenparametern angeben, bevor wir die experimentellen Parameter festlegen -XX:+UnlockExperimentalVMOptions. Zum Beispiel:

java -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=10 -XX:G1MaxNewSizePercent=75 G1test.jar

7. Best Practices und Empfehlungen

Bevor Sie die G1-Parameter anpassen, sollten Sie einige Dinge beachten:

  • 禁止设置年轻代的大小: Verwenden Sie keine Optionen wie -Xmn, -XX:NewRatiousw., um die Größe der jungen Generation anzugeben. Wenn Sie eine feste Größe für die junge Generation angeben, überschreiben Sie das maximale Pausenzeitziel, das den Gewinn überwiegt.
  • 期望的最大暂停时间值: Unabhängig davon, welcher Garbage Collector optimiert ist, gibt es einen Kompromiss zwischen Latenz- und Durchsatzmetriken.
    G1 ist ein inkrementeller Garbage Collector mit einheitlicher Pausenzeit, sodass der Overhead für die CPU-Ressourcen relativ groß ist. Das Durchsatzziel von G1 bezieht sich darauf, sicherzustellen, dass Anwendungsthreads in Hochlastszenarien mehr als 90 % der CPU-Zeit beanspruchen und der Overhead von GC-Threads unter 10 % gehalten wird.
    Im Gegensatz dazu kann der integrierte Garbage Collector mit hohem Durchsatz in HotSpot auf 99 % der Anwendungs-Thread-Zeit optimiert werden, was bedeutet, dass weniger als 1 % des GC-Overheads anfällt.
    Daher muss bei der Messung des Durchsatzindex von G1 der Pausenzeitindex gelockert werden. Das Festlegen eines zu kleinen Pausenzeitziels bedeutet, dass Sie bereit sind, einen großen GC-Overhead in Kauf zu nehmen, der sich jedoch auf den Durchsatz auswirkt. Beim Stresstest des Latenzindex von G1 können Sie den erwarteten weichen Echtzeit-Pausenzeitindex festlegen, und G1 wird sein Bestes geben, um dieses Ziel zu erreichen. Der Nebeneffekt ist, dass der Durchsatz leidet.
  • Bei den meisten serverseitigen Anwendungen wird die CPU-Auslastung 50 % nicht überschreiten. Selbst wenn der GC etwas mehr CPU belegt, hat dies keine großen Auswirkungen, da immer noch viele Redundanzen vorhanden sind. Wir achten mehr auf die Pausenzeit des GC, weil es hängt mit Antwortlatenzmetriken zusammen.
  • 混合模式的GC: Beim Optimieren eines Mixed-Mode-GC können die folgenden Optionen ausprobiert werden. Einzelheiten zu diesen Optionen finden Sie in den vorherigen Abschnitten:
    • -XX:InitiatingHeapOccupancyPercent: Legt den Auslöseschwellenwert für den Markierungszyklus fest.
    • -XX:G1MixedGCLiveThresholdPercentund -XX:G1HeapWastePercent: Passen Sie Mixed-Mode-GC-bezogene Strategien an.
    • -XX:G1MixedGCCountTargetund -XX:G1OldCSetRegionThresholdPercentwerden verwendet, um den Anteil der Region der alten Generation im CSet zu optimieren und anzupassen.

8. Meldungen über Speicherüberlauf und Speichererschöpfung im GC-Protokoll

Wenn wir dies in den GC-Protokollen sehen to-space overflow/exhausted, bedeutet das, dass G1 nicht über genügend Speicher verfügt, weder für den Live-Bereich noch für die Objekte, die hochgestuft werden müssen, oder für beides. Zu diesem Zeitpunkt hat der Java-Heapspeicher im Allgemeinen den Maximalwert erreicht und kann nicht automatisch erweitert werden. Beispiele sind wie folgt:

924.897: [GC pause (G1 Evacuation Pause) (mixed) (to-space exhausted), 0.1957310 secs]

oder dieses:

924.897: [GC pause (G1 Evacuation Pause) (mixed) (to-space overflow), 0.1957310 secs]

Um solche Probleme zu beheben, können Sie die folgenden Anpassungen ausprobieren:

  • Erhöhen Sie -XX:G1ReservePercentden Wert der Option, um die reservierte „to-space“-Größe zu erhöhen. Im Allgemeinen muss die Gesamtgröße des Heap-Speichers entsprechend erhöht werden.
  • Senken Sie den Wert -XX:InitiatingHeapOccupancyPercent, um Markierungszyklen früher auszulösen.
  • Erhöhen Sie den Wert der Option entsprechend, -XX:ConcGCThreadsum die Anzahl gleichzeitiger Markierungsthreads zu erhöhen.

Spezifische Informationen zu diesen Optionen finden Sie in der vorherigen Beschreibung.

9. Speicherzuweisung für große Objekte/riesige Objekte

Wenn ein Objekt die Hälfte eines einzelnen Regionsraums überschreitet, wird es von G1 als Humongous-Objekt betrachtet. Zum Beispiel ein sehr großes Array oder String.
Solche Objekte werden direkt der „Humongous-Region“ der alten Generation zugeordnet. Eine große Objektregion ist eine Gruppe zusammenhängender Regionen im virtuellen Adressraum. StartsHumongousMarkiert die erste Region und ContinuesHumongousmarkiert die nachfolgende Gruppe von Regionen.

Bevor große Objektbereiche zugewiesen werden, ermittelt G1 zunächst, ob der Schwellenwert für den Start des Markierungszyklus erreicht ist, und startet bei Bedarf einen gleichzeitigen Markierungszyklus.

Während der Bereinigungsphase am Ende des Markierungszyklus und während der Bereinigung von FullGC werden riesige Objekte freigegeben, die nicht mehr verwendet werden.

Um den Overhead beim Kopieren des Speichers zu reduzieren, komprimieren und organisieren alle Übertragungspause-GCs keine riesigen Objekte. Die vollständige GC organisiert nur die großen Objekte, die vorhanden sind.

Da jede StartsHumongous- und ContinuesHumongous-Sammlung nur ein Humongous-Objekt enthält, wird immer ein Teil des letzten Platzes innerhalb der Sammlung verschwendet.
Wenn der von einem Objekt eingenommene Speicherplatz nur geringfügig größer als N Regionen ist, führt der ungenutzte Teil des Speicherplatzes tatsächlich zu einer Speicherfragmentierung.

Wenn Sie im GC-Protokoll eine große Anzahl gleichzeitiger Zyklen sehen, die durch die Humongous-Zuweisung ausgelöst werden, und in der alten Generation eine große Anzahl von Speicherfragmenten gebildet wird, müssen Sie den Wert erhöhen, damit die vorherigen riesigen Objekte nicht mehr als solche betrachtet werden Riesen -XX:G1HeapRegionSize. Befolgen Sie stattdessen die herkömmliche Objektzuweisungsmethode [solange sie weniger als 50 % der Region ausmacht].

10. Zusammenfassung

G1 ist ein [inkrementeller] Garbage Collector im [parallel + gleichzeitig] Modus, der den Heap-Speicher in viele Bereiche unterteilt. Im Vergleich zu anderen GC-Algorithmus-Implementierungen bietet er vorhersehbarere und genauere Pausenzeiten.
Die inkrementelle Funktion ermöglicht es G1, größere Heap-Speicherplätze zu verarbeiten und dabei im schlimmsten Fall dennoch angemessene Antwortzeiten beizubehalten.

G1 verfügt über selbstadaptive Funktionen. Im Allgemeinen müssen nur drei Tuning-Parameter eingestellt werden:

  • Die gewünschte maximale Pausenzeit, z.B.-XX:MaxGCPauseMillis=50
  • Beispielsweise die maximale Größe des Heap-Speichers-Xmx4g
  • Beispielsweise der Mindestwert des Heap-Speichers-Xms4g

Über den Autor

Monica Beckwith, ein Kernmitglied der Oracle Technical Working Group, ist die Leistungsleiterin für den Garbage First Garbage Collector im Rahmen des Java HotSpot VM-Projekts.
Mehr als 10 Jahre Berufserfahrung im Bereich Performance und Architektur.
Vor Oracle und Sun Microsystems war Monica für die Leistungsoptimierung bei Spansion Inc. verantwortlich.
Monica hat mit vielen Java-basierten Benchmarks zusammengearbeitet, um Leistungsverbesserungen für die Java HotSpot VM zu finden.

Verwandte Ressourcen und Links

Ich denke du magst

Origin blog.csdn.net/renfufei/article/details/108476781
Empfohlen
Rangfolge