Est-il coûteux à l'utilisation de blocs try-catch, même si une exception n'est jamais jeté?
Nous savons que c'est cher pour intercepter des exceptions. Mais, est-il aussi cher d'utiliser un bloc try-catch en Java, même si une exception n'est jamais jeté?
J'ai trouvé que le Dépassement de Pile question/réponse Pourquoi les blocs try cher?, mais c'est pour .NET.
Il n'y a vraiment pas de point pour cette question. Try..catch a un but très précis. Si vous en avez besoin, vous en avez besoin. En tout cas, ce point est d'essayer sans crochet?
Ce coût doit être pesés contre les avantages. Il n'est pas autonome. En tout cas, cher est relatif, et jusqu'à ce que vous savez que vous ne pouvez pas le faire, il est judicieux d'utiliser le plus évident de la méthode plutôt que de ne pas faire quelque chose, car il pourrait vous faire économiser une milliseconde ou deux cours d'une heure de l'exécution du programme.
J'espère que ce n'est pas un lieu à un "laisser-réinventer des erreurs de codes" type de situation...
avec Java7 vous pouvez même obtenir débarrasser de la
try { /* do stuff */ } finally { /* make sure to release resources */ }
est légal et utileCe coût doit être pesés contre les avantages. Il n'est pas autonome. En tout cas, cher est relatif, et jusqu'à ce que vous savez que vous ne pouvez pas le faire, il est judicieux d'utiliser le plus évident de la méthode plutôt que de ne pas faire quelque chose, car il pourrait vous faire économiser une milliseconde ou deux cours d'une heure de l'exécution du programme.
J'espère que ce n'est pas un lieu à un "laisser-réinventer des erreurs de codes" type de situation...
avec Java7 vous pouvez même obtenir débarrasser de la
finally
bloc à l'aide d'un try-with-resources
OriginalL'auteur jsedano | 2013-05-08
Vous devez vous connecter pour publier un commentaire.
try
a presque pas de frais à tous. Au lieu de faire le travail de mise en place de latry
au moment de l'exécution, le code des métadonnées structurées au moment de la compilation, tels que lorsqu'une exception est levée, c'est maintenant une opération relativement coûteuse de marche de la pile et de voir si touttry
blocs existent qui permettraient de capter cette exception. À partir d'un point de vue du profane,try
peut ainsi être libre. C'est réellement lancer l'exception qui vous coûte - mais à moins que vous prépariez des centaines ou des milliers d'exceptions, vous ne remarquerez pas le coût.try
a quelques petites coûts qui y sont associés. Java ne peut pas faire quelques optimisations sur le code dans untry
bloc qu'elle ne le feraient autrement. Par exemple, Java va souvent à ré-organiser les instructions dans une méthode pour le faire fonctionner plus rapidement - mais Java doit également garantir que si une exception est levée, la méthode d'exécution est observé comme si ses déclarations, comme écrit dans le code source, exécutés dans l'ordre jusqu'à une certaine ligne.Parce que dans une
try
bloquer une exception peut être levée (à n'importe quelle ligne dans le bloc try! Certaines exceptions sont levées, de manière asynchrone, comme en appelantstop
sur un Thread (ce qui est déconseillé), et même d'ailleurs que OutOfMemoryError peut se produire presque n'importe où) et pourtant, il peut être pris et le code de continuer à exécuter par la suite dans la même méthode, il est plus difficile de raisonner sur des optimisations qui peuvent être faites, de sorte qu'ils sont moins susceptibles de se produire. (Quelqu'un aurait de programme, le compilateur de le faire, de la raison et de garantir l'exactitude, etc. Ce serait une grande douleur pour quelque chose destiné à être "exceptionnelles"), Mais encore, dans la pratique, vous ne remarquerez pas des choses comme ça.Un
try...finally
bloc sanscatch
également de prévenir certaines optimisations?de réellement lancer l'exception qui vous" Techniquement, lancer l'exception n'est pas cher; l'instanciation de la
Exception
objet est ce qui prend le plus de temps.OriginalL'auteur Patashu
Mesurons il, allons-nous?
Sur mon ordinateur, cela s'imprime quelque chose comme:
Au moins dans cet exemple trivial, le rapport d'essai n'avait aucun impact mesurable sur la performance. Se sentir libre de mesure plus complexes.
Une manière générale, je recommande de ne pas vous soucier de la performance des coûts de constructions de langage jusqu'à ce que vous avez des preuves de rendement réel problème dans votre code. Ou comme Donald Knuth mettre: "l'optimisation prématurée est la racine de tout mal".
Comment est-il défectueux?
quelques niveaux: vous voulez dire que les résultats sont calculés en vertu de 1ns? Le code compilé supprimera le try/catch ET de la boucle (en additionnant le nombre de 1 à n est trivial progression arithmétique de la somme). Même si le code contient des try/finally, le compilateur peut le prouver, il n'y a rien à être jetés là. Le code abstrait a seulement 2 sites d'appel et il sera le clone et inline. Il y a plus de cas, il suffit de regarder quelques articles sur microbenchmark et vous décidez d'écrire un microbenchmark toujours vérifier l'assembly généré.
Le temps rapportés sont par itération de la boucle. Une mesure ne sera utilisée que si elle a un temps total écoulé > 0,1 secondes (ou 2 milliards d'itérations, ce qui n'était pas le cas ici), je trouve votre affirmation que la boucle a été supprimé dans son intégralité difficile à croire - parce que si la boucle a été supprimé, ce qui a eu de 0,1 secondes à s'exécuter?
... et en effet, selon
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
, à la fois de la boucle et de l'outre qui y sont présents dans le générés en code natif. Et non, les méthodes abstraites ne sont pas inline, parce que leurs appelant n'est pas juste à temps compilé (sans doute, parce qu'il n'est pas invoquée assez de temps).OriginalL'auteur meriton
try
/catch
peut avoir des répercussions sur les performances. C'est parce qu'il empêche la JVM de faire quelques optimisations. Joshua Bloch, dans "Effective Java", a déclaré ce qui suit:Kraken Code à l'intérieur de blocs try (habituellement? toujours?) ne peut pas être re-commandé avec le code en dehors des blocs try, comme un exemple.
Notez que la question était de savoir si "c'est cher", pas si "il a tout impact sur les performances".
ajout d'un extrait de Efficace Java, et c'est la bible de java, bien sûr; à moins qu'il y est une référence de l'extrait n'est pas de dire quoi que ce soit. Pratiquement n'importe quel code java est à l'intérieur de try/finally à un certain niveau.
OriginalL'auteur Evgeniy Dorofeev
Yep, comme les autres l'ont dit, un
try
bloc inhibe certaines optimisations à travers le{}
personnages qui l'entourent. En particulier, l'optimiseur doit supposer qu'une exception peut se produire à n'importe quel point à l'intérieur du bloc, donc il n'y a aucune assurance que les instructions sont exécutées.Par exemple:
Sans
try
, la valeur calculée à attribuer àx
a pu être sauvé comme un "sous-expression" et réutilisés à attribuer ày
. Mais en raison de latry
il n'y a aucune assurance que la première expression n'a jamais été évalué, de sorte que l'expression doit être recalculé. Ce n'est généralement pas un gros problème en "ligne droite" de code, mais peuvent être importants dans une boucle.Il convient de noter, toutefois, que cela ne s'applique qu'à JITCed code. javac ne fait qu'un minable montant de l'optimisation, et il y a un coût nul pour l'interpréteur de bytecode pour entrer/quitter un
try
bloc. (Il n'y a pas bytecode généré pour marquer les limites des blocs.)Et pour bestsss:
De sortie:
javap de sortie:
Pas de "GOTO".
catch/finally
cadre.Même si un GOTO est généré (qui n'est pas donné), dont le coût est minime, et c'est loin d'être un "marqueur" pour une limite de bloc -- GOTO peut être généré de nombreuses constructions.
Je n'ai parlé de coût, cependant, il n'y a pas bytecode généré est une fausse déclaration. C'est tout. En fait, il n'y a pas de blocs en bytecode, frames ne sont pas des blocs égaux.
Il n'y aura pas un GOTO si l'essai tombe directement dans la enfin, et il y a d'autres situations où il n'y aura pas de GOTO. Le point est qu'il n'y a rien sur l'ordre de "saisir essayer de"/"à la sortie d'essayer" de bytecode.
Il n'y aura pas un GOTO si l'essai tombe directement dans la enfin - Faux! il n'y a pas de
finally
en bytecode, c'esttry/catch(Throwable any){...; throw any;}
Et Il a attraper le rapport w/ un cadre et d'un Throwable qui DOIVENT ÊTRE définis (non nul) et ainsi de suite. Pourquoi avez-vous essayer d'argumenter sur le sujet, vous pouvez vérifier au moins certains bytecode? La recommandation actuelle pour impl. de enfin est de copier les blocs et en évitant d'aller à la section précédente impl) mais le bytecode doivent être copiés selon le nombre de points de sortie.OriginalL'auteur Hot Licks
Encore un autre microbenchmark (source).
J'ai créé un test dans lequel je mesure try-catch et non-try-catch code version basée sur une exception de pourcentage. 10% pourcentage signifie que 10% des cas de test avait une division par zéro cas. Dans une situation, il est géré par un bloc try-catch, dans l'autre par un opérateur conditionnel. Voici mon tableau des résultats:
Qui dit qu'il n'y a pas de différence significative entre l'un de ces cas.
OriginalL'auteur Andrey Chaschev
De comprendre pourquoi les optimisations ne peut pas être effectuée, Il est utile de comprendre les mécanismes sous-jacents. La plus succincte exemple que j'ai pu trouver a été implémenté en C macros: http://www.di.unipi.it/~nids/docs/longjump_try_trow_catch.html
Compilateurs ont souvent de la difficulté à déterminer si un saut peut être localisée à X, Y et Z de sorte qu'ils sauter les optimisations qu'ils ne peuvent pas garantir d'être en sécurité, mais la mise en œuvre elle-même est plutôt léger.
L'implémentation de java est trop vaste pour inclure dans son intégralité, c'est une mise en oeuvre simplifiée dans le but de comprendre l'idée de base de la façon dont les exceptions peuvent être mises en œuvre. Dire qu'il émet 0 temps d'exécution des instructions est trompeuse. Par exemple, un simple classcastexception extends runtimeexception qui s'étend d'exception qui s'étend throwable qui implique: grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/... ... C'est comme dire d'un cas de commutateur dans C est gratuit si seulement 1 cas est jamais utilisé, il y a toujours une petite startup de frais généraux.
Tous ceux précompilés bits doivent encore être chargé au démarrage si oui ou non ils ne sont jamais utilisés. Il n'y a aucun moyen de savoir si il y aura une sortie de la mémoire d'exception lors de l'exécution au moment de la compilation, et c'est pourquoi ils sont appelés moment de l'exécution des exceptions, sinon ils seraient les avertissements du compilateur/erreurs, donc non, il n'est pas optimiser tout de suite, tout le code pour gérer eux est inclus dans le code compilé et a un coût de démarrage.
Je ne peux pas parler de C. C# et Java, essayer est mis en œuvre par l'ajout de métadonnées, pas de code. Lorsqu'un bloc try est entré, rien n'est exécuté pour indiquer ce - lorsqu'une exception est levée, la pile est unwinded et les métadonnées vérifié pour les gestionnaires de ce type d'exception (cher).
Yep, en fait, j'ai mis en place un interprète de Java & statique compilateur bytecode et a travaillé sur une ultérieure JITC (pour IBM iSeries) et je peux vous dire qu'il n'y a rien que les "marques" de l'entrée/sortie de l'essai de la gamme dans le bytecode, mais plutôt les plages sont identifiés dans une table séparée. L'interprète ne fait rien de spécial pour un essai de la gamme (jusqu'à ce qu'une exception est levée). Un JITC (ou statique compilateur bytecode) doit être conscient des limites de supprimer les optimisations comme indiqué précédemment.
OriginalL'auteur technosaurus
J'ai trouvé la capture NullPointException assez cher. Pour 1,2 k opérations de l'époque était de 200ms et 12ms quand je handeled de la même façon avec
if(object==null)
qui était assez amélioration pour moi.OriginalL'auteur Mateusz Kaflowski