ABONAMENTE VIDEO JOBS REDACȚIA
RO
EN
×
▼ LISTĂ EDIȚII ▼
Numărul 58
Abonament PDF

Java Performance: Unelte

Lucian Torje
Senior Java Developer @ Siemens
PROGRAMARE

Motto: "Creșterea performanței unui sistem e ușoară, trebuie doar să știi totul." Sergey Kuksenko, Inginer Performanță Oracle

Scopul acestui articol este de a oferi informații despre cele mai folosite unelte în măsurarea performanței aplicațiilor scrise în Java. Pentru a ne atinge scopul am folosit exemplul de la Pivotal, Spring Pet clinic application. Am optat pentru acest exemplu deoarece Spring MVC și Spring Boot au fost web frameworkurile cele mai folosite în 2016, conform studiului realizat de ZeroTurnaround.

HPROF

HPROF este un tool distribuit gratuit de Oracle odată cu JDK și apare în format .dll. Acesta folosește API JVM TI pentru a măsura performanța heapului și a CPU-ul. Brendan Gregg, care a lucrat pentru Sun și Oracle ca Inginer Performance și Kernel, a raportat câteva probleme:

Pentru a monitoriza aplicația Spring Pet Clinic a trebuit să fie adăugat un http endpoint care să forțeze aplicația să se închidă, se constată lipsa posibilității de a porni/pauza/opri măsurătorile. Rezultatele pentru Pet Clinic se pot observa mai jos:

$ mvn package
$ java -Xrunhprof:cpu=samples -jar target/spring-petclinic-1.5.1.jar
...
2017-03-20 23:00:49.565  INFO 11640 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/close]}" o nto public void org.springframework.samples.petclinic.vet.VetController.close()
...
Dumping CPU usage by sampling running threads ... done.
$ cat java.hprof.txt
JAVA PROFILE 1.0.1, created Mon Mar 20 23:00:22 2017
...
CPU SAMPLES BEGIN (total = 22941) Mon Mar 20 23:04:20 2017
rank   self  accum   count trace method
   1 56.37% 56.37%    5784 301590 sun.nio.ch.WindowsSelectorImpl$        SubSelector.poll0
   2 16.73% 73.10%    1716 301591 sun.nio.ch.ServerSocketChannelImpl.accept0
   3  6.67% 79.77%     684 300352 org.springframework.boot.loader.jar.JarURLConnection.getInputStream
   4  5.47% 85.23%     561 300356 sun.misc.URLClassPath$Loader.        getResource
   5  2.16% 87.40%     222 300231 java.io.RandomAccessFile.open0
   6  1.39% 88.79%     143 300131 java.lang.ClassLoader.defineClass1
   7  1.02% 89.81%     105 300502 sun.misc.URLClassPath$Loader.      findResource
...
CPU SAMPLES END

NetBeans profiler

NetBeans profiler este un tool gratuit de profiling integrat în NetBeans IDE. Oferă suport pentru următoarele: CPU profiling (overhead mare) /sampling (overhead mic) Heap profiling

NetBeans profiler ne-a făcut o impresie foarte bună și este un tool care oferă tot ceea ce este nevoie pentru a analiza problemele de performanță.

VisualVM

VisualVM este un profiler Java distribuit cu Oracle JDK dar care poate fi instalat și separat de pe pagina de download. Acesta este alternativă bună pentru JConsole, oferind aceleași funcții dar și posibilitatea de a le extinde prin pluginuri.

VisualVM include următoarele: Se atașează la procesele locale și remote Monitorizează performanța CPU și memoria Analizează threadurile Obține și analizează snapshoturi de thread/heap Extensibil prin pluginuri*, incluzând MBeans (această opțiune din JConsole sau din Java Mission Control fiind binecunoscută)

VisualVM se poate porni din terminal cu următoarea comandă:

$ jvisualvm

VisualVM este un tool care merită luat în considerare, conform unui studiu ZeroTurnaround din noiembrie 2015 este surprinzător de utilizat, 46% dintre respondenți au folosit VisualVM pentru măsurători de performanță.

Java Mission Control

Java Mission Control și Java Flight Recorder (cunoscute ca JRockit Mission Control și JRockit Flight Recorder - JFR) sunt profiling tooluri adăugate la suita JDK începând cu 7u40 și promovate ca având profiling overhead apropiat de zero.

