37 votes

Analyse des fuites en Java

Pour autant que je sache, la JVM utilise l'analyse d'échappement pour certaines performances. optimisations comme le dégrossissage et l'élision de la serrure. Je suis intéressé de savoir s'il existe une possibilité pour la JVM de décider qu'un objet particulier peut être alloué sur la pile en utilisant l'analyse d'échappement.

Quelques ressources me faire croire que j'ai raison. Existe-t-il des JVM qui le font réellement ?

92voto

Janek Bogucki Points 2573

Avec cette version de java, -XX:+DoEscapeAnalysis entraîne une activité gc bien moindre et une exécution 14 fois plus rapide.

$ java -version
java version "1.6.0_14"
Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
    Java HotSpot(TM) Client VM (build 14.0-b16, mixed mode, sharing)

$ uname -a
Linux xxx 2.6.18-4-686 #1 SMP Mon Mar 26 17:17:36 UTC 2007 i686 GNU/Linux

Sans analyse d'évasion,

$ java -server -verbose:gc EscapeAnalysis|cat -n
     1  start
     2  [GC 896K->102K(5056K), 0.0053480 secs]
     3  [GC 998K->102K(5056K), 0.0012930 secs]
     4  [GC 998K->102K(5056K), 0.0006930 secs]
   --snip--
   174  [GC 998K->102K(5056K), 0.0001960 secs]
   175  [GC 998K->102K(5056K), 0.0002150 secs]
   176  10000000

Avec une analyse de l'évasion,

$ java -server -verbose:gc -XX:+DoEscapeAnalysis EscapeAnalysis
start
[GC 896K->102K(5056K), 0.0055600 secs]
10000000

Le temps d'exécution est considérablement réduit avec l'analyse d'évasion. Pour cela, la boucle a été modifiée à 10e9 itérations,

public static void main(String [] args){
    System.out.println("start");
    for(int i = 0; i < 1000*1000*1000; ++i){
        Foo foo = new Foo();
    }
    System.out.println(Foo.counter);
}

Sans analyse d'évasion,

$ time java -server EscapeAnalysis
start
1000000000

real    0m27.386s
user    0m24.950s
sys     0m1.076s

Avec une analyse de l'évasion,

$ time java -server -XX:+DoEscapeAnalysis EscapeAnalysis
start
1000000000

real    0m2.018s
user    0m2.004s
sys     0m0.012s

Ainsi, avec l'analyse d'échappement, l'exemple s'est exécuté environ 14 fois plus vite que l'exécution sans analyse d'échappement.

5voto

benmmurphy Points 1609

Je ne pense pas qu'il fasse une analyse d'échappement pour l'allocation de la pile, par exemple :

public class EscapeAnalysis {

    private static class Foo {
        private int x;
        private static int counter;

        public Foo() {
            x = (++counter);
        }
    }
    public static void main(String[] args) {
        System.out.println("start");
        for (int i = 0; i < 10000000; ++i) {
            Foo foo = new Foo();
        }

        System.out.println(Foo.counter);
    }
}

avec -server -verbose:gc -XX+DoEscapeAnalysis :

start
\[GC 3072K->285K(32640K), 0.0065187 secs\]
\[GC 3357K->285K(35712K), 0.0053043 secs\]
\[GC 6429K->301K(35712K), 0.0030797 secs\]
\[GC 6445K->285K(41856K), 0.0033648 secs\]
\[GC 12573K->285K(41856K), 0.0050432 secs\]
\[GC 12573K->301K(53952K), 0.0043682 secs\]
\[GC 24877K->277K(53952K), 0.0031890 secs\]
\[GC 24853K->277K(78528K), 0.0005293 secs\]
\[GC 49365K->277K(78592K), 0.0006699 secs\]
10000000

Prétendument Le JDK 7 prend en charge l'allocation de la pile .

2voto

Mike Ceruti Points 29

L'analyse d'échappement est vraiment bien, mais ce n'est pas une carte de sortie de prison complète. Si vous avez une collection de taille dynamique à l'intérieur d'un objet, l'analyse d'échappement ne passera PAS du tas à la pile. Par exemple :

public class toEscape {
   public long l;
   public List<Long> longList = new ArrayList<Long>();
}

Même si cet objet est créé dans une méthode et ne s'échappe absolument PAS d'un point de vue syntaxique, le compilateur ne le marquera pas pour l'échappement. Je soupçonne que c'est parce que cette longList n'est pas vraiment de taille limitée d'un point de vue purement syntaxique et qu'elle pourrait potentiellement faire exploser votre pile. Ainsi, je crois qu'il prend un laissez-passer dans ce cas. J'ai expérimenté avec cela où la longList était vide et cela a quand même causé des collections dans un simple micro benchmark.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X