54
Guide de survie du développeur dans une application (Java) qui rame BreizhCamp 2016 #BzhCmp @blep

Breizhcamp : Guide de survie du développeur dans une application (Java) qui rame

Embed Size (px)

Citation preview

  • Guide de survie du dveloppeur dans une

    application (Java) qui rame

    BreizhCamp 2016 #BzhCmp@blep

  • Les ordres de grandeur importent

    Salaire: 1000 --> 1300

    Page speed: 30s --> 20s Seuls les changements d'ordre de grandeur

    ( >300%) changent la perception de la performance de l'application

    BreizhCamp 2016 #BzhCmp@blep

  • About me

    Brice LEPORINI

    Dveloppeur Java / Scala

    BreizhCamp 2016 #BzhCmp@blep

    http://the-babel-tower.github.io/ @blep

  • Lenteurs ou performance ?

    BreizhCamp 2016 #BzhCmp@blep

  • Scott Oaks - Java Performance The definitive guide

    There is no magical -XX:+RunReallyFast option

    BreizhCamp 2016 #BzhCmp@blep

  • Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    BreizhCamp 2016 #BzhCmp@blep

  • Collecter des donnes sur l'environnement

    concern!

    BreizhCamp 2016 #BzhCmp@blep

  • Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    CPU bound? GC?

    BreizhCamp 2016 #BzhCmp@blep

  • Les problmes lis la mmoire

    Terminal avec jstat -gcutil

    BreizhCamp 2016 #BzhCmp@blep

  • Young Generation

    Heap

    Eden

    From Space To Space

    Old Generation

    Survivor

    1: new

    2: minor 1

    3: n minors

    4: promotion

    BreizhCamp 2016 #BzhCmp@blep

  • GC: la master classhttp://www.infoq.com/presentations/Understanding-Java-Garbage-Collection

    BreizhCamp 2016 #BzhCmp@blep

  • Les GC Stop The World

    Serial GC: 1 thread

    Throughput Collector ou Parallel Collector:

    multi threads young et old

    BreizhCamp 2016 #BzhCmp@blep

  • Les GC concurrents: CMS Concurrent Mark Sweep

    Multi thread sur la young et les phases concurrentes, mono thread sur les Full GC

    STW sur les minor GC

    6 Phases:

    1. Initial mark (STW)

    2. Concurrent Mark

    3. Pre clean

    4. Remark (STW)

    5. Sweep

    6. Reset

    Ne compacte pas de faon concurrenteBreizhCamp 2016 #BzhCmp@blep

  • Les GC concurrents : G1 G1 pour Garbage first

    Multi thread sur la young et les phases concurrentes, mono thread sur les Full GC

    STW sur les minor GC

    Gre la heap en zones discrtes

    Phases:

    1. Initial Mark (STW)

    2. Root Region Scanning

    3. Concurrent Marking

    4. Remark (STW)

    5. Cleanup / Copying

    Eden Survivor

    Old

    Old

    EdenEden

    Old

    Survivor

    OldEden Eden

    BreizhCamp 2016 #BzhCmp@blep

  • Le log du GC90,652: [ GC (Allocation Failure) [ PSYoungGen: 130768K->1088K(152576K) ] 381293K->253237K(502272K), 0,0044329 secs ] [Times: user=0,02 sys=0,00, real=0,01 secs]

    101,003: [ Full GC (Ergonomics) [ PSYoungGen: 3687K->0K(150528K) ] [ ParOldGen: 344000K->132146K(349696K) ] 347687K->132146K(500224K), [ Metaspace: 76887K->76887K(1118208K) ], 0,1998650 secs ] [Times: user=1,03 sys=0,01, real=0,20 secs]

    Type de collecte-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGClogFiles=10 -XX:GCLogFileSize=1000K

    BreizhCamp 2016 #BzhCmp@blep

  • GCViewer

    https://github.com/chewiebug/GCViewerBreizhCamp 2016 #BzhCmp@blep

  • Maintenant qu'on en sait un peu plus sur les GC,

    lequel choisir?

    BreizhCamp 2016 #BzhCmp@blep

  • Profils applicatifs

    Transactionnels

    Batches

    BreizhCamp 2016 #BzhCmp@blep

  • Choix du GC Batch:

    Throughtput collector

    Application transactionnelle:

    GC concurrent

    CMS heap < 4GB

    G1 heap >= 4GB

    BreizhCamp 2016 #BzhCmp@blep

  • Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    CPU bound? GC?

    Prlever un heap dump

    BreizhCamp 2016 #BzhCmp@blep

  • Heap dump

    $ jmap -dump:file=heap.hprof,format=b,live 4695 Dumping heap to heap.hprof ... Heap dump file created $ du -sh heap.hprof 462M heap.hprof

    $ java -XX:+HeapDumpOnOutOfMemoryError \ -XX:HeapDumpPath=myApp.hprof ...

    BreizhCamp 2016 #BzhCmp@blep

  • Retained size et dominateur

    User

    age: 42 8o

    name: 4/8o

    StringB i l lvalue:

    4/8o

    Groupname:

    4/8oa d m i n

    group: 4/8o

    User

    age: 42 8o

    group: 4/8o

    name: 4/8o

    StringJ o h nvalue:

    4/8o

    Shallow sizeRetained size deep size

    BreizhCamp 2016 #BzhCmp@blep

  • Memory Analyzer Tool (MAT)

    http://www.eclipse.org/mat/

    1

    2

    3

    BreizhCamp 2016 #BzhCmp@blep

  • Tester

    Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    CPU bound? GC?

    Prlever un heap dump

    Fuite ou utilisation

    abusive?

    Analyser le dump et identifier les dominateurs

    Augmenter la mmoire

    Optimisation du code

    BreizhCamp 2016 #BzhCmp@blep

  • Et le tuning mmoire et GC?

    Dfinition des ratios pour tailler les zones Eden, Survivor et Old

    Dfinition dobjectifs de latence

    Nombre de threads allous au GC

    Java Ergonomics depuis 1.5 -XX:+UseAdaptiveSizePolicy

    $ java -XX:+PrintFlagsFinal -version |wc -l java version "1.8.0_66" Java(TM) SE Runtime Environment (build 1.8.0_66-b17) Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode) 718

    BreizhCamp 2016 #BzhCmp@blep

  • Tester

    Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    CPU bound? GC?

    Prlever un heap dump

    Fuite ou utilisation

    abusive?

    Analyser le dump et identifier les dominateurs

    Augmenter la mmoire

    Prlever un ou plusieurs thread dumps

    OU Analyser lactivit des

    threads avec un profiler

    Optimisation du code

    BreizhCamp 2016 #BzhCmp@blep

  • Thread dump$ jstack 4695

    2016-03-06 09:47:03 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.66-b17 mixed mode):

    "http-bio-8081-exec-74" #305 daemon prio=5 os_prio=31 tid=0x00007fa2de53b000 nid=0xf11f runnable [0x00000001202e7000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:170) at java.net.SocketInputStream.read(SocketInputStream.java:141) at java.io.BufferedInputStream.fill(BufferedInputStream.java:246) at java.io.BufferedInputStream.read(BufferedInputStream.java:265) - locked (a java.io.BufferedInputStream) at java.io.DataInputStream.readByte(DataInputStream.java:265) at org.hsqldb.result.Result.newResult(Unknown Source) at org.hsqldb.ClientConnection.read(Unknown Source) at org.hsqldb.ClientConnection.execute(Unknown Source) - locked (a org.hsqldb.ClientConnection) at org.hsqldb.ClientConnection.getAttribute(Unknown Source) - locked (a org.hsqldb.ClientConnection) at org.hsqldb.ClientConnection.isAutoCommit(Unknown Source) - locked (a org.hsqldb.ClientConnection) at org.hsqldb.jdbc.JDBCConnection.getAutoCommit(Unknown Source) - locked (a org.hsqldb.jdbc.JDBCConnection) at org.apache.commons.dbcp.DelegatingConnection.getAutoCommit(DelegatingConnection.java:337) []

    "http-bio-8081-exec-79" #310 daemon prio=5 os_prio=31 tid=0x00007fa2e00e7800 nid=0xe30b waiting for monitor entry [0x0000000123aa0000] java.lang.Thread.State: BLOCKED (on object monitor) at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:216) - waiting to lock (a java.lang.Object)

    BreizhCamp 2016 #BzhCmp@blep

  • Les tats du thread

    BreizhCamp 2016 #BzhCmp@blep

  • java.lang.Thread.State#BLOCKED

    Un thread bloqu est dans lattente de lacquisition dun moniteur pour entrer dans un bloc synchronis

    La synchronisation dun bloc permet de garantir que les instructions ne sont excutes exclusivement que par un et un seul thread

    @Test public void lockMe() throws InterruptedException { final Thread thread1 = new Thread(this::intenseLockingComputation); final Thread thread2 = new Thread(this::intenseLockingComputation); thread1.start(); thread2.start();

    thread2.join();

    }

    private final Object monitor = new Object();

    private String intenseLockingComputation() { synchronized (monitor) { return { ... } } }

    Thread1 verrouille monitor

    Thread2 attend monitorThread2 verrouille monitor

    BreizhCamp 2016 #BzhCmp@blep

  • Lire le thread dump

    "Thread-2" #21 prio=5 os_prio=31 tid=0x00007fed9c8b3800 nid=0x6803 waiting for monitor entry [0x000000012d3b1000] java.lang.Thread.State: BLOCKED (on object monitor) at blep.LockTest.intenseLockingComputation(LockTest.java:36) - waiting to lock (a java.lang.Object) at blep.LockTest$$Lambda$9/204349222.run(Unknown Source) at java.lang.Thread.run(Thread.java:745)

    "Thread-1" #20 prio=5 os_prio=31 tid=0x00007fed9bb03000 nid=0x6603 runnable [0x000000012d2ae000] java.lang.Thread.State: RUNNABLE at sun.nio.cs.UTF_8$Decoder.decode(UTF_8.java:456) at java.lang.StringCoding$StringDecoder.decode(StringCoding.java:153) at java.lang.StringCoding.decode(StringCoding.java:193) at java.lang.StringCoding.decode(StringCoding.java:254) at java.lang.String.(String.java:534) at java.lang.String.(String.java:554) at blep.LockTest.intenseLockingComputation(LockTest.java:39) - locked (a java.lang.Object) at blep.LockTest$$Lambda$8/1100439041.run(Unknown Source) at java.lang.Thread.run(Thread.java:745)

    Thread-2 est bloqu l en attente du moniteur de la classe

    Thread-1 excute la ligne et a verrouill le moniteur l

    BreizhCamp 2016 #BzhCmp@blep

  • Un cas concret de verrouillage"http-bio-8081-exec-172" #454 daemon prio=5 os_prio=31 tid=0x00007fa2e00f2000 nid=0xe12f waiting for monitor entry [0x0000000122acc000] java.lang.Thread.State: BLOCKED (on object monitor) at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:216) - waiting to lock (a java.lang.Object) at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:108) at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:88) at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:64) at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:285) at ch.qos.logback.classic.Logger.callAppenders(Logger.java:272) at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:473) at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:427) at ch.qos.logback.classic.Logger.debug(Logger.java:534)

    "http-bio-8081-exec-173" #457 daemon prio=5 os_prio=31 tid=0x00007fa2e275e800 nid=0xf61b runnable [0x0000000122de8000] java.lang.Thread.State: RUNNABLE at java.io.FileOutputStream.writeBytes(Native Method) at java.io.FileOutputStream.write(FileOutputStream.java:326) at java.io.BufferedOutputStream.write(BufferedOutputStream.java:122) - locked (a java.io.BufferedOutputStream) at java.io.PrintStream.write(PrintStream.java:480) - locked (a java.io.PrintStream) at java.io.FilterOutputStream.write(FilterOutputStream.java:97) at org.apache.tomcat.util.log.SystemLogHandler.write(SystemLogHandler.java:169) at ch.qos.logback.core.joran.spi.ConsoleTarget$1.write(ConsoleTarget.java:36) at ch.qos.logback.core.encoder.LayoutWrappingEncoder.doEncode(LayoutWrappingEncoder.java:103) at ch.qos.logback.core.OutputStreamAppender.writeOut(OutputStreamAppender.java:193) at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:217) - locked (a java.lang.Object) at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:108) at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:88) at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:64)

    BreizhCamp 2016 #BzhCmp@blep

  • Mon Thread Dump Analyzerhttp://the-babel-tower.github.io/tda.html

    Analyse des moniteurs soumis concurrence

    Stats

    Recherche dans les piles dappels

    Lien vers GrepCode (enfin quand a marche)

    Regroupements par tat

    BreizhCamp 2016 #BzhCmp@blep

  • Thread history

    BreizhCamp 2016 #BzhCmp@blep

  • Ca dpend !

    Dimensionner un pool de threads

    BreizhCamp 2016 #BzhCmp@blep

  • Sync vs Async

    RUN RUNWAIT

    Traitement

    2 x Traitement @ 1 thread :

    RUN11 RUN12WAIT1 RUN21 RUN22WAIT2Sync

    Async RUN11 RUN12WAIT1

    RUN21 RUN22

    WAIT2

    Conception squentielle et bloquante

    Conception non bloquante base sur la composition de callbacks

    BreizhCamp 2016 #BzhCmp@blep

  • Dimensionner un pool de threads

    Conception asynchrone: autant que de threads physiques (@see /proc/cpuinfo)

    Conception synchrone: a dpend!

    Batch: autant que de threads physiques

    Transactionnel : plus ( voire avec la charge et la proportion dattente)

    BreizhCamp 2016 #BzhCmp@blep

  • Tester

    Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    CPU bound? GC?

    Prlever un heap dump

    Fuite ou utilisation

    abusive?

    Analyser le dump et identifier les dominateurs

    Augmenter la mmoire

    Prlever un ou plusieurs thread dumps

    OU Analyser lactivit des

    threads avec un profiler

    Identifier les segments de code applicatifs concerns

    Optimisation du code

    Locks?

    Identifier les moniteurs soumis concurrence

    BreizhCamp 2016 #BzhCmp@blep

  • Identifier les consommateurs avec un profiler

    Sampling ou profiling?

    BreizhCamp 2016 #BzhCmp@blep

  • Profiler gratuit ou payant? Profilers gratuits:

    Gratuit!

    Pas de choix

    Peu performant

    Tlmtrie

    Lger

    Profilers payants:

    Cot dcent (500/600)

    Peu de choix

    Performants

    Prcis

    Sondes de haut niveau

    Intgrs lIDEBreizhCamp 2016 #BzhCmp@blep

  • Tester

    Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    CPU bound? GC?

    Prlever un heap dump

    Fuite ou utilisation

    abusive?

    Analyser le dump et identifier les dominateurs

    Augmenter la mmoire

    Prlever un ou plusieurs thread dumps

    OU Analyser lactivit des

    threads avec un profiler

    Identifier les segments de code applicatifs concerns

    Optimisation du code

    Locks?

    Identifier les moniteurs soumis concurrence

    IO bound?

    Analyser lactivit I/O

    BreizhCamp 2016 #BzhCmp@blep

  • Monitorer les I/O

    BreizhCamp 2016 #BzhCmp@blep

  • Identifier les contentions I/O

    BreizhCamp 2016 #BzhCmp@blep

  • Tester

    Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    CPU bound? GC?

    Prlever un heap dump

    Fuite ou utilisation

    abusive?

    Analyser le dump et identifier les dominateurs

    Augmenter la mmoire

    Prlever un ou plusieurs thread dumps

    OU Analyser lactivit des

    threads avec un profiler

    Identifier les segments de code applicatifs concerns

    Optimisation du code

    Locks?

    Identifier les moniteurs soumis concurrence

    IO bound?

    Analyser lactivit I/O

    Optimiser les IO (cache?)

    BreizhCamp 2016 #BzhCmp@blep

  • Tester

    Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    CPU bound? GC?

    Prlever un heap dump

    Fuite ou utilisation

    abusive?

    Analyser le dump et identifier les dominateurs

    Augmenter la mmoire

    Prlever un ou plusieurs thread dumps

    OU Analyser lactivit des

    threads avec un profiler

    Identifier les segments de code applicatifs concerns

    Optimisation du code

    Locks?

    Identifier les moniteurs soumis concurrence

    IO bound?

    Analyser lactivit I/O

    Optimiser les IO (cache?)

    Prlever un ou plusieurs thread dumps

    pour identifier les threads en wait

    BreizhCamp 2016 #BzhCmp@blep

  • Exemple du pool sous dimensionn

    BreizhCamp 2016 #BzhCmp@blep

  • Dimensionner un pool JDBC

    x connexions pour y utilisateurs?

    42?

    Autant que de requtes HTTP?

    initial = max = maxIdle !

    Exprimenter pour rduire le temps dacquisition et obtenir la meilleure cadence

    BreizhCamp 2016 #BzhCmp@blep

  • Tester

    Pool sous dimensionn?

    Redimensionner

    Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    CPU bound? GC?

    Prlever un heap dump

    Fuite ou utilisation

    abusive?

    Analyser le dump et identifier les dominateurs

    Augmenter la mmoire

    Prlever un ou plusieurs thread dumps

    OU Analyser lactivit des

    threads avec un profiler

    Identifier les segments de code applicatifs concerns

    Optimisation du code

    Locks?

    Identifier les moniteurs soumis concurrence

    IO bound?

    Analyser lactivit I/O

    Optimiser les IO (cache?)

    Prlever un ou plusieurs thread dumps

    pour identifier les threads en wait

    BreizhCamp 2016 #BzhCmp@blep

  • Tester

    Pool sous dimensionn?

    Redimensionner

    Analyser lactivit/lutilisation des systmes externes

    Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    CPU bound? GC?

    Prlever un heap dump

    Fuite ou utilisation

    abusive?

    Analyser le dump et identifier les dominateurs

    Augmenter la mmoire

    Prlever un ou plusieurs thread dumps

    OU Analyser lactivit des

    threads avec un profiler

    Identifier les segments de code applicatifs concerns

    Optimisation du code

    Locks?

    Identifier les moniteurs soumis concurrence

    IO bound?

    Analyser lactivit I/O

    Optimiser les IO (cache?)

    Prlever un ou plusieurs thread dumps

    pour identifier les threads en wait

    BreizhCamp 2016 #BzhCmp@blep

  • Always blame the database! Analyse des plans dexcution / query trace

    Ajout dindexes

    Fracheur des statistiques

    Purge de donnes / partitionnement / sharding (NoSQL)

    Rationalisation des changes (batches, round trips, fetch size)

    Dnormalisation

    BreizhCamp 2016 #BzhCmp@blep

  • Optimisation IO

    Utiliser les Buffered(In|Out)putStreams

    Utilisation de cache:

    Applicatif

    cache FS du kernel

    BreizhCamp 2016 #BzhCmp@blep

  • Tester

    Pool sous dimensionn?

    Redimensionner

    Analyser lactivit/lutilisation des systmes externes

    Optimiser les IO (batches / buffers / ?)

    Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    CPU bound? GC?

    Prlever un heap dump

    Fuite ou utilisation

    abusive?

    Analyser le dump et identifier les dominateurs

    Augmenter la mmoire

    Prlever un ou plusieurs thread dumps

    OU Analyser lactivit des

    threads avec un profiler

    Identifier les segments de code applicatifs concerns

    Optimisation du code

    Locks?

    Identifier les moniteurs soumis concurrence

    IO bound?

    Analyser lactivit I/O

    Optimiser les IO (cache?)

    Prlever un ou plusieurs thread dumps

    pour identifier les threads en wait

    BreizhCamp 2016 #BzhCmp@blep

  • Et la virtualisation? Rservation de ressources!

    BreizhCamp 2016 #BzhCmp@blep

    https://www.youtube.com/watch?v=XK2sG7AiEY8

  • Optimisation du code

    Identifier les segments de code applicatifs concerns

    Tester

    Pool sous dimensionn?

    Redimensionner

    Analyser lactivit/lutilisation des systmes externes

    Optimiser les IO (batches / buffers / ?)

    Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    CPU bound? GC?

    Prlever un heap dump

    Fuite ou utilisation

    abusive?

    Analyser le dump et identifier les dominateurs

    Augmenter la mmoire

    Prlever un ou plusieurs thread dumps

    OU Analyser lactivit des

    threads avec un profiler

    Identifier les segments de code applicatifs concerns

    Optimisation du code

    Locks?

    Identifier les moniteurs soumis concurrence

    CPU bound?

    Placer des marqueurs de mesure dans les log

    OU Analyser lactivit avec un

    profiler

    IO bound?

    Analyser lactivit I/O

    Optimiser les IO (cache?)

    Tester

    Prlever un ou plusieurs thread dumps

    pour identifier les threads en wait

    BreizhCamp 2016 #BzhCmp@blep

  • Faites confiance aux frameworks matures!

    BreizhCamp 2016 #BzhCmp@blep