Java Profiling ist der Prozess der Überwachung verschiedener Parameter auf JVM-Ebene, wie z.B. Methodenausführung, Thread-Ausführung, Objekterstellung und Garbage Collection.Ein Thread-Dump ist eine Momentaufnahme des Zustands aller Threads, die Teil eines bestimmten Prozesses sind.
Unter Linux können Sie mit dem Befehl ‚jps‘ (JVM-Prozess-Status-Tool) die instrumentierten HotSpot Java Virtual Machines (JVMs) auf dem Zielsystem mit ihrer entsprechenden Prozess-ID abrufen.
Abbildung 1- JVMs und ihre Pids.
Der Befehl ‚jps -l‘ gibt den vollständigen Paketnamen für die Hauptklasse der Anwendung oder den vollständigen Pfadnamen zur JAR-Datei der Anwendung aus. Weitere Informationen finden Sie in der Dokumentation von jps.
Danach können wir den Befehl ‚jstack‘ verwenden, um Thread-Dumps zu erfassen. jstack wird im Ordner JDK_HOME/bin ausgeliefert. Hier ist der Befehl, den Sie zum Erfassen von Thread-Dumps eingeben müssen:jstack <pid>. Dabei ist pid die Prozess-ID der Anwendung, deren Thread-Dump aufgezeichnet werden soll. So wird ‚jstack 13626‘ in meiner Konsole das folgende Protokoll von Thread-Dumps ausgeben, wie in der Abbildung gezeigt.
Builtin Profiling Tools und ihre Implementierung
Zusätzlich zu diesen gibt es verschiedene eingebaute Tools, um das Profiling von JVM wie Java VisualVM,Honest Profiler, Async Profiler und Java Mission Controller
Bevor wir uns näher mit diesen Profilern befassen, sollten wir das Konzept des „sicheren Punktes“ kennen. JVM kümmert sich intern um viele Dinge für uns, wie Garbage Collection und JIT Compilation. Die JVM braucht also auch ihre eigene Zeit, um einige Dinge außerhalb der Anwendung für sich selbst zu erledigen. Einige der Dinge, die JVM erledigen kann, können einen Safepoint beinhalten (einschließlich GC). Während eines Safepoints werden alle Threads, die Java-Code ausführen, angehalten, damit die JVM ihre Arbeit erledigen kann. Daher leiden einige Profiler unter diesem Safepoint-Problem, bei dem sie den angegebenen Threads einen Callback geben, die sich in einem Safepoint befinden sollten, um auf diesen Callback zu reagieren, was die Leistung beeinträchtigt.
Andererseits verwenden einige Profiler eine openJDK-interne API namens AsyncGetCallTrace (ASGT), um die Sammlung von Stacktraces ohne Safepoint zu erleichtern. AsyncGetCallTrace ist KEINE offizielle JVM-API.Um ASGT zu verwenden, erstellen Sie zunächst einen JVMTI-Agenten.Das Java Virtual Machine Tool Interface (JVMTI) bietet eine Programmierschnittstelle, die es Ihnen, dem Softwareentwickler, ermöglicht, Softwareagenten zu erstellen, die Ihre Java-Programmiersprachenanwendungen überwachen und steuern können.Dann richten Sie einen Signalhandler ein, der ein Signal mit der gewünschten Abtastfrequenz auslöst.Stellen Sie sicher, dass der unterbrochene Thread in Ihrem Signalhandler läuft und rufen Sie den AGCT auf. Der Honest Profiler verwendet diesen ASGT, um ein Profiling durchzuführen. Ein C++ JVMTI-Agent, der eine Datei mit allen Profiling-Informationen über die Anwendung schreibt, an die der JVMTI-Agent angehängt wurde.
Der zweite Teil ist eine Java-Anwendung, die ein Profil auf der Grundlage dieses Protokolls erstellt, das zuvor generiert wurde.
Die ASGT-Methode sieht wie folgt aus. AsyncGetCallTrace(ASGCT_CallTrace *trace,jint depth,void* ucontext) Wir sollten dieser Methode einen Zeiger auf den ASGT-Aufruf-Trace übergeben.
Das Problem bei diesem Ansatz ist, dass man etwas andere Daten erhält als einen typischen Java-Stack-Trace. Der Profiler muss sie verarbeiten und den Zeilen im Quellcode zuordnen, um nützlich zu sein.
Async-Profiler ist ein Sampling-Profiler mit geringem Overhead, der arbeitet, indem er einen nativen Java-Agenten an einen laufenden JVM-Prozess anhängt und die Stack-Trace-Samples mit Hilfe von HotSpot-spezifischen APIs sammelt. Async-Profiler funktioniert nur auf GNU/Linux und MacOS, und auf ersterem nutzt er zusätzlich perf_events, um auch den nativen Code zu untersuchen. async-Profiler empfängt von perf_events erzeugte Aufrufstapel und gleicht sie mit den von AsyncGetCallTrace erzeugten Aufrufstapeln ab, um ein genaues Profil sowohl von Java als auch von nativem Code zu erstellen. Es verwendet die perf_events-API, um CPU-Sampling in einem Speicherpuffer zu konfigurieren, und fordert ein Signal an, das bei Auftreten eines Samples geliefert wird. Der Signalhandler ruft dann AGCT auf und führt die beiden Stacks zusammen: den Java-Stack, der von AGCT erfasst wird, und den nativen + Kernel-Stack, der von perf_events erfasst wird. Für Nicht-Java-Threads wird nur der perf_events-Stack beibehalten.
Java Mission Controller (JMC) liefert auf effiziente Weise einen detaillierten Bericht über die einzelnen Threads in jeder JVM und ihren prozentualen CPU-Verbrauch.Java Mission Control funktioniert durch Interaktion mit einem JMX-Agenten in der JVM, der über einen MBean-Server verfügt, der mit der integrierten VM und der in der JVM laufenden App-Instrumentierung integriert ist. Das ist ein entscheidender Vorteil, da es die Overhead-Kosten des Tools wirklich senkt, da es bereits vorhandene Hooks verwendet. Oracle gibt an, dass der Overhead in der Regel deutlich unter 1 % liegt, und dass Sie nichts installieren oder an Ihre vorhandene VM anhängen müssen, damit es funktioniert. Bei Flight Recorder müssen Sie ein paar Flags aktivieren, aber nichts installieren. Starten Sie ein Terminal, gehen Sie in Ihr JDK-Bin-Verzeichnis und geben Sie einfach jmc ein. JMC wird eine GUI ausgeben, die Ihre laufenden JVMs enthält.
Eine andere beliebte Alternative ist die Verwendung von Linux-Perf, das Java nicht direkt unterstützt, aber großartige Unterstützung für das Profiling von nativem Code bietet und keine Probleme hat, auch Kernel-Stacks zu betrachten. Für die JVM-Unterstützung benötigen wir eine Perf-Map, die JIT-kompilierte Adressen auf Funktionsnamen abbildet (folglich werden nur kompilierte Frames unterstützt; Interpreter-Frames sind unsichtbar)
Und einen JIT-Schalter -XX:+PreserveFramePointer, der sicherstellt, dass Perf den Java-Stack durchlaufen kann. Wenn Sie diese Art von Ansatz verwenden, verlieren Sie Interpreter-Frames. Sie können kein Profil für eine ältere JVM erstellen, die das PreserveFramePointer-Flag nicht hat. Es kann einige veraltete Einträge in Ihrer Perfmap geben, weil das JIT den Code neu kompilieren kann. Da das JIT etwas Code wegwirft, können einige Funktionalitäten mit einer unsachgemäßen Implementierung enden.
Zusätzlich dazu hat die Java 2 Platform Standard Edition (J2SE) immer ein einfaches Kommandozeilen-Profiling-Tool namens HPROF für Heap- und CPU-Profiling bereitgestellt. HPROF ist ein in das JDK integriertes Tool zur Erstellung von Profilen für die CPU- und Heap-Nutzung innerhalb einer JVM. HPROF ist eigentlich eine native JVM-Agentenbibliothek, die beim Start der JVM über eine Befehlszeilenoption dynamisch geladen wird und Teil des JVM-Prozesses wird. Durch die Angabe von HPROF-Optionen beim Start kann der Benutzer verschiedene Arten von Heap- und/oder CPU-Profiling-Funktionen von HPROF anfordern. Die erzeugten Daten können im Text- oder Binärformat vorliegen und zum Aufspüren und Isolieren von Leistungsproblemen bei der Speichernutzung und ineffizientem Code verwendet werden. Die Binärformatdatei von HPROF kann mit Tools wie HAT verwendet werden, um die zugewiesenen Objekte im Heap zu durchsuchen.
Schlussfolgerung
Wir stellen fest, dass die ehrliche Profilerstellung und die Async-Profilerstellung die Anomalie des „Leidens an Safepoints“ durch einen openJDK-internen API-Aufruf AsyncGetCallTrace überwunden haben.Sie können das Profiling mit viel weniger Overhead als die Standard-Profiling-Tools durchführen, aber sie können kein detailliertes Profiling der Threads liefern, die für die einzelnen JVM-Prozesse spezifisch sind, sondern nur eine Protokolldatei/GUI-Schnittstelle der gesamten Thread-Dumps ausgeben.Auf der anderen Seite kann Java Mission Control die Threads, die spezifisch für jeden Prozess sind, separat profilieren, wo Sie die heißen Threads mit ihrer CPU-Auslastung überwachen können.
Referenzen.
Java Virtual Machine Process Status Tool Oracle Dokumentation.
https://docs.oracle.com/javase/7/docs/technotes/tools/share/jps.html
Erstellen eines Debugging- und Profiling-Agenten mit JVMTI
http://www.oracle.com/technetwork/articles/java/jvmti-136367.html
Die Vor- und Nachteile von AsyncGetCallTrace-Profilern
http://psy-lob-saw.blogspot.com/2016/06/the-pros-and-cons-of-agct.html
Ein Sampling-JVM-Profiler ohne die Safepoint-Sample-Verzerrung.Honest Profiler
https://github.com/jvm-profiling-tools/honest-profiler
Sampling CPU und HEAP Profiler für Java mit AsyncGetCallTrace + perf_events
https://github.com/jvm-profiling-tools/async-profiler