0

Je viens d'écrire un texte de présentation tout sur la façon dont je suis arrivé à ce point, mais figurés il est plus facile d'afficher le code et le laisser à ce :)Java Exceptions Les boucles et désapprobations (ou est-ce une chose urlencodage?)

Comme autant que je peux dire, la performance de test3() devrait être la même que test1() - la seule différence est où l'exception est attrapée (à l'intérieur de la méthode appelant pour test1(), à l'intérieur de la méthode appelée pour test3())

Pourquoi test3() prend-il régulièrement du temps entre test1() et test2() pour terminer?

import java.io.UnsupportedEncodingException; 
import java.net.URLEncoder; 

public class Test { 

    public static void main(String[] args) { 
     warmup(); 
     test1(2500000); // Exception caught inside the loop 
     test2(2500000); // Exception caught outside the loop 
     test3(2500000); // Exception caught "inside" the loop, but in the URLEncoder.encode() method 
    } 

    private static void warmup() { 
     // Let URLEncoder do whatever startup it needs before we hit it 
     String encoding = System.getProperty("file.encoding"); 
     try { 
      URLEncoder.encode("ignore", encoding); 
     } catch (UnsupportedEncodingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

    private static void test1(int count) { 
     String encoding = System.getProperty("file.encoding"); 
     long start = System.currentTimeMillis(); 
     for (int i = 0; i < count; i++) { 
      try { 
       URLEncoder.encode("test 1 " + i, encoding); 
      } catch (UnsupportedEncodingException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
     long end = System.currentTimeMillis(); 
     System.out.println("Performed " + count + " encodings trying to catch each in " + (end - start) + "ms"); 
    } 

    private static void test2(int count) { 
     String encoding = System.getProperty("file.encoding"); 
     long start = System.currentTimeMillis(); 
     try { 
      for (int i = 0; i < count; i++) { 
       URLEncoder.encode("test 2" + i, encoding); 
      } 
     } catch (UnsupportedEncodingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     long end = System.currentTimeMillis(); 
     System.out.println("Performed " + count + " encodings trying to catch all in " + (end - start) + "ms"); 
    } 

    private static void test3(int count) { 
     long start = System.currentTimeMillis(); 
     for (int i = 0; i < count; i++) { 
      URLEncoder.encode("test 3 " + i); 
     } 
     long end = System.currentTimeMillis(); 
     System.out.println("Performed " + count + " encodings with a deprecated method in " + (end - start) + "ms"); 
    } 

} 

Courir ça me donne (JDK 1.6.0_13 sous Windows XP) la sortie:

Performed 2500000 encodings trying to catch each in 4906ms 
Performed 2500000 encodings trying to catch all in 2454ms 
Performed 2500000 encodings with a deprecated method in 2953ms 

Ainsi, les réponses sont assez proches (on parle quelque chose qui est si trivial qu'il est hors de propos), btu Je suis curieux!

plus tard ...

Les gens ont suggéré qu'il ya optimisation JVM obtenir de la manière - je suis d'accord. J'ai donc divisé chaque test en fonction de sa propre classe/méthode principale et individuellement. Les résultats de cette:

1 - Performed 2500000 encodings trying to catch each in 5016ms 
1 - Performed 5000000 encodings trying to catch each in 7547ms 
1 - Performed 5000000 encodings trying to catch each in 7515ms 
1 - Performed 5000000 encodings trying to catch each in 7531ms 

2 - Performed 2500000 encodings trying to catch all in 4719ms 
2 - Performed 5000000 encodings trying to catch all in 7250ms 
2 - Performed 5000000 encodings trying to catch all in 7203ms 
2 - Performed 5000000 encodings trying to catch all in 7250ms 

3 - Performed 2500000 encodings with a deprecated method in 5297ms 
3 - Performed 5000000 encodings with a deprecated method in 8015ms 
3 - Performed 5000000 encodings with a deprecated method in 8063ms 
3 - Performed 5000000 encodings with a deprecated method in 8219ms 

observations intéressantes:

  • L'écart entre la capture chaque appel contre la capture tout à l'extérieur de la boucle est réduite dans sa propre machine virtuelle Java (je suppose que l'optimisation ne va pas tout le porc dans le cas de tous les tests en un en raison des autres itérations qui ont été effectuées)
  • L'écart entre le try/catch de mon côté et le try/catch dans URLEncoder.encode() est maintenant beaucoup plus petit (moitié une seconde sur 5000000 itérations) mais toujours de manière constante ...
+0

Essayez les tests dans un ordre différent: test2(), test3(), test1() pour isoler les différences dues à la compilation JIT. – erickson

Répondre

1

il marche dans l'ordre courant:

Effectué 2500000 encodages essayant de attraper chacun dans 34208ms
Interprétée 2500000 encodages essayant d'attraper tous dans 31708ms
Interprétée 2500000 encodages avec un dépréciée procédé 30738ms

inversant l'ordre:

Interprétée 2500000 encodages avec une méthode désapprouvée dans 32598ms
Joué 2500000 encodages essayant d'attraper tous dans 31239ms
Interprétée 2500000 encodages essayant d'attraper chacun dans 31208ms

Par conséquent, je ne suis pas vraiment pense que vous voyez ce que vous pensez que vous voyez (certainement, test1 n'est pas 66% plus lent que test3, ce qui est ce que vos benchmarks suggèrent)

+0

Hmm ... J'ai éclaté chaque test dans sa propre classe principale, donc il ne peut y avoir aucune optimisation entre les tests entrants, je vois: 1 - Encodage 2500000 encodés en essayant d'attraper chacun en 5016ms 1 - Exécuté 5000000 codages essayant d'attraper chacun à 7547ms 2 - Exécuté 2500000 codages essayant d'attraper tous dans 4719ms 2 - Exécuté 5000000 codages essayant d'attraper tous dans 7250ms 3 - Exécuté 2500000 codages avec une méthode dépréciée en 5297ms 3 - Exécution de codages 5000000 avec une méthode obsolète en 8015ms Le test déconseillé est toujours légèrement plus lent. Encore une fois, seulement minutieusement! :/ – Martin

+0

Blah - être un commentaire foiré le formatage ...Voir le texte original pour une mise à jour – Martin

0

Oui, vous avez votre explication n, je pense:

3 est légèrement plus lent que 1 en raison de l'appel de méthode supplémentaire impliqué.

2 est plus rapide que l'un ou l'autre car il ne «configure» pas et ne «supprime» pas le bytecode lié à l'exception dans chaque boucle. Vous pouvez ouvrir le code d'octet pour voir la différence avec javap - voir http://www.theserverside.com/tt/articles/article.tss?l=GuideJavaBytecode

Que vous utilisiez 2 ou 1 dépend du comportement que vous voulez, car ils ne sont pas équivalents. Je choisirais 1 sur 3 puisque vous n'utilisez pas une méthode obsolète, ce qui est plus important que la petite augmentation de vitesse - mais en l'occurrence 1 est plus rapide de toute façon.

0

Corrigez-moi s'il vous plaît, mais la boucle for test2 n'exécute que 1 étape, à cause de l'exception de lancement et test1 a intercepté l'exception à l'intérieur de la boucle et est exécuté 2500000 fois.

Lorsque vous interceptez l'exception en dehors de la boucle, la boucle ne redémarre pas. Imprimez "int i" pour être sûr du nombre de pas effectués par la boucle.

Le troisième est le plus lent, car la méthode délègue l'appel à la méthode obsolète.

+1

L'exception n'est jamais réellement levée - l'encodage est valide pour chacun d'entre eux - il s'agit plutôt de savoir ce que fait la JVM au cas où elle serait lancée (imprimer quelque chose sur chaque boucle vérifie cela) – Martin

+0

merci Martin, je pensais que l'exception serait levée. –