En cas de code où vous devez faire un nettoyage de ressource avant de quitter une fonction, y a-t-il une différence de performance majeure entre ces 2 façons de le faire.
Nettoyage de la ressource avant chaque déclaration de retour
void func() { login(); bool ret = dosomething(); if(ret == false) { logout(); return; } ret = dosomethingelse(); if(ret == false) { logout(); return; } dootherstuff(); logout(); }
Nettoyage de la ressource dans un bloc enfin
void func() { login(); try { bool ret = dosomething(); if(ret == false) return; ret = dosomethingelse(); if(ret == false) return; dootherstuff(); } finally { logout(); } }
J'ai fait quelques tests de base dans des exemples de programmes et il ne semble pas y avoir beaucoup de différence. Je préfère tellement la finally
façon de procéder - mais je me demandais si cela entraînerait un impact sur les performances d'un grand projet.
java
performance
efficiency
user93353
la source
la source
if(!cond)
, alors c'est Java qui m'a fait faire ça. En C ++, c'est ainsi que j'écris du code à la fois des booléens et aussi pour d'autres types - ieint x;
if(!x)
. Étant donné que java ne me permet de l'utiliser que pourbooleans
, j'ai complètement cessé d'utiliser leif(cond)
&if(!cond)
in java.(someIntValue != 0)
que comparer plutôt qu'évaluer les booléens. Cela me sent, et je le refaçonne immédiatement quand je le vois à l'état sauvage.Réponses:
Comme indiqué dans Quelle est la lenteur des exceptions Java? on peut voir que la lenteur de se
try {} catch {}
situe dans l'instauration de l'exception elle-même.La création d'une exception récupère la pile d'appels entière depuis le runtime et c'est là que se situe la dépense. Si vous ne créez pas d'exception, il ne s'agit que très légèrement d'une augmentation de temps.
Dans l'exemple donné dans cette question, il n'y a pas d'exceptions, on ne s'attendrait pas à un ralentissement de leur création - ils ne sont pas créés. Au lieu de cela, il s'agit ici
try {} finally {}
de gérer la désallocation des ressources dans le bloc finally.Donc, pour répondre à la question, non, il n'y a pas de réel coût d'exécution dans une
try {} finally {}
structure qui n'utilise pas d'exceptions (ce n'est pas inconnu, comme on le voit). Ce qui est peut - être coûteux, c'est le temps de maintenance lorsque l'on lit le code et voit ce style de code non typique et que le codeur doit se rappeler que quelque chose d'autre se produit dans cette méthode après lereturn
avant de revenir à l'appel précédent.Comme cela a été mentionné, la maintenance est un argument pour les deux façons de procéder. Pour mémoire, après examen, ma préférence serait l'approche finale.
Considérez le temps nécessaire pour enseigner à quelqu'un une nouvelle structure linguistique. Voir
try {} finally {}
n'est pas quelque chose que l'on voit souvent dans le code Java et peut donc être source de confusion pour les gens. Il y a un certain temps de maintenance pour apprendre des structures un peu plus avancées en Java que ce que les gens connaissent.Le
finally {}
bloc s'exécute toujours . Et c'est pourquoi vous devriez l'utiliser. Considérez également le temps de maintenance du débogage de l'approche non-finale lorsque quelqu'un oublie d'inclure une déconnexion au bon moment, ou l'appelle au mauvais moment, ou oublie de retourner / quitter après l'avoir appelée afin qu'elle soit appelée deux fois. Il y a tellement de bugs possibles avec cela que l'utilisation detry {} finally {}
rend impossible.Lorsque l'on pèse ces deux coûts, il est coûteux en temps de maintenance de ne pas utiliser l'
try {} finally {}
approche. Alors que les gens peuvent hésiter sur le nombre de millisecondes fractionnaires ou d'instructions jvm supplémentaires que letry {} finally {}
bloc est comparé à l'autre version, il faut également considérer les heures passées à déboguer le moyen moins qu'idéal de traiter la désallocation des ressources.Écrivez d'abord le code maintenable, et de préférence de manière à empêcher l'écriture ultérieure des bogues.
la source
/programming/299068/how-slow-are-java-exceptions
La réponse acceptée à cette question montre que l'encapsulation d'un appel de fonction dans un bloc try catch coûte moins de 5% par rapport à un appel de fonction nu. En réalité, le fait de lancer et de rattraper l'exception a provoqué une exécution de la montgolfière à plus de 66 fois l'appel de fonction nue. Donc, si vous vous attendez à ce que la conception des exceptions se produise régulièrement, j'essayerais de l'éviter (dans un code critique de performances correctement profilé), mais si la situation exceptionnelle est rare, ce n'est pas un gros problème.
la source
Au lieu d'optimiser - pensez à ce que fait votre code.
L'ajout du bloc finally est une implémentation différente - cela signifie que vous vous déconnecterez de chaque exception.
Plus précisément - si la connexion lève une exception, le comportement de votre deuxième fonction sera différent de votre premier.
Si la connexion et la déconnexion ne font pas réellement partie du comportement de la fonction, je suggère que la méthode fasse bien une chose et une chose:
et devrait être dans une fonction qui est déjà encapsulée dans un contexte qui gère la connexion / déconnexion, car ceux-ci semblent fondamentalement différents de ce que fait votre code principal.
Votre message est étiqueté comme Java que je ne connais pas très bien mais en .net, j'utiliserais un bloc à l'aide de ceci:
c'est à dire:
Et le contexte de connexion a une méthode Dispose qui déconnectera et nettoiera les ressources.
Edit: je n'ai pas vraiment répondu à la question!
Je n'ai aucune preuve mesurable, mais je ne m'attendrais pas à ce que cela soit plus cher ou certainement pas suffisamment cher pour qu'il soit digne d'une optimisation prématurée.
Je vais laisser le reste de ma réponse car bien que je ne réponde pas à la question, je pense que c'est utile pour le PO.
la source
using
construction .net , en supposant que la ressource en question implémente l'AutoCloseable
interface.ret
variable, qui vient d'être affectée deux fois pour être vérifiée une ligne plus tard. Faites-leif (dosomething() == false) return;
.ret2 = doSomethingElse(ret1)
, mais ce n'est pas pertinent pour la question, il a donc été supprimé.if (dosomething() == false) ...
est un mauvais code. Utilisez le plus intuitifif (!dosomething()) ...
Hypothèse: vous développez en code C #.
La réponse rapide est qu'il n'y a aucun impact significatif sur les performances de l'utilisation des blocs try / finally. Il y a un impact sur les performances lorsque vous lancez et interceptez des exceptions.
La réponse la plus longue est de voir par vous-même. Si vous regardez le code CIL sous-jacent généré ( par exemple, le réflecteur à grille rouge, vous pouvez voir les instructions CIL sous-jacentes générées et voir l'impact de cette façon.
la source
Comme d'autres l'ont déjà noté, le code Ttese aura des résultats différents, si l'un
dosomethingelse
ou l' autre lèventdootherstuff
une exception.Et oui, tout appel de fonction peut lever une exception, au moins un
StackOVerflowError
! Bien qu'il soit rarement possible de les gérer correctement (car toute fonction de nettoyage appelée aura probablement le même problème, dans certains cas (comme l'implémentation de verrous par exemple), il est crucial de gérer cela correctement ...la source