web-dev-qa-db-fra.com

Java try/catch performance, est-il recommandé de limiter au minimum le contenu de la clause try?

Considérant que vous avez un code comme celui-ci:

doSomething() // this method may throw a checked a exception
//do some assignements calculations
doAnotherThing() //this method may also throw the same type of checked exception
//more calls to methods and calculations, all throwing the same kind of exceptions.

Maintenant, je sais qu'il y a en fait une baisse de performance lors de la construction de l'exception, en particulier le déroulement de la pile. Et j'ai également lu plusieurs articles faisant état d'une légère baisse de performance lors de la saisie de blocs try/catch, mais aucun des articles ne semble conclure quoi que ce soit.

Ma question est la suivante: est-il recommandé de limiter au minimum les lignes à l'intérieur de try try? Le code contenu dans la clause try s'exécute-t-il plus lentement ou peut-il nuire aux performances ?.

Mais plus important encore, quelle est la meilleure pratique/solution plus lisible si vous envisagez de le faire:

try {
    doSomething() // this method may throw a checked a exception
//do some assignements calculations
doAnotherThing() //this method may also throw the same type of checked exception
//more calls to methods and calculations, all throwing the same kind of exceptions.
}
catch (MyCheckedException e) {
   //handle it
}

ou :

try {
    doSomething() // this method may throw a checked a exception
}
catch (MyCheckedException e) {
   //Store my exception in a Map (this is all running in a loop and I want it to   continue running, but I also want to know which loops didn't complete and why)
   continue;     
} 
 //do some assignements calculations
try {
    doAnotherThing() // this method may throw a checked a exception
}
catch (MyCheckedException e) {
    //Store my exception in a Map (this is all running in a loop and I want it to   continue running, but I also want to know which loops didn't complete and why)
   continue;
} 

Cela tient compte du fait que vous traiterez TOUTES ces exceptions vérifiées exactement de la même manière, bien sûr.

33
Oscar Gomez

Dans votre exemple, les performances réelles sont affectées par les exceptions si doSomething () et doAnotherThing () lisent les deux. Entrer dans un bloc d'essai est rapide, jusqu'à ce qu'il lève une exception.

Cela dépend vraiment de votre situation. Si vous devez faire la même chose lorsque MyCheckedException est levée de l'une ou l'autre manière, je considérerais qu'il est à la fois plus lisible et plus performant de les avoir tous les deux dans le même bloc try, mais si vous devez gérer les deux situations différentes différemment, bien sûr. il est plus logique de les séparer.

Edit: J'ai lu la fin de votre commentaire, vous supposez que vous manipulez les deux de la même manière, auquel cas je les mettrais tous les deux dans le même bloc d'essai.

15
rwat

Est-il recommandé de garder les lignes à l'intérieur de la prise d'essai au strict minimum?

Vous ne pouvez pas imaginer comment vous pourriez penser que la longueur d'un bloc try ou même d'un bloc quelconque peut avoir un impact sur les performances.

Le code contenu dans la clause try s'exécute-t-il plus lentement ou peut-il nuire aux performances ?.

Non.

Comme vous l'avez observé, les exceptions n'engendrent que des coûts de performance lorsqu'elles sont levées.

Si vous êtes préoccupé par les performances d’essai, vous devez certainement garder le code à l’intérieur de maximum?

23
user207421

Je ne sais pas lequel est le plus lent, mais n'oubliez pas qu'un bloc try est un flux de contrôle. Vous devez adapter le flux de contrôle à ce que vous essayez d'accomplir. Pour moi, le choix entre

try {
    // op 1.
    // op 2.
    / ...
    // op n.
}
catch ( MyCheckedException error )
{
    // handle any `MyException` in op 1, 2 ... n.
}

et séparer les blocs catch pour chacun est principalement une décision de savoir si je souhaite effectuer un traitement différent pour chaque opération, continuer à l'exécuter jusqu'à l'opération n indépendamment des erreurs ou essayer de les exécuter toutes et échouer à la première erreur.

Écrivez un code propre et lisible et puis recherchez les goulots d'étranglement. Si les expériences existantes ne permettent pas de conclure aux lignes directrices de base, je suppose que ce n'est pas là que vous trouverez vos goulots d'étranglement de toute façon.

4
André Caron

Avoir des blocs d'essai ne devrait avoir pratiquement aucun effet sur les performances dans une machine virtuelle Java décente. Le vrai succès survient lorsqu'une exception est réellement levée.

Vous pouvez lire cet article pour avoir une idée de la façon dont la JVM implémente la gestion des exceptions dans le bytecode: elle crée des "tables d’exception" qui mappent des régions de code sur les blocs catch/finally, ainsi:

  • Le code binaire pour un bloc d'essai est le même que pour un bloc standard {}
  • Le seul coût supplémentaire dans le cas qui n’a pas été lancé est celui du chargement de la "table d’exceptions" en mémoire.

Bien sûr, quand une exception est levée, il y a beaucoup de travail en pile, donc cela va avoir un coût. Quoi qu'il en soit, ce n'est pas aussi grave qu'avec SEH (exceptions .NET).

3
gpeche

Votre code ne devrait gérer que les exceptions pour lesquelles il peut faire quelque chose, les autres devraient être relancés.

La quantité de code contenue dans le bloc try ne provoque pas de ralentissement, mais frappe le bloc catch. Mais à moins que vous n'essayiez d'écrire du code très performant, je ne m'en inquiéterais pas.

2
Jeroen van Bergen

Limiter au minimum le nombre de blocs try/catch améliorera légèrement les performances, mais déplacer le travail ne fera pas vraiment une différence, sauf pour le travail qui serait ignoré à cause d'une exception levée.

1
Chris

Il y a des frais généraux pour chaque bloc d'exception. Donc, vous voulez maximiser la quantité de temps que vous restez dans un bloc.

Cependant, vous devez également prendre en compte la différence de sémantique. Dans votre premier exemple, si doSomething() lève une exception, alors doAnotherThing() ne sera pas exécuté. Dans le deuxième exemple (en supposant que le gestionnaire de captures ne retourne pas), doAnotherThing() SERA exécuté.

0
Mike Caron

Je ne suis pas sûr que, dans le bloc try, les performances puissent être lentes, mais ce que je sais, c'est que les performances de ex.getStackTrace() sont très lentes car elles révèlent toute votre pile de commandes et vous devez faire attention à cela.

0
danny.lesnik

Les exceptions coûtent cher car chaque fois qu'une exception est levée, la trace de pile doit être créée et remplie.

Imaginez une opération de transfert de solde qui échoue dans 1% des cas en raison d'un manque de fonds. Même avec ce taux de défaillance relativement faible, les performances peuvent être sérieusement affectées.

Voir le code source et les résultats de référence ici .

0
Richard Gomes