2013-01-15 5 views
7

Ich habe Java-Anwendung, die einen Job mit bestimmten Speicherauslastung macht. Ich bemerkte, dass, wenn ich die Anwendung mit fast 80% der Heap-Setup für junge Generation starten, meine Anwendungen viel schneller als mit Standard 1: 2-Einstellungen. Insbesondere ich starte Jvm mit:Große NewSize von Java-Heap machen Prozess für lange Zeit unpositiv

java -XX:NewSize=10G -XX:+UseParallelOldGC -server -Xmx12G -Xms12G

Der Server mindestens 14 GB freien physischen Speicher hat, so sollte es genug sein, um wie ich glaube, für Java-Heap und ‚andere‘ Raum.

Jetzt passieren Dinge wie diese:

25.289: [GC [PSYoungGen: 7872317K->1058813K(9175040K)] 7872533K->1059029K(11272192K), 0.1876420 secs] [Times: user=1.92 sys=1.01, real=0.18 secs] 
28.918: [GC [PSYoungGen: 8923133K->1091124K(9175040K)] 8923349K->1091340K(11272192K), 0.2206940 secs] [Times: user=1.92 sys=1.70, real=0.22 secs] 
32.946: [GC [PSYoungGen: 8955444K->1060567K(9175040K)] 8955660K->1060783K(11272192K), 0.1804050 secs] [Times: user=2.86 sys=0.01, real=0.18 secs] 
37.166: [GC [PSYoungGen: 8924887K->1080085K(8329344K)] 8925103K->1080301K(10426496K), 0.1891370 secs] [Times: user=3.08 sys=0.01, real=0.19 secs] 
41.326: [GC [PSYoungGen: 8098709K->1088209K(8106880K)] 8098925K->1088425K(10204032K), 0.2284920 secs] [Times: user=3.49 sys=0.04, real=0.23 secs] 
45.779: [GC [PSYoungGen: 8106833K->59784K(8672768K)] 8107049K->1039790K(10769920K), 0.2195770 secs] [Times: user=2.02 sys=1.91, real=0.22 secs] 
49.963: [GC [PSYoungGen: 6953352K->75043K(8689664K)] 7933358K->1062837K(10786816K), 0.0384440 secs] [Times: user=0.63 sys=0.01, real=0.04 secs] 
54.171: [GC [PSYoungGen: 6968611K->140387K(8737984K)] 7956405K->1129497K(10835136K), 0.0715690 secs] [Times: user=1.12 sys=0.00, real=0.07 secs] 
58.455: [GC [PSYoungGen: 7093923K->194024K(8701312K)] 8083033K->1205300K(10798464K), 0.0952730 secs] [Times: user=1.66 sys=0.02, real=0.10 secs] 
62.825: [GC [PSYoungGen: 7147560K->122912K(8840256K)] 8158836K->1298466K(10937408K), 0.1671770 secs] [Times: user=2.89 sys=0.10, real=0.16 secs] 
67.302: [GC [PSYoungGen: 7270304K->117888K(8792896K)] 8445858K->1377169K(10890048K), 0.1156200 secs] [Times: user=1.98 sys=0.05, real=0.12 secs] 
71.785: [GC [PSYoungGen: 7265280K->119002K(8950720K)] 8524561K->1464556K(11047872K), 0.1152940 secs] [Times: user=1.97 sys=0.09, real=0.11 secs] 
76.448: [GC [PSYoungGen: 7477018K->206455K(8893056K)] 8822572K->1642652K(10990208K), 0.1607870 secs] [Times: user=2.63 sys=0.06, real=0.16 secs] 
81.051: [GC [PSYoungGen: 7564471K->114350K(9084608K)] 9000668K->1649307K(11181760K), 0.1145730 secs] [Times: user=1.89 sys=0.16, real=0.12 secs] 
86.020: [GC [PSYoungGen: 7739630K->125895K(9026432K)] 9274587K->1743248K(11123584K), 0.1125030 secs] [Times: user=1.95 sys=0.06, real=0.11 secs] 
91.007: [GC [PSYoungGen: 7751175K->202320K(9221952K)] 9368528K->1905769K(11319104K), 0.1523180 secs] [Times: user=2.58 sys=0.06, real=0.15 secs] 
95.817: [GC [PSYoungGen: 8085136K->327488K(9146624K)] 9788585K->2203753K(11243776K), 0.2542190 secs] [Times: user=4.44 sys=0.10, real=0.25 secs] 
96.071: [Full GC [PSYoungGen: 327488K->0K(9146624K)] [ParOldGen: 1876265K->1032314K(2097152K)] 2203753K->1032314K(11243776K) [PSPermGen: 27528K->21277K(48128K)], 1.4351920 secs] [Times: user=5.12 sys=0.36, real=1.44 secs] 

Wie Sie sehen, ist alles in Ordnung und Full GC funktioniert OK. Aber der nächste auftretende GC (nicht Full) erhöht die Speichernutzung des Prozesses dramatisch und der Server beginnt mit dem Einsatz von Swap.

Die Frage ist - warum? Soweit ich verstehe, ist volle GC am schmerzhaftesten Punkt in der GC-Verarbeitung. Warum stoppt dann die Anwendung AFTER full gc erfolgreich?

Antwort

2

Angesichts der sehr hohen Systemzeit (viel höher als die Benutzerzeit) Dies deutet darauf hin, dass etwas im OS vor sich geht. Sie sagen, Sie haben viel Speicher, aber wenn sogar ein kleiner Teil der JVM auf die Festplatte ausgelagert wird, kann es die GC-Zeiten töten.

Ich schlage vor, die Gesamtgröße des Heap zu reduzieren, um sicherzustellen, dass Sie mehr freien Speicher für den OS/Festplattencache/andere Programme haben.

Um Ihre Anwendung weiter zu verbessern, würde ich einen Speicher-Profiler verwenden (wahrscheinlich müssen Sie einen Werbespot verwenden, eine Eval-Lizenz wird tun) Sie scheinen 1,5 GB pro Sekunde Müll zu erzeugen, was eine unglaubliche Menge ist. Wenn Sie es auf ein paar 100 MBs pro Sekunde schneiden können, sollte es Ihre Leistung erheblich verbessern (sowie Verzögerungen reduzieren)

BTW: -server sollte die Standardeinstellung auf jedem 64-Bit-Maschine sein.

2

Ich habe seit mehreren Jahren mit einer Anwendung gearbeitet, die eine Heap-Größe und Speicherabwanderung ähnlich wie Ihre (20 GB Heap, 1 GB +/Sekunde Abwanderung) erfordert. Wie @Peter Lawrey sagte, wenn du entweder den gesamten Speicherverbrauch oder die Abwanderung verringern kannst, kommst du voraus (FYI - ich hatte viel Glück mit dem YourKit Profiler. Keine Verbindung mit der Firma, aber meine Erfahrung hat war gut. YMMV.)

Aber, wenn Sie wirklich nicht die Heapverwendung oder -abwanderung verringern können, würde ich Ihnen empfehlen, etwas mehr GC-Abstimmung zu betrachten. Du hast offensichtlich einiges getan; hier sind ein paar Dinge, die für uns gearbeitet haben:

  • neue Generation verkleinern (Sie derzeit 10 GB sind die Zuteilung und fast alle es alle paar Sekunden sammeln Sie könnten besser 1-2 zuzuordnen. . GB und häufiger sammeln auf diese Weise könnten Sie die Gesamtspeichergröße als auch, zu reduzieren und wahrscheinlich Swapping vermeiden

-XX:+PrintGCDetails -XX:+PrintGCDateStamps -. manchmal ist es schön Echtdaten in den GC-Protokolle zu haben)

-XX:+UseConcMarkSweepGC - Concurrent Old-Gen GC verbraucht mehr CPU, bietet aber kürzere Pausen. Für unsere Anwendung ist das unsere Vorliebe, und es scheint, dass es wahrscheinlich auch Ihnen gehört.

Sie könnten auch -XX:ParallelGCThreads=<threads> auf etwas sinnvoll für Ihre Hardware setzen (wir verwenden 6 auf 12-Core-Maschinen, aber ich weiß nicht, dass wir das optimal abgestimmt haben).

Verwandte Themen