Java Mision Control este gratuit, spre deosebire de Java Flight Recorder. Pentru a folosi JFR este nevoie de semnarea acordului comercial Oracle.

JMC & JFR oferă toate opțiunile de bază gen monitorizare CPU, heap, threaduri incluzând detecția deadlockuri. Dintre funcțiile avansate merită menționate suportul pentru triggere, monitorizarea I/O a excepțiilor și a evenimentelor, suport pentru MBeans, statisticile despre hot dar și restrângerea monitorizării la o sub -perioadă de timp.

Mission Control se pornește rulând următoarea comandă (din UI se poate folosi wizzardul Java Flight Recording dar și rula metodele JFR prin JMX):

$ jmc

Pentru a pregăti aplicația pentru Flight Recorder, trebuie adăugate următoarele argumente:

-XX:+UnlockCommercialFeatures -XX:+FlightRecorder

Pentru a programa o înregistrare cu Flight Recorder, întârziată cu 20 secunde și salvată în fișierul c:/TEMP/myrecording.jfr se folosesc următorii parametri:

-XX:StartFlightRecording=delay=20s,
  duration=60s,
  name=MyRecordings, 
  filename=c:/TEMP/myrecording.jfr,
  settings=profile 
-XX:FlightRecorderOptions=loglevel=info

Monitorizarea cu JFR poate fi pornită din terminal folosind jcmd și JMX rulând comanda de mai jos:

$ jcmd 9200 JFR.start delay=20s duration=60s name=MyRecordings 
filename=c:/TEMP/myrecording.jfr,settings=profile
9200:
Recording 4 scheduled to start in 20 s. The result will be written to:
C:\temp\myrecording.jfr,settings=profile

Verificarea stării unei înregistrări se realizează rulând următoarea comandă:

$ jcmd 9200 JFR.check
9200:
Recording: recording=4 name="MyRecordings" duration=1m filename="c:/TEMP/myrecording.jfr,settings=profile" compress=false (running)

Pentru crearea unui JFR dump folosim următoarea comandă:

$ jcmd 9200 JFR.dump name=MyRecordings filename=c:/TEMP/dump.jfr
9200:
Dumped recording "MyRecordings", 265.2 kB written to: C:\temp\dump.jfr

Java Mission Control și Java Flight Recorder sunt cu adevărat niște profilere de excepție și dacă dețineți una dintre licențele: "Oracle Java SE Advanced", "Oracle Java SE Advanced Desktop" sau "Oracle Java SE Suite" nu există nici un motiv să folosiți un alt profiler.

JMH

Numele JMH vine de la Java Microbenchmark Harness și este un micro benchmarking framework, distribuit cu OpenJDK începând din 2013. Funcționalitatea pe care o oferă și anume obținerea de statistici de performanță este motivul pentru care este menționat acest framework printre uneltele de profiling. Pentru a obține rezultate cât mai precise, JMH trebuie configurat cu un warmup time generos; acest pas este folosit și de unele profilere și este numit calibrare.

Analiza JMH are ca rezultate posibile timpul de rulare al unei metode (incluzând percentila), media timpului sau throughputului, în funcție de configurație.

Modul cel mai ușor și recomandat de folosire al JMH este de a crea un proiect separat doar pentru JMH folosind Maven:

$ mvn archetype:generate \
          -DinteractiveMode=false \
          -DarchetypeGroupId=org.openjdk.jmh \
          -DarchetypeArtifactId=jmh-java-benchmark-archetype \
          -DgroupId=org.sample \
          -DartifactId=test-pet-clinic \
          -Dversion=1.0

Rezultatul comenzii de mai sus este crearea directorului test-pet-clinic care conține proiectul de testare JMH și care poate fi rulat în modul următor (mod throughput în exemplul de mai jos):

$ cd test-pet-clinic/
$ mvn clean install
$ java -jar target/benchmarks.jar
# JMH 1.9.3 (released 667 days ago, please consider updating!)
# VM invoker: C:\Program Files\Java\jre1.8.0_111\bin\java.exe
# VM options: 
# Warmup: 20 iterations, 1 s each
# Measurement: 20 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.test.spring.RestImplementationsBenchmark.owners
# Parameters: (path = /owners, port = 8080, server = localhost)

# Run progress: 0.00% complete, ETA 00:06:40
# Fork: 1 of 10
# Warmup Iteration   1: 7.829 ops/s
...
# Warmup Iteration  19: 91.628 ops/s
# Warmup Iteration  20: 93.504 ops/s
Iteration   1: 92.267 ops/s
Iteration   2: 34.738 ops/s
Iteration   3: 92.347 ops/s

