Java Profiling is het proces van het monitoren van verschillende parameters op JVM-niveau, zoals het uitvoeren van methodes, het uitvoeren van threads, het maken van objecten en het verzamelen van vuilnis.Je kunt threaddumps verkrijgen als logbestand van alle processen die in een JVM worden uitgevoerd. Een threaddump is een momentopname van de status van alle threads die deel uitmaken van een specifiek proces.
In Linux kun je met het commando ‘jps’ (JVM process status tool) de geïnstrumenteerde HotSpot Java Virtual Machines (JVM’s) op het doelsysteem verkrijgen met hun bijbehorende proces-ID.
Figuur 1- JVM’s en hun pids.
‘jps -l’-opdracht geeft de volledige pakketnaam voor de hoofdklasse van de toepassing of de volledige padnaam naar het JAR-bestand van de toepassing. Raadpleeg de documentatie van jps voor meer informatie.
Daarna kunnen we ‘jstack’-opdracht gebruiken om thread-dumps vast te leggen. jstack-tool wordt geleverd in JDK_HOME/bin-map. Dit is het commando dat je moet uitvoeren om thread dumps vast te leggen:jstack <pid>. Hier is pid de proces-ID van de toepassing, waarvan de thread dump moet worden opgevangen. Dus ‘jstack 13626’ in mijn console zal de volgende log van thread dumps weergeven, zoals weergegeven in figuur.
Builtin Profiling tools and their Implementation
Naast deze tools zijn er verschillende ingebouwde tools om JVM te profileren, zoals Java VisualVM,Honest Profiler, Async Profiler en Java Mission Controller
Voordat we dieper ingaan op deze profilers, moeten we het concept van ‘Safe point’ kennen. JVM regelt intern veel dingen voor ons, zoals Garbage Collection en JIT Compilation. Dus JVM heeft ook zijn eigen tijd nodig om sommige dingen voor zichzelf uit te zoeken, buiten de applicatie om. Sommige van de dingen die JVM kan doen kunnen een safepoint inhouden (inclusief GC). Tijdens een safepoint worden alle threads die Java code uitvoeren opgeschort zodat de JVM zijn werk kan doen. De applicatie staat stil gedurende de tijd dat de JVM naar een safepoint gaat. Dus sommige profilers hebben last van dit safepoint probleem waar ze een callback geven aan de gespecificeerde threads, die threads zouden in een safepoint moeten zijn om op die callback te reageren. Dus het beïnvloedt de performance.
Aan de andere kant gebruiken sommige profilers een openJDK interne API call AsyncGetCallTrace (ASGT) om het verzamelen van stack traces zonder safepoint te vergemakkelijken. AsyncGetCallTrace is GEEN officiële JVM API. Om ASGT te gebruiken maak je eerst een JVMTI agent aan. De Java Virtual Machine Tool Interface (JVMTI) voorziet in een programmeer interface die je, als software ontwikkelaar, toelaat om software agents aan te maken die je Java programmeertaal applicaties kunnen monitoren en controleren. Zet dan een signaal handler op die een signaal triggert op de gewenste sample frequentie.Dat signaal zal naar de lopende JVM worden geleid en een van hun lopende threads zal worden onderbroken en terugbellen naar onze signaal handler.Zorg ervoor dat de onderbroken thread in je signaal handler draait en roep de AGCT .Honest profiler gebruik deze ASGT om profiling te doen .
De Honest profiler bestaat uit twee delen. Een C++ JVMTI agent die schrijft een bestand met alle profiling informatie over de toepassing die de jvmti agent was gekoppeld aan.Het tweede deel, is een Java-applicatie die een profiel op basis van dit logboek dat eerder werd gegenereerd.
ASGT methode ziet er als volgt uit. AsyncGetCallTrace(ASGCT_CallTrace *trace,jint depth,void* ucontext) .We moeten een pointer naar ASGT call trace aan deze methode doorgeven.
Het probleem met deze aanpak is dat je iets andere gegevens krijgt dan een typische Java stack trace. De profiler moet het verwerken en in kaart brengen naar de regels in de broncode om nuttig te zijn.
Async-profiler is een low overhead sampling profiler die werkt door een native Java-agent aan een draaiend JVM-proces te koppelen en de stack traces-monsters te verzamelen door gebruik te maken van HotSpot-specifieke API’s. Async-profiler werkt alleen op GNU/Linux en MacOS, en op de eerste gebruikt het bovendien perf_events om ook in native code te graven. De algemene aanpak is het ontvangen van call stacks gegenereerd door perf_events en deze te matchen met call stacks gegenereerd door AsyncGetCallTrace, om zo een accuraat profiel van zowel Java als native code te produceren. Het gebruikt de perf_events API om CPU sampling in een geheugenbuffer te configureren, en vraagt om een signaal af te geven wanneer een sample optreedt. De signaal handler roept dan AGCT aan, en voegt de twee stacks samen: de Java stack, opgevangen door AGCT, en de native + kernel stack, opgevangen door perf_events. Voor niet-Java threads, wordt alleen de perf_events stack behouden.
Java Mission Controller(JMC) geeft een gedetailleerd rapport van elk van de specifieke threads in elke JVM en hun CPU verbruikspercentage op een efficiënte manier.Java Mission Control werkt door interactie met een JMX agent in de JVM die een MBean server heeft die integreert met de ingebouwde VM en app instrumentatie die in de JVM draait. Dat is een belangrijk voordeel omdat het echt de overheadkosten van het gereedschap verlaagt omdat het gebruik maakt van reeds bestaande hooks. Oracle zegt dat dit normaal gesproken ver onder de 1% overhead is. Hier is niets dat u hoeft te installeren of aan uw bestaande VM hoeft te koppelen om het werkend te krijgen. Met Flight Recorder zijn er een paar vlaggen die je moet inschakelen, maar niets om te installeren. Start een terminal, ga naar je JDK bin directory en typ jmc. JMC zal een GUI laten zien met daarin je JVM’s. Selecteer het JVM proces dat je wilt profileren en begin met opnemen door de tijdslimiet in te stellen.
Een ander populair alternatief is het gebruik van Linux perf, dat Java niet direct ondersteunt, maar wel geweldige ondersteuning biedt voor het profilen van native code, en ook geen moeite heeft met het bekijken van kernel stacks. Voor JVM ondersteuning hebben we een perf map nodig die JIT-gecompileerde adressen mapt naar functienamen (als gevolg daarvan worden alleen gecompileerde frames ondersteund; interpreter frames zijn onzichtbaar)
En een JIT switch -XX:+PreserveFramePointer die ervoor zorgt dat perf de Java stack kan doorlopen. Wanneer je dit soort aanpak gebruikt, verlies je interpreter frames.Je kunt geen profiel maken van een oudere JVM die de PreserveFramePointer vlag niet heeft.Er kunnen wat oude entries in je perfmap staan omdat de JIT de code kan hercompileren.Omdat de JIT wat code weggooit, kunnen sommige functionaliteiten verkeerd worden geïmplementeerd.
In aanvulling hierop heeft de Java 2 Platform Standard Edition (J2SE) altijd een eenvoudig opdrachtregel profiling tool genaamd HPROF voor heap en cpu profiling. HPROF is een in JDK ingebouwd hulpmiddel voor het profilen van het CPU- en heap-gebruik binnen een JVM.HPROF is eigenlijk een JVM native agent library die dynamisch wordt geladen via een commandoregeloptie, bij het opstarten van de JVM, en onderdeel wordt van het JVM-proces. Door bij het opstarten HPROF-opties op te geven, kunnen gebruikers verschillende soorten heap- en/of cpu-profilering opvragen bij HPROF. De gegenereerde gegevens kunnen in tekst- of binair formaat zijn, en kunnen worden gebruikt om prestatieproblemen op te sporen en te isoleren die te maken hebben met geheugengebruik en inefficiënte code. Het binaire formaat bestand van HPROF kan worden gebruikt met tools zoals HAT om de gealloceerde objecten in de heap te doorzoeken.
Conclusie
We constateren dat de honest profiling en Async profiling de anomalie van ‘Suffering from safepoints’ hebben overwonnen door een openJDK interne API call AsyncGetCallTrace.Ze kunnen de profiling uitvoeren met veel minder overhead dan de standaard profiling tools.Maar ze kunnen geen gedetailleerde profiling geven van de threads die specifiek zijn voor de JVM processen afzonderlijk.Ze kunnen alleen een log file/GUI interface van de hele thread dumps als een bosje uitvoeren.Aan de andere kant kan Java Mission Control de threads die specifiek zijn voor elk proces afzonderlijk profileren, waarbij je de hot threads met hun CPU-gebruik kunt controleren. JMC is dus de beste optie om de JVM-parameters met veel granulariteit te controleren.
Referenties.
Java Virtual Machine Process Status Tool Oracle Documentation.
https://docs.oracle.com/javase/7/docs/technotes/tools/share/jps.html
Een debug- en profileringsagent maken met JVMTI
http://www.oracle.com/technetwork/articles/java/jvmti-136367.html
De voor- en nadelen van AsyncGetCallTrace-profilers
http://psy-lob-saw.blogspot.com/2016/06/the-pros-and-cons-of-agct.html
Een JVM-profililer met steekproeven zonder de bias van het safepoint-steekproeven.Honest Profiler
https://github.com/jvm-profiling-tools/honest-profiler
Sampling CPU- en HEAP-profilers voor Java met AsyncGetCallTrace + perf_events
https://github.com/jvm-profiling-tools/async-profiler