2017-02-14 3 views
2

Ich habe eine Web-App, die auf Tomcat ausgeführt wird, die Max Heap-Größe auf 8 GB festgelegt hat.Was bewirkt, dass ein vollständiger GC ausgeführt wird?

Folgende sind meine vm args.

export CATALINA_OPTS="$CATALINA_OPTS -Xms512m -Xmx8192m -XX:+UseConcMarkSweepGC" 

Wenn keine Benutzer in der App einloggen, nicht reinigbar Speicher (die nach einer Garbage Collection befindet) ist sehr gering (etwa 1 GB).

In dieser Situation, wenn ich das Speicherwachstum Muster mit jconsole beobachten, sehe ich eine konstante Speichererweiterung für ca. 4 GB und dann Garbage Collector läuft und Speicher wieder auf etwa 1 GB fällt. Dieses Muster wird fortgesetzt, wenn kein Benutzer angemeldet wird.

Wenn ich die GC-Daten protokolliere, beobachte ich etwas wie unten.

2017-02-14T15:30:44.553+0530: 591.922: [GC (Allocation Failure) [PSYoungGen: 1501051K->631966K(1833472K)] 2392189K->1523112K(3030016K), 1.5100144 secs] [Times: user=1.49 sys=0.01, real=1.51 secs] 
2017-02-14T15:31:20.335+0530: 627.705: [GC (Allocation Failure) [PSYoungGen: 1553054K->595007K(1842176K)] 2444200K->1570521K(3038720K), 1.3050284 secs] [Times: user=1.27 sys=0.04, real=1.31 secs] 
2017-02-14T15:33:33.682+0530: 761.052: [GC (Allocation Failure) [PSYoungGen: 1516095K->556800K(1842176K)] 2491609K->1596474K(3038720K), 1.6957154 secs] [Times: user=1.67 sys=0.03, real=1.69 secs] 
2017-02-14T15:33:35.378+0530: 762.748: [Full GC (Ergonomics) [PSYoungGen: 556800K->365446K(1842176K)] [ParOldGen: 1039673K->1196476K(2018304K)] 1596474K->1561923K(3860480K), [Metaspace: 70472K->70472K(1114112K)], 11.2779843 secs] [Times: user=11.13 sys=0.09, real=11.28 secs] 
2017-02-14T15:34:56.232+0530: 843.602: [GC (Allocation Failure) [PSYoungGen: 1286534K->216613K(1842176K)] 2483011K->1609875K(3860480K), 1.4938761 secs] [Times: user=1.45 sys=0.05, real=1.50 secs] 

Wie es zu sehen ist, manchmal ein Voll GC durchgeführt wird, die eine beträchtliche Menge an Zeit (11 Sekunden) im Vergleich zu kleineren GC (ca. 1 Sekunde) stattgefunden hat.

Da alle anderen Threads während GC angehalten werden, reagiert der Server nicht, wenn ein Benutzer versucht, während eines vollständigen GC auf die Webanwendung zuzugreifen.

Was ich wissen wollte ist, was löst diesen Full GC aus? Gemäß dem Protokoll sind geringfügige GC-Ereignisse aufgrund von Zuweisungsfehlern und Full GC ist auf Ergonomics zurückzuführen. Was bedeutet das?

Kann ich in diesem Fall verhindern, dass Full GC auftritt? Es gibt genügend freien Heap-Speicherplatz übrig, und ich möchte Full GC verzögern, bis keine signifikante Speicherreduktion aufgrund von untergeordneten GC auftritt.

+1

Könnten Sie bitte alle GC-relevanten VM-Optionen hinzufügen, die Sie verwenden (Xms, MaxGCPauseMillis, welche Kollektoren, ...) plus den physischen Speicher Ihres Servers. Wenn Sie niedrige Pausenzeiten wünschen, ist das Verzögern der vollen GCs nicht der Weg zu gehen, da die Pausen weniger, aber länger sind. So scheint es, dass Ihr Heap zu groß für die Ziele konfiguriert ist, die Sie erreichen wollen (und Sie verwenden den falschen Collection-Algorithmus). –

+0

@ piet.t, vm Optionen hinzugefügt –

+0