Result " owners ":
  98.147 ▒(99.9%) 3.851 ops/s [Average]
  (min, avg, max) = (34.738, 98.147, 113.290), stdev = 15.129
  CI (99.9%): [94.296, 101.998] (assumes normal distribution)

# Run complete. Total time: 00:06:08

Benchmark  (path)  (port)   (server)   Mode  Cnt   Score   Error  Units
RestImpl   /owners  8080   localhost   thrpt 173  98.147 ▒ 3.851  ops/s

Dintre utilizările existente ale JMH merită amintite benchmark-urile de Java 8 făcute de TubeMogul sau măsurătorile lui Pavel Samolysov conform cărora: "EJB este cu 15% mai rapid decât Spring Framework în timp ce CDI este cu 19% mai încet".

Daniel Mitterdofer a identificat în prezentarea sa despre benchmark-ul elastic search-ului 7 probleme ale benchmarking-ului:

  1. A nu lua in considerare sistemul folosit (hardware, OS, alte aplicații)

  2. Nu se folosește warmup

  3. Nu se face analiza bootleneck-urilor

  4. A considera scriptul de benchmarking ca fiind infailibil

  5. A nu înțelege și folosi analizele statistice - distribuție, t-test, percentila

  6. Metrici vagi

  7. Tratarea performanței ca un simplu număr

XRebel

XRebel Trial este împachetat ca arhivă zip conținând xrebel.jar java agent, licența și acordul de licențv. Se utilizează ușor prin adăugarea unui parametru: -javaagent:xrebel.jar - acesta va activa XRebel inclusiv toolbar-ul XRebel. Odată ce aplicația web a pornit cu XRebel activat, toolbarul este afișat stânga jos a oricărei pagini web a aplicației. Toolbarul are următoarele meniuri:

Find exceptions - conține toate excepțiile logate

XRebel oferă suport pentru următoarele frameworkuri: Spark, Spring MVC, Spring Boot, JSF, Vaadin, Spark Framework, Grails, Struts, Jersey și permite agregarea datelor de la alte servicii web (pornite cu XRebel activat și folosite de care aplicația curenta). Printre application servers suportate amintim: GlassFish, JBoss, Jetty, Tomcat, TomEE, WebLogic, WebSphere, WebSphere Liberty Profile, WildFly. Dintre bazele de date NoSQL există suport pentru: Cassandra, Couchbase Server, MongoDB, Redis. În ce privește bazele de date relaționale există suport pentru următoarele: Apache Derby, H2, HSQLDB, Microsoft SQL Server, MySQL, Oracle, PostgreSQL, SAP MaxDB și SQLite.

XRebel oferă o experiența plăcută, interfața este intuitivă și ușor de folosit. XRebel ar putea fi mult mai util dacă s-ar implementa vizualizare timpului luat de threadul/urile pornite de către anumite requesturi.

JProfiler

JProfiler este un produs comercial implementat de către EJ Technologies. Oferă suport pentru următoarele:

Profiling pentru procese locale și remote

Interfața este ușor de folosit permițându-ne ca în scurt timp să folosim JProfiler la parametri maximi.

JMeter

JMeter poate fi configurat pentru a obține statistici începând de la web service endpoint throughput până la timpul necesar execuției unei metode. Terminologia JMeter conține următoarele elemente:

Exista posibilitatea de a adăuga manual dar și de a înregistra requesturi HTTP folosind proxy serverul oferit de JMeter. De obicei, Firefox este folosit pentru înregistrări și trebuie amintit faptul că în caz în care aplicația web monitorizată folosește headere x-csrf-token pentru detecția falsificării, este posibil să se extragă tokenul din callul dinainte folosind post procesare gen regex și creând variabile referențiabile (de exemplu ${my_csrf}). JMeter conține următorii extractori:

Măsurătorile conțin următoarele elemente relevante din punct de vedere al performanței sistemului:

Răspunsul pentru un request http realizat cu JMeter se prezintă ca și mai jos:

Thread Name: Thread Group 1-1
Sample Start: 2017-03-26 13:33:01 EET
Load time: 1559
Connect Time: 1
Latency: 1559
…
Sample Count: 1
Error Count: 0
…

Response headers:
HTTP/1.1 200 OK
…
Set-Cookie: JSESSIONID=11D10081A56BB9FA911E7350E57429A1; Path=/owners
Content-Type: application/json;charset=utf-8
…

JMeter este o surpriză plăcută, fiind foarte personalizabil iar integrarea cu unele dintre cele mai importante Continuous Integration tools (Bamboo JMeter Aggregator, JMeter plugin for TeamCity, CircleCI JMeter package or JMeter Jenkins Plugin) îl face un profiler de luat în considerare.

YourKit

YourKit este un profiler comercial care are următoarele funcții:

În general, interacțiunea a fost plăcută, interfața nu este atât de intuitivă pe cât ne-am dori, iar pentru a obține anumite informații avansate este nevoie ca profilerul să fie folosit în mod CPU tracing sau CPU sampling.

Note

Notele reprezintă perspectiva noastră parțial subiectivă, iar intervalul folosit pentru notare este de la 0 la 5. Nota finală a fost calculată ca media notelor, unde Y și N corespund notelor 0 respectiv 5.

Concluzii

Tabel 1 - Evaluarea profiler-elor Java

Cunoașterea avansată a JVM-ului, propriei aplicații și a sistemului în care rulează ajută în a înțelege rezultatele monitorizării și a aplica schimbările necesare pentru a obține o aplicație performantă care va satisface așteptările clienților. Pentru a afla mai multe despre Hotspot și optimizările pe care le face, recomandăm prezentarea JVM Mechanics a lui Doug Hawkins. Pentru cei interesați există toolurile cu ajutorul cărora se poate dezasambla o aplicație Java până la nivel de Java byte code sau cod asamblare nativ cum ar fi: javap JITWatch cu hsdis.

Una dintre problemele cele mai amintite legat de downtime-ul aplicațiilor sunt GC hiccups. Dacă se dovedește că GC-ul cauzează probleme, există opțiunea de a schimba implementarea folosită cu o versiune mai apropiată de aplicația cu probleme. Există câteva implementări disponibile de GC atât pentru Oracle JVM cât și pentru Open JDK unde noul GC Shenandoah merită menționat. Tuningul de GC este explicat în detaliu pe pagina Oracle de GC tuning 6.

Instrumentarea aplicațiilor poate altera valorile măsurătorilor uneori și de 10 ori. Acest lucru se întâmplă deoarece codul este modificat de profiler în timpul monitorizării, ceea ce schimbă modul în care JVM-ul se comportă (optimizează alte zone de cod, schimbă safepoints, schimba code layoutul și adaugă overhead). Acesta nu este un caz izolat, deoarece majoritatea profiler-or folosesc API-ul Java Virtual Machine Tool Interface. Diferența între acuratețea măsurătorilor unui profiler și a altuia poate constă în calibrarea făcută.

Samplingul funcționează prin observarea din exterior a sistemului, crearea de thread dumps la interval regulat de timp și analizarea dumpului. Acest mod de profiling consumă mult CPU, ceea ce îl face inexact. Există profilere mai inteligente cum ar fi cel al lui Richard Warburton numit Honest Profiler, care funcționează ca un hibrid între instrumentare și sampling, verificând la interval regulat de timp stackul metodelor care rulează la un moment dat, în mod asincron, folosindu-se de un API intern OpenJDK.

Măsurarea unei aplicații Java poate fi făcută și în alte moduri. De exemplu, prin examinarea logurilor, monitorizare JMX, Spring actuators sau prin folosirea performance counterilor de sistem.

Îmbunătățirea performanței unei aplicații este o sarcină dificilă și de multe ori consumatoare de timp, cu rezultate concrete doar după eforturi consecvente. Profilerele cu acuratețe ridicată și care oferă setul necesar de funcții sunt un ajutor real și binevenit.

LANSAREA NUMĂRULUI 59

Cluj-Napoca
Marți, 23 Mai, ora 18:00

Înregistrează-te gratuit

Facebook Meetup

Târgu-Mureș
Miercuri, 24 Mai, ora 17:00

Înregistrează-te gratuit

Facebook Meetup

În aceeaşi ediţie ... (58)

▼ TOATE ARTICOLELE ▼

Sponsori

  • Endava
  • 3PillarGlobal
  • Gemini Solutions
  • Betfair
  • Accenture
  • Telenav
  • Siemens
  • Bosch
  • ntt data
  • FlowTraders
  • Crossover
  • Hewlett Packard Enterprise
  • Colors in projects
  • SmartSoft