Quel est le véritable surcharge de try/catch en C#?
Donc, je sais que try/catch ne s'ajouter des frais généraux et n'est donc pas un bon moyen de contrôler les flux de processus, mais d'où vient cette surcharge viennent et quel est son impact réel?
Vous devez vous connecter pour publier un commentaire.
Je ne suis pas un expert dans les implémentations de langue (afin de prendre cela avec un grain de sel), mais je pense que l'un des coûts les plus importants est le dénouement de la pile et de les stocker pour la trace de la pile. Je soupçonne que cela se produit uniquement lorsque l'exception est levée (mais je ne sais pas), et si oui, ce serait décemment taille de frais cachés, chaque fois qu'une exception est levée... donc ce n'est pas comme vous êtes juste de sauter d'un endroit dans le code à l'autre, il se passe beaucoup de choses.
Je ne pense pas que c'est un problème tant que vous êtes en utilisant les exceptions EXCEPTIONNELLES comportement (donc pas votre typique, de la trajectoire prévue par le programme).
Trois points ici:
Tout d'abord, il y a peu ou PAS de perte de performance dans le fait d'avoir des blocs try-catch dans votre code. Cela ne devrait pas être prise en considération lors de la tentative pour éviter de les avoir dans votre application. Le gain de performance n'est mise en jeu lorsqu'une exception est levée.
Lorsqu'une exception est levée en plus de la pile de déroulement des opérations, etc ... qui ont lieu et qui d'autres ont mentionné que vous devez être conscient que tout un tas d'exécution/la réflexion en matière de trucs qui se passe afin de remplir les membres de la classe d'exception comme la trace de la pile d'objet et les différents type de membres, etc.
Je crois que c'est une des raisons pour lesquelles le conseil général si vous allez à renvoyer l'exception est juste
throw;
plutôt que de jeter l'exception à nouveau ou en construire un nouveau, comme dans les cas que toutes les informations de la pile est regathered alors que dans le simple jet c'est tous conservé.throw new Exception("Wrapping layer’s error", ex);
Êtes-vous demander à propos de la surcharge de l'utilisation de try/catch/finally, lorsque les exceptions ne sont pas jetés, ou les frais généraux de l'utilisation des exceptions aux processus de contrôle de flux? Ce dernier est quelque peu semblable à l'aide d'un bâton de dynamite à la lumière d'un tout-petit de l'anniversaire de la bougie, et les frais généraux associés tombe dans les domaines suivants:
Vous pouvez s'attendre à d'autres défauts de page en raison de la levée d'une exception accéder à des non-résidents de code et de données qui ne sont pas normalement dans votre application de jeu de travail.
les deux éléments ci-dessus, généralement de l'accès "à froid", le code et les données, donc dur de défauts de page sont probables si vous avez de la mémoire de la pression à tous:
Comme pour l'impact réel du coût, cela peut varier beaucoup en fonction de ce qui se passe dans votre code à la fois. Jon Skeet a un bon résumé ici, avec quelques liens utiles. J'ai tendance à être d'accord avec son affirmation que si vous arrivez à un point où les exceptions sont considérablement nuire à votre performance, vous avez des problèmes en termes de votre utilisation des exceptions au-delà de la performance.
Dans mon expérience, le plus grand surcharge est dans de réellement lancer une exception et la manipulation. Une fois, j'ai travaillé sur un projet où un code semblable au suivant a été utilisé pour vérifier si quelqu'un avait un droit de modifier un objet. Cette HasRight() la méthode a été utilisée partout dans la couche de présentation, et a souvent été appelé pour 100s d'objets.
Lorsque le test de base de données est plus complète avec des données de test, cela a conduit à une très visibles ralentissement alors que openening de nouvelles formes etc.
Donc j'ai refait à la suivante, ce qui - selon la plus tard rapides " n sale - mesures est d'environ 2 ordres de grandeur plus rapide:
Donc, en bref, à l'aide d'exceptions dans le processus normal d'écoulement est d'environ deux ordres de grandeur plus lent en utilisant les mêmes flux de processus sans exceptions.
Pour ne pas mentionner si c'est à l'intérieur de l'un des plus fréquemment cette méthode, il peut affecter le comportement global de l'application.
Par exemple, je considère que l'utilisation de Int32.Analyser comme une mauvaise pratique dans la plupart des cas, car il lève des exceptions pour quelque chose qui peut être pris facilement autrement.
Donc pour conclure que tout ce qui est écrit ici:
1) Utiliser try..catch à la capture des erreurs inattendues presque pas de perte de performances.
2) Ne pas utiliser les exceptions pour l'exception des erreurs, si vous pouvez l'éviter.
J'ai écrit un article à ce sujet un temps, parce qu'il y avait beaucoup de gens qui demandent à ce propos à la fois. Vous pouvez le trouver et le code de test à http://www.blackwasp.co.uk/SpeedTestTryCatch.aspx.
Le résultat est que, il ya une petite quantité de surcharge pour un bloc try/catch mais si petit qu'il ne doit être ignorée. Toutefois, si vous utilisez les blocs try/catch dans la boucle sont exécutées des millions de fois, vous pouvez envisager de déplacer le bloc à l'extérieur de la boucle si possible.
La clé du problème de performance avec les blocs try/catch, c'est quand vous avez réellement attraper une exception. Cela peut ajouter un retard notable à votre demande. Bien sûr, quand les choses vont mal, la plupart des développeurs (et beaucoup d'utilisateurs) reconnaissent la pause comme une exception qui est sur le point d'arriver! La clé ici est de ne pas utiliser la gestion des exceptions pour les opérations normales. Comme son nom l'indique, ils sont exceptionnels et vous devez faire tout votre possible pour éviter d'être jeté. Vous ne devriez pas les utiliser dans le cadre de l'écoulement d'un programme qui fonctionne correctement.
Contrairement aux théories communément admises,
try
/catch
peut avoir d'importantes implications sur les performances, et que si une exception est levée ou pas!L'ancien a été couverte en quelques posts par Microsoft Mvp au fil des années, et j'espère que tu les trouveras facilement encore StackOverflow soucis tellement sur contenu je vais donc donner des liens vers certains de
de remplissagela preuve:essayer
/catch
/enfin
(et la partie deux), par Pierre Ritchie explore les optimisations quitry
/catch
/finally
désactive (et je vais aller plus loin dans ce avec des citations de la norme)Parse
au lieu deTryParse
au lieu deConvertTo
par Ian Huff états ouvertement que "la gestion des exceptions est très lent" et illustre ce point par les piqûresInt.Parse
etInt.TryParse
les uns contre les autres... À toute personne qui insiste sur le fait queTryParse
utilisetry
/catch
derrière les scènes, ce qui devrait faire la lumière!Il y a aussi cette réponse qui montre la différence entre un code désassemblé avec et sans l'aide de
try
/catch
.Il semble donc évident qu'il n'y est une surcharge qui est manifestement observables dans la génération de code, et que les frais généraux semble même être reconnu par des gens qui Microsoft de la valeur! Pourtant, je suis, répéter l'internet...
Oui, il y a des dizaines de extra MSIL instructions pour un trivial ligne de code, et qui ne couvre même pas les handicapés optimisations donc, techniquement, c'est un micro-optimisation.
J'ai posté une réponse d'années qui a été supprimé car il était axé sur la productivité des programmeurs (les macro-optimisation).
C'est malheureux, car pas de sauvegarde de quelques nanosecondes, ici et là, de temps CPU est probablement pour beaucoup d'heures cumulées de manuel d'optimisation par l'homme. Qui est-ce que votre patron à payer plus pour: une heure de votre temps, ou d'une heure avec l'ordinateur en cours d'exécution? À quel point nous tirez sur la fiche et admettre que c'est le temps de acheter un ordinateur plus rapide?
Clairement, nous devrions être l'optimisation de nos priorités, et pas seulement de notre code! Dans ma dernière réponse, j'ai dessiné sur les différences entre les deux extraits de code.
À l'aide de
try
/catch
:Pas à l'aide de
try
/catch
:Considérer du point de vue d'un entretien développeur, qui est le plus susceptible de perdre votre temps, si ce n'est dans profilage/optimisation (couverts ci-dessus), qui probablement ne serait pas nécessaire s'il n'y avait pas la
try
/catch
problème, puis en faisant défiler le code source... Un de ces quatre lignes supplémentaires de passe-partout de des ordures!Comme de plus en plus les champs sont introduits dans une classe, tous ce passe-partout ordures s'accumule (à la fois dans la source et du code désassemblé) bien au-delà des niveaux raisonnables. Quatre lignes supplémentaires par domaine, et ils sont toujours les mêmes lignes... n'Étions-nous pas appris à éviter de nous répéter? Je suppose que nous pourrions cacher la
try
/catch
derrière certains brassée maison de l'abstraction, mais... alors nous pourrions aussi bien d'éviter les exceptions (c'est à dire utiliserInt.TryParse
).Ce n'est même pas un exemple complexe; j'ai vu des tentatives de l'instanciation de nouvelles classes dans
try
/catch
. Considérer que l'ensemble du code à l'intérieur du constructeur pourrait alors être disqualifié de certaines optimisations qui seraient autrement appliqués automatiquement par le compilateur. Quoi de mieux pour donner naissance à la théorie que le compilateur est lent, par opposition à le compilateur est en train de faire exactement ce qu'il dit de faire?En supposant une exception est levée par le constructeur, et certains bug est déclenchée en conséquence, le mauvais entretien de développeur puis a suivre. Qui pourrait ne pas être une tâche facile, car contrairement à l'spaghetti code de la goto cauchemar,
try
/catch
peuvent causer des dégâts dans trois dimensions, comme il pourrait se déplacer vers le haut de la pile non seulement d'autres parties de la même méthode, mais aussi d'autres classes et méthodes, tout ce qui sera observé par le maintien de développeur, à la dure! Pourtant on nous dit que "goto est dangereux", heh!À la fin je le mentionne,
try
/catch
a ses avantages, il est conçu pour désactiver les optimisations! C'est, si vous voulez, un débogage aide! C'est ce qu'il a été conçu et c'est ce qu'il devrait être utilisé comme...Ce optimisations ne
try
,catch
etfinally
désactiver?A. K. Un
Comment sont
try
,catch
etfinally
utile que le débogage sida?ils sont en écriture obstacles. Cela vient de la norme:
12.3.3.13 Try-catch états
En d'autres termes, au début de chaque
try
déclaration:try
déclaration doit être complète, ce qui nécessite un fil de verrouillage pour un début, ce qui est utile pour le débogage des conditions de course!try
déclarationUne histoire similaire vaut pour chaque
catch
déclaration; supposons que dans votretry
instruction (ou un constructeur ou de la fonction qu'il invoque, etc) que vous attribuez à qui, autrement, inutile variable (disons,garbage=42;
), le compilateur ne peut pas éliminer cette déclaration, peu importe comment pas pertinent c'est le comportement observable du programme. La cession doit avoir terminé avant lacatch
bloc est entré.Pour ce que ça vaut,
finally
raconte une de la même façon dégradant histoire:12.3.3.14 Essayez-enfin états
12.3.3.15 Try-catch-finally états
J'ai fait un l'entrée de blog sur ce sujet l'année dernière.
Check it out. Ligne de fond est qu'il n'y a presque pas de coût d'un bloc try si aucune exception ne se produit - et sur mon ordinateur portable, une exception a été sur 36µs. C'est peut-être moins que prévu, mais gardez à l'esprit que ces résultats au cas où un faible de la pile. Aussi, d'abord les exceptions sont vraiment lentes.
try
/catch
trop? heh heh), mais vous semblez être à discuter avec le langage de spécification et de quelques MS Mvp qui ont également écrit des blogs sur le sujet, assurant des mesures à l'effet contraire de vos conseils... je suis ouvert à la suggestion que les recherches que j'ai fait est mal, mais je vais avoir besoin de lire votre billet de blog pour voir ce qu'il dit.try-catch
bloc vstryparse()
méthodes, mais le concept est le même.C'est largement plus facile à écrire, le débogage et la maintenance du code, qui est libre de messages d'erreur du compilateur, code-analyse des messages d'avertissement et de routine accepté exceptions (notamment les exceptions levées dans un endroit et accepté dans un autre). Parce que c'est plus facile, le code en moyenne, mieux écrit et moins buggé.
Pour moi, que programmeur et de la qualité de surcharge est le principal argument contre l'utilisation de try-catch pour le flux de processus.
L'ordinateur généraux des exceptions est insignifiante en comparaison, et généralement minuscules en termes de la capacité de l'application à rencontrer dans le monde réel des exigences de performance.
J'aime vraiment Hafthor de post de blog, et pour ajouter mon grain de sel à cette discussion, je tiens à dire que, il a toujours été facile pour moi d'avoir les DONNÉES de la COUCHE de jeter un seul type d'exception (DataAccessException). De cette façon, ma COUCHE sait ce qu'exception à attendre et l'attrape. Ensuite, selon les règles (c'est à dire si mon objet de l'entreprise participe dans le flux de travail etc), je peut lancer une nouvelle exception (BusinessObjectException) ou poursuivre sans re/jeter.
Je dirais de ne pas hésiter à utiliser try..catch à chaque fois que c'est nécessaire et l'utiliser à bon escient!
Par exemple, ce procédé participe à un flux de travail...
Commentaires?
On peut lire dans les Langages de Programmation Pragmatique par Michael L. Scott que l'aujourd'hui les compilateurs ne pas ajouter de frais généraux dans le cas le plus courant, cela signifie que, lorsque aucune exception se produit. Ainsi, chaque travail est fait dans les temps de compilation.
Mais lorsqu'une exception est levée lors de l'exécution, compilateur a besoin pour effectuer une recherche binaire pour trouver la bonne exception et ce sera le cas pour chaque nouveau jet de ce que vous faite.
Mais des exceptions sont des exceptions et ce coût est parfaitement acceptable. Si vous essayez de faire la gestion des exceptions sans exceptions et utiliser retourner les codes d'erreur au lieu de cela, probablement, vous aurez besoin d'une instruction if pour chaque sous-programme, ce qui entraînera dans un vraiment en temps réel des frais généraux. Vous savez si la déclaration est converti à quelques instructions de montage, qui sera exécuté à chaque fois que vous entrez dans votre sous-routines.
Désolé pour mon anglais, espérons que cela vous aide. Cette information est basée sur la cité du livre, pour plus d'informations, reportez-vous au Chapitre 8.5 gestion des exceptions.
Laissez-nous analyser l'un des plus grands coûts possibles d'un bloc try/catch quand utilisé là où il ne devrait pas être utilisé:
Et voici l'un sans try/catch:
Sans compter le petit espace blanc, on peut remarquer que ces deux équivalence des morceaux de code sont presque exactement la même longueur, en octets. Ce dernier contient 4 octets de moins en retrait. Est-ce une mauvaise chose?
Pour ajouter l'insulte à l'injure, un étudiant décide de boucle tandis que l'entrée peut être analysée comme un int. La solution sans try/catch pourrait être quelque chose comme:
Mais comment fonctionne ce regard lors de l'utilisation de try/catch?
Les blocs Try/catch sont magiques façons de perdre de l'indentation, et nous ne savons même pas pourquoi il a échoué! Imaginez la façon dont la personne de faire le débogage se sent, quand le code continue de s'exécuter passé d'une logique grave faille, plutôt que de les arrêter avec une belle exception évidente erreur. Les blocs Try/catch sont un paresseux de la validation des données/de l'assainissement.
L'un des plus petits coûts, c'est que les blocs try/catch ne sont en effet de désactiver certaines optimisations: http://msmvps.com/blogs/peterritchie/archive/2007/06/22/performance-implications-of-try-catch-finally.aspx. Je suppose que c'est un point positif aussi. Il peut être utilisé pour désactiver les optimisations qui, autrement, pourrait paralyser sécuritaire, sain de la transmission de message algorithmes pour les applications multithread, et pour attraper possible des conditions de course 😉 C'est sur le seul scénario que je peux penser à utiliser try/catch. Même qui a des alternatives.
Int.Parse
en faveur deInt.TryParse
.