in Frage zu stellen Es ist möglich, dass die Anwendung explizit tut 'System.gc()' ruft irgendwo im Code. Ich habe gesehen, dass der CMS-Sammler ein bisschen verrückt geworden ist und immer einen Stop-the-World-Full-GC nach einem Aufruf von 'System.gc()' ausführt. Sie können den GC dazu veranlassen, solche Aufrufe über die JVM-Option "-XX: + DisableExplicitGC" zu ignorieren. –

Antwort

0

Adressierung Ihres Hauptproblems (Server blockiert wegen übermäßiger Zeit für die Garbage-Collection), kann dies aufgrund falscher Garbage Collector aus irgendeinem Grund verwendet werden. Die Abstimmung der Müllsammlung ist dokumentiert here. Mit Garbage-First collector können Sie jede Pause einstellen, die Sie noch als akzeptabel empfinden (Standard ist 200 ms, das sollte kein großes Problem für einen Server sein).

0

Ich würde Sie auf die Parallel Collector Link verweisen. Die "Ergonomie" ist eine Methode, um den Kollektor automatisch auf das spezifische Verhalten einer Anwendung abzustimmen.

Die meiste Zeit ist die automatische Abstimmung in Ordnung. In Ihrem Fall scheint es, dass es in zu lange GC endet. Sie können es reparieren, indem Sie sich den Parameter des Kollektors anpassen.

Zitiert in der Dokumentation:

Maximum Garbage Collection Pause Zeit

Die maximale Pausenzeit Ziel wird mit der Befehlszeilenoption -XX angegeben: MaxGCPauseMillis =. Dies wird als ein Hinweis interpretiert, dass Pausenzeiten von Millisekunden oder weniger erwünscht sind; Standardmäßig gibt es kein Ziel für die maximale Pausenzeit. Wenn ein Pausenzeitziel angegeben wird, werden die Größe des Heapspeichers und andere Parameter im Zusammenhang mit der Speicherbereinigung so angepasst, dass Garbage Collection-Pausen kürzer als der angegebene Wert bleiben. Diese Anpassungen können dazu führen, dass der Garbage Collector den Gesamtdurchsatz der Anwendung reduziert und das gewünschte Pausenzeitziel nicht immer erreicht werden kann.

Throughput

Das Durchsatz Ziel in Bezug auf die Zeit gemessen wird damit verbracht, die Garbage Collection im Vergleich zu der Zeit außerhalb der Garbage Collection ausgegeben (bezeichnet als Anwendungszeit). Das Ziel wird durch die Befehlszeilenoption -XX: GCTimeRatio = angegeben, die das Verhältnis von Speicherbereinigungszeit zu Anwendungszeit auf 1/(1 +) festlegt.

Zum Beispiel -XX: GCTimeRatio = 19 setzt ein Ziel von 1/20 oder 5% der Gesamtzeit, in der Garbage Collection. Der Standardwert ist 99, was zu einem Ziel von 1% der Zeit bei der Garbage Collection führt.

Fußabdruck

Maximale Heap-Fußabdruck wird mit der Option -Xmx angegeben. Darüber hinaus hat der Kollektor ein implizites Ziel, die Größe des Heaps zu minimieren, solange die anderen Ziele erreicht werden.

+0

-XX: MaxGCPauseMillis sieht für mich wie eine gute Option aus, aber wäre es in der Lage, die Zeit für einen vollständigen GC zu minimieren? In meinem Fall läuft ein kleiner GC ziemlich schnell, aber ein vollständiger GC dauert etwa 10 mal länger. Ich habe Zweifel, ob -XX: MaxGCPauseMillis dies auf etwa 1 Sekunde herunterrechnen könnte. –

+0

@LahiruChandima Nein, natürlich, es wird versuchen, es am besten zu tun, die festgesetzte Zeit zu respektieren, aber es ist nur ein Hinweis. Wenn Sie nach dem Anpassen des GC weiterhin Probleme haben, sollten Sie untersuchen, warum es so viele Objekte im Müll gibt und warum dies nicht in einem kleineren Zeitrahmen möglich ist. –

+0

Ich werde -XX: MaxGCPauseMillis hinzufügen und überprüfen. Tatsächlich glaube ich nicht, dass die höhere Dauer für den vollständigen GC auf die große Anzahl von Objektzählungen zurückzuführen ist. Wie ich durch jconsole beobachtet habe, wenn kleinere GC passiert, entfernt es etwa 3 GB Müll-Objekte in weniger als 2 Sekunden. –

Verwandte Themen