Perfug Guide de survie du développeur dans une application Java qui rame

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

Transcript of Perfug Guide de survie du développeur dans une application Java qui rame

  • Guide de survie du dveloppeur dans une

    application (Java) qui rame

    @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

    @blep

  • About me

    Brice LEPORINI

    Dveloppeur Java / Scala

    @blep

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

  • Lenteurs ou performance ?

    @blep

  • Scott Oaks - Java Performance The definitive guide

    There is no magical -XX:+RunReallyFast option

    @blep

  • Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    @blep

  • Collecter des donnes sur l'environnement

    concern!

    @blep

  • Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    CPU bound? GC?

    @blep

  • Les problmes lis la mmoire

    Terminal avec jstat -gcutil

    @blep

  • Young Generation

    Heap

    Eden

    From Space To Space

    Old Generation

    Survivor

    1: new

    2: minor 1

    3: n minors

    4: promotion

    @blep

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

    @blep

  • Les GC Stop The World

    Serial GC: 1 thread

    Throughput Collector ou Parallel Collector:

    multi threads young et old

    @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 concurrente@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

    @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

    @blep

  • GCViewer

    https://github.com/chewiebug/GCViewer@blep

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

    lequel choisir?

    @blep

  • Profils applicatifs

    Transactionnels

    Batches

    @blep

  • Choix du GC Batch:

    Throughtput collector

    Application transactionnelle:

    GC concurrent

    CMS heap < 4GB

    G1 heap >= 4GB

    @blep

  • Lenteurs avec 1 utilisateur?

    Ouvrir un shell sur la plateforme dexcution

    CPU bound? GC?

    Prlever un heap dump

    @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 ...

    @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

    @blep

  • Memory Analyzer Tool (MAT)

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

    1

    2

    3

    @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

    @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

    @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

    @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)

    @blep

  • Les tats du thread

    @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

    @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

    @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)

    @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

    @blep

  • Thread history

    @blep

  • Ca dpend !

    Dimensionner un pool de threads

    @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

    @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)

    @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

    @blep

  • Identifier les consommateurs avec un profiler

    Sampling ou profiling?

    @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 lIDE@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

    @blep

  • Monitorer les I/O

    @blep

  • Identifier les contentions I/O

    @blep

  • Optimisation IO

    Utilisation de cache:

    Applicatif

    cache FS du kernel

    @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?)

    @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

    @blep

  • Exemple du pool sous dimensionn

    @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

    @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

    @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

    @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

    @blep

  • Optimisation IO

    Utiliser les Buffered(In|Out)putStreams

    @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

    @blep

  • Et la virtualisation? Rservation de ressources!

    @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

    @blep