2016-07-26 14 views
1

Ich benutze CMS für GC, jedoch wird die CPU-Auslastung nach zwei Monaten sehr hoch sein.Parameter für GC (CMS) anpassen

Es gibt ein Stück GC Protokoll, wenn die Situation schlimmer wurde, können Sie die lange STW finden.

3519696.386: [GC [1 CMS-initial-mark: 8617524K(12582912K)] 17105967K(23907584K), 4.9369140 secs] [Times: user=4.94 sys=0.00, real=4.94 secs] 
3519701.324: [CMS-concurrent-mark-start] 
3519709.419: [CMS-concurrent-mark: 8.096/8.096 secs] [Times: user=16.17 sys=0.00, real=8.09 secs] 
3519709.420: [CMS-concurrent-preclean-start] 
3519709.442: [CMS-concurrent-preclean: 0.023/0.023 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
3519709.442: [CMS-concurrent-abortable-preclean-start] 
CMS: abort preclean due to time 3519714.691: [CMS-concurrent-abortable-preclean: 3.345/5.248 secs] [Times: user=3.36 sys=0.00, real=5.25 secs] 
3519714.692: [GC[YG occupancy: 8489655 K (11324672 K)]3519714.692: [Rescan (parallel) , 8.4072250 secs]3519723.099: [weak refs processing, 0.0000190 secs]3519723.099: [scrub string table, 0.0008130 secs] [1 CMS-remark: 8617524K(12582912K)] 17107180K(23907584K), 8.4081940 secs] [Times: user=65.71 sys=0.15, real=8.41 secs] 
3519723.100: [CMS-concurrent-sweep-start] 
3519725.451: [CMS-concurrent-sweep: 2.350/2.350 secs] [Times: user=2.36 sys=0.00, real=2.35 secs] 
3519725.451: [CMS-concurrent-reset-start] 
3519725.478: [CMS-concurrent-reset: 0.028/0.028 secs] [Times: user=0.03 sys=0.00, real=0.03 secs] 
3519727.480: [GC [1 CMS-initial-mark: 8617522K(12582912K)] 17107229K(23907584K), 4.9378950 secs] [Times: user=4.94 sys=0.00, real=4.94 secs] 
3519732.418: [CMS-concurrent-mark-start] 

Meine GC-Parameter:

java -server -Xmx24g -Xms24g -XX:NewSize=12g -XX:MaxNewSize=12g -XX:+HeapDumpOnOutOfMemoryError -XX:MaxDirectMemorySize=24g -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:ReservedCodeCacheSize=128m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:CMSInitiatingOccupancyFraction=68 

gibt es 9 CPUs und 64G Speicher auf meinem Server installiert.

Können Sie helfen, den entscheidenden Punkt herauszufinden, warum es monatlich schlechter wird?

+0

Haben Sie ein Bild angehängt, um zu sehen, ob Sie ein Leck haben oder das Problem beheben? –

+0

@ ThorbjørnRavnAndersen Gibt es irgendwelche Werkzeuge, um es zu machen? – Junjie

+0

Visualvm ist Teil der jdk-Distribution. –

Antwort

4

Ok, lassen Sie uns ein bisschen im Detail sehen. Ich merke zuerst, dass alle Zeiten in Benutzer zu sein scheinen, nicht in sys, also sind die Hauptverdächtigen die JVM und die Anwendung.

Der GC wird bei alten Gen ausgelöst. Belegung von 8617524K mit einer Kapazität von 12582912K. Die gesamte Heapnutzung beträgt 17105967K, Größe 23907584K.

Anfängliche Markierung dauert ~ 5s.

3519696.386: [GC [1 CMS-initial-mark: 8617524K(12582912K)] 17105967K(23907584K), 4.9369140 secs] [Times: user=4.94 sys=0.00, real=4.94 secs] 

AFAIK die erste Markierung verarbeitet nur GC-Wurzeln. Sie können sehen, welche sind diese here, aber die Tatsache, dass es so viel nimmt, ist seltsam. Mein erster Verdacht wäre, dass diese von Zeit zu Sicherungspunkte beeinflusst wird, so ermöglichen vielleicht:

-XX: + PrintSafepointStatistics -XX: PrintSafepointStatisticsCount = 1

Die gleichzeitige Markierungsphase 8s

3519709.419: [CMS-concurrent-mark: 8.096/8.096 secs] [Times: user=16.17 sys=0.00, real=8.09 secs] 

nimmt Dies ist das Scannen der Live-Objekte

Preclean ist vergleichsweise schnell.

Abortable Preclean wird um 5s abgebrochen, die AFAIK kommt mit CMSMaxAbortablePrecleanTime konfigurierbar. Wenn ich an dieser Option denke, ist es wünschenswert, dass zu diesem Zeitpunkt kleinere Sammlungen vorhanden sind. Wenn dies nicht möglich ist, kann dies zu großen Pausen im CMS führen. Erhöhen Sie diese CMSMaxAbortablePrecleanTime, und aktivieren Sie CMSScavengeBeforeRemark. Schauen Sie sich diesen Beitrag von Jon Masamitsu.

Junge Generation ist bei 8G und Rescanning dauerte 8s, was zu viel scheint. Wieder der gleiche Kommentar. Safepoints.

3519714,692: [GC [YG Belegung: 8.489.655 K (11.324.672 K)] 3519714,692: [Rescan (parallel), 8,4072250 secs] 3519723,099: [schwache refs Verarbeitung, 0,0000190 secs] 3519723,099: [scrub Stringtabelle, 0,0008130 secs] [1 CMS-Bemerkung: 8617524K (12582912K)] 17107180K (23907584K), 8,4081940 sec] [Zeiten: user = 65,71 sys = 0,15, real = 8,41 sec]

Beachten Sie, dass die junge Generation. Größe tatsächlich erhöht während dieser Zeit: 8617524K

Die endgültige Bereinigung bei gleichzeitigem Sweep dauert 2,35 Sekunden, und die Heap-Inhalte scheinen sich nicht wesentlich zu ändern. Sie haben immer noch ungefähr den gleichen Jungen- und Haufenverbrauch.

So ZUSAMMENFASSENDE Ich sehe zwei Punkte:

  • Ihr Haufen groß ist, sind Sie die CMSInitiatingOccupancyFraction erreichen und das Auslösen CMS und viel Zeit scheint auf Scannen Live-Objekte zu gehen. So oder so, überprüfen Sie die Größe mal, um zu sehen, ob dies verbessert werden könnte.
  • GC sammelt nicht wirklich viel, so dass Sie wahrscheinlich in einer dieser Situationen sind:
    • Sie wollen viel langlebiger Objekte halten (z .: a-Cache). In diesem Fall möchten Sie die CMSInitiatingOccuphancyFraction erhöhen (wie Sie erwarten, dass die alte Generation sehr voll wird). Aber achten Sie auch darauf, dass Sie keine mittel- oder kurzlebigen Objekte promoten, da diese letztendlich (in einem Tag oder in 2 Monaten) zu langen GCs führen. Das heißt: Vermeiden Sie Abwanderungen in alten Genen.
    • Sie erzeugen viele kurz- bis mittelfristige Objekte, Sie müssen Werbeaktionen vermeiden. Zuteilungen verringern, Eden erhöhen.

Noch weitere Details über Ihre App etc. würde es auf jeden Fall helfen Nagel besser nach unten. Ich hoffe, das hilft ein bisschen.

1

In Ihren Protokollen sehe ich nicht normale junge GC. CMS Stop-the-World-Phasen sind so angelegt, dass sie auf junge Weltraumsammlungen zurückgreifen, um effektiv zu sein.

3519727.480: [GC [1 CMS-initial-mark: 8617522K(12582912K)] 17107229K(23907584K), 4.9378950 secs] [Times: user=4.94 sys=0.00, real=4.94 secs] 

Hier CMS-initial-mark haben in einem Thread 8,6 GiB jungen Raumes zu scannen. Wenn es direkt nach der jungen GC aufgerufen würde, wäre die junge Weltraumbesetzung um eine Größenordnung kleiner.

Gleiches gilt für CMS-remark.

Junge haben große junge Raum, so dass Sie in der Situation enden, wenn Sie alten Raum häufiger diesen jungen Raum gesammelt wird.

Hier sind einige Möglichkeiten zur Behebung der

  • -XX:CMSWaitDuration=3600000 lassen CMS-initial-mark bis zum nächsten jungen GC zu einer Stunde warten, bis.
  • -XX:+CMSScavengeBeforeRemark lassen Sie CMS-remark zwingen junge Sammlung zu vorhersagbaren Pause Zeiten zu produzieren.
  • Nutzt die neueste Java 8.7, die parallel CMS-initial-mark

Weitere Details hat, sind in this article zur Verfügung.