Im August 2016 führte die Java-Performance-Tuning-Expertin Monica Beckwith auf der von Geeknet, InfoQ und Tingyun gemeinsam gesponserten APMCon 2016 China Application Performance Management Conference den „Java Performance Tuning Must-Read Code“ (Originaltitel: Java Performance Engineer's) durch Präsentation „Survival Guide“. Während der Rede gab Monica persönliche Vorschläge zu Best Practices für das Java-Tuning: wie man die Leistungsanforderungen festlegt, die optimiert werden müssen, welche Indikatoren analysiert werden müssen und wie man das Tuning nach der Festlegung der Ziele konkret durchführt.
Monica Beckwith konzentriert sich auf die Optimierung von Java Virtual Machines und Garbage Collectors in Unternehmensanwendungen und hat viele Artikel über Garbage Collectors und Java-Speichermodelle veröffentlicht. Zuvor arbeitete sie bei Oracle, wo sie das G1-Garbage-Collector-Performance-Team leitete, und ist derzeit als unabhängige Beraterin tätig. Nach Monicas Rede führte InfoQ ein exklusives Interview mit ihr.
Vorbereitung vor der Leistungsoptimierung
Monica ist davon überzeugt, dass ein Leistungsoptimierungsprojekt aus zwei Teilen besteht: Leistungsanforderungsanalyse und -planung sowie Leistungsergebnisanalyse. Die beiden bilden einen geschlossenen Kreislauf, wodurch die Leistung kontinuierlich verbessert werden kann.
1. Analyse und Planung der Leistungsanforderungen
Bei der Ermittlung der Leistungsanforderungen müssen sich Ingenieure zunächst drei Fragen stellen:
Was macht Benutzer glücklich?
Was wird Benutzer stören?
Müssen die aktuellen Probleme beachtet und gelöst werden?
Als nächstes müssen wir über QoS aus der Sicht der Benutzer nachdenken; QoS-Standards quantifizieren messbarer Indikator, d. h. SLA-Service-Level-Agreement; dann SLA-Leistungsindikatoren definieren, sortieren und priorisieren (Durchsatz, Antwortzeit, Kapazität, Anforderungs-Footprint, CPU-Auslastung usw.).
1. Durchsatz/Rate:
Zielwert – kann dieser niedriger sein als der eingestellte Durchsatz?
Messung – Wie wird gemessen? (Transaktionen/Sekunde oder beides) Wo soll gemessen werden (Client, Server oder Browser)
Ziel – Kann die Wenn ja, wie lange kann dieser Zustand maximal erreicht werden?
Test – Wie wird gemessen? Zählt man nur einen bestimmten Zeitraum der Reaktionszeit (im schlimmsten Fall oder alle), wo soll gemessen werden? (Client, Server oder die gesamte Schleife)
3 Was ist die akzeptable Kapazität? Was ist, wenn ein System überlastet ist (Lastausgleichsproblem)? Wie lange kann die Kapazität eines Systems ausgehalten werden?
2. Leistungsergebnisanalyse
Bezüglich der Leistungsergebnisanalyse wird hier nur die Java-Leistungsanalyse besprochen. Analysieren Sie, welche Faktoren sich auf die Endbenutzererfahrung auswirken und die erwarteten QoS nicht erreichen; verfolgen und überwachen Sie Leistungsindikatoren. Das folgende Bild ist ein Schichtsituationsdiagramm:
Ökosystem der Anwendungsschicht: Anwendungsdienste, Anwendungsserver, Datenbanken und andere Dienste im ÖkosystemJRE-Schicht: Klassenladestatus, JIT-Kompilierungsstatus, Speicherbereinigungsstatus, Thread-Status
Betriebssystemschicht: System-/Kernelstatus, Sperrstatus, Threadstatus
Hardwareschicht: Speicherbandbreite/Speicherdurchsatz /Speicher Auslastung, CPU-/Kernauslastung, CPU-Cache-Effizienz/Auslastung/Level, Prozessorstruktur, E/A-Status
Ausführung der Leistungsoptimierung
Zwei Implementierungsmodi
Monica hat zwei Implementierungsmethoden vorgeschlagen : von oben nach unten und von unten nach oben. Welche Sie verwenden, hängt davon ab, was Sie erreichen möchten.
Wenn Sie Verbesserungen auf der Anwendungsebene vornehmen möchten und ein Anwendungsingenieur mit der Fähigkeit sind, Code zu ändern, können Sie einen Top-Down-Ansatz verwenden.
Wenn Sie Verbesserungen auf Plattformebene vornehmen möchten, können Sie einen Bottom-up-Ansatz verwenden. Erstens müssen Sie ermitteln, welches Modul der Plattform verbessert werden muss. Zweitens müssen Sie die relevanten Anwendungen auflisten, die Arbeitslast bewerten und dann die geeigneten Tools finden. Vier SchritteEgal in welche Richtung, es kann in vier Schritte unterteilt werden: Der erste Schritt ist die Überwachung, der zweite Schritt ist die Induktion, der dritte Schrittanalyse, Schritt 4-Tuning und Anwendung.
Im Allgemeinen geben die folgenden Indikatoren Anlass zur Sorge.CPU: CPU-Status, Kernel-Status, Anzahl der Cache-Hits und -Misses, Verzweigungsvorhersage, Pipeline, bedingte Übertragung, Load-Store-Arbeitsmodus usw.
Speicher: Speichernutzung, Speicher, Bandbreite, Lese- und Schreibstatus, maximale Bandbreite für Lesevorgänge, maximale Bandbreite für Schreibvorgänge, maximale Kapazität, bezogen auf die Struktur.
JVM/GC: Sammeln Sie Informationen im Zusammenhang mit Änderungen, sammeln Sie Informationen über verschiedene Phasen der allgemeinen oder gleichzeitigen GC, gleichzeitige Arbeitswarteschlangen und Arbeitsstatus, interne Warteschlangen oder Caches usw.
1. Überwachung
Beginnen Sie zunächst mit dem Überwachungsprozess.
Überwachungsmethoden werden in drei Typen unterteilt: aktiv (Alarmeinstellung), passiv (Netzwerksplitter) und offline (Protokollerfassung).
Es gibt drei Arten von Werkzeugen, aus denen Sie wählen können:
Drittanbieter – VisualVM, Java Flight Recorder
JVM wird mit Befehlen geliefert – PrintCompilation, PrintGCDetails (PrintGCDateStamps), jmap-clstats, jcmd GC.class-stats
Das Betriebssystem wird mit Belt geliefert - Linux verfügt über mpstat, sysstat-iostat, pidstat, prstat, vmstat, dash, CPU-Z, Cacti usw.; Windows verfügt über Leistungsmonitor, Task-Manager, Ressourcenmonitor, CPU-Z, Cacti usw.
2. Zusammenfassung und Analyse
Der nächste Schritt ist der Zusammenfassungs- und Analyseschritt.
Zu diesem Zeitpunkt verfügen Sie bereits über alle Informationen, die Sie benötigen. Sie müssen Bereiche identifizieren, die verbessert werden müssen, und potenzielle Probleme analysieren, die verbessert werden müssen. Es gibt zwei Arten von Open-Source-Tools, die über diesen Link verwendet werden können:
Leistungsanalysetools von Drittanbietern – Oracle Solaris Studio Performance Analyzer, perftools, PAPI, Code XL, Dtrace, Oprofile, gprof, LTT
Java-Programmebene – Visual VM, Netbeans Profiler, JConsole
3. Tuning
Der letzte Schritt des Tunings. Der Schwerpunkt der JVM/GC-Optimierung liegt auf der Auswahl des richtigen Heaps und des richtigen Garbage-Collection-Algorithmus. Teilen Sie zunächst das Alter des Objekts richtig auf und optimieren Sie dann nur die langfristig überlebenden Objekte (das Stop-the-World-Phänomen von GC) und mehrere GC-Threads in derselben VM Wenn das Komprimieren einfacher Objektzeiger funktioniert, müssen bei großen Heaps möglicherweise AlwaysPretouch aktiviert und UseLargePages auf die optimale Größe eingestellt werden. Optimieren Sie außerdem auf Codeebene, um die SLA-Ziele zu erreichen, legen Sie geeignete Ramp-up- und Ramp-down-, Objektaltersaufteilungs- und Aufbewahrungsrichtlinien fest (verstehen Sie die Bildung von LDS-Dateien) und stellen Sie eine korrekte Messung sicher.
Sprechen Sie mit Monica
InfoQ: Ist es notwendig, alle Protokolle während der Leistungsanalyse zu sammeln?
Monica: Im Allgemeinen, wenn wir wissen, dass etwas optimiert werden muss, Benutzer sendet mir Protokolle aus der Produktionsumgebung, wir werden die Umgebung auf dieser Grundlage replizieren und dann in dieser replizierten Umgebung Tests und Inspektionen durchführen. Ich empfehle nicht, in einer realen Umgebung zu testen, da die Produktionsumgebung stabil sein muss. Unter welchen Umständen werden alle Protokolle benötigt? Wenn wir sicher sind, dass ein bestimmtes Problem vorliegt, z. B. ein Speicherverlust, müssen wir zu diesem Zeitpunkt so viele Protokolle wie möglich sammeln.
InfoQ: Können Sie mehrere GC-Methoden analysieren und eine einfache Bewertung vornehmen?
Monica: Garbage Collection ist der Kern der Java-Anwendungsoptimierung. GC sammelt nicht nur Müllinformationen, sondern verwaltet auch Heap-Zuordnungsinformationen. Generell gilt: Wenn Sie wenig Platz haben, um Objekte in Generationen aufzuteilen, empfehle ich in der Hotspot-JVM die Optimierung für Objekte der alten Generation. Denn die junge Generation stellt die Mehrheit und wird sterben. Der häufigste Standard unter den Sammlungsalgorithmen der alten Generation ist der Garbage-Mark-Komprimierungsalgorithmus.
Der CMS-Garbage Collector zielt auf das Recycling der alten Generation ab und markiert überlebende Objekte beginnend mit dem Stammobjekt. Sobald keine aktiven Objekte mehr im Raum vorhanden sind, werden die belegten Ressourcen freigegeben und auf die freie Liste aktualisiert. CMS teilt die gesamte alte Generation, die zur freien Liste gehören sollte, in diese auf.
Ein weiteres Design ist G1. Es unterteilt Ressourcen in Regionen. Einige Regionen bilden zusammen die junge Generation, andere bilden die alte Generation. Das heißt, alle Regionen derselben Generation sind nicht unbedingt benachbart. Jede Region ist zunächst willkürlich und muss als junge oder alte Generation deklariert werden. Während der Sammelperiode nimmt nicht unbedingt die gesamte alte Generation teil. G1 kümmert sich darum, Gebiete mit viel Müll einzusammeln. Darüber hinaus wird G1 auch versuchen, die Intervallgröße der jungen Generation anzupassen.
InfoQ: Was möchten Sie jetzt am meisten in Java ändern?
Monica: Die Nicht-Heap-Speicherverwaltung von Java könnte in JDK 9 oder JDK 10 verbessert werden sehr schwierig Schwierig, ich denke, es gibt viele Bereiche, die verbessert werden müssen.
InfoQ: Worauf müssen Java-Softwareentwickler Ihrer Meinung nach achten, um eine bessere Leistung zu erzielen?
Monica: Beim Programmieren sollte man darüber nachdenken, wie der Java GC funktioniert. Es sind nicht abgelaufene Objekte, die Ressourcen beanspruchen, sondern lebende Objekte, die gepflegt werden müssen. Beim Programmieren müssen Sie die Objekterstellung, Aufbewahrungsstrategien und die Funktionsweise des Garbage Collectors verstehen. Es ist gut, diese drei Punkte zu berücksichtigen. Man muss sich nicht dazu zwingen, alles richtig zu machen, solange das Ganze koordiniert und gut koordiniert ist.