146 votes

Les exceptions .NET sont-elles lentes ?

Je ne veux pas d'une discussion sur le fait de savoir quand il faut ou non lancer des exceptions. Je souhaite résoudre un problème simple. Dans 99 % des cas, l'argument en faveur du rejet des exceptions tourne autour de leur lenteur, tandis que l'autre partie affirme (avec des tests de référence) que la vitesse n'est pas un problème. J'ai lu de nombreux blogs, articles et messages concernant un côté ou l'autre. Alors lequel des deux ?

Quelques liens à partir des réponses : Skeet , Mariani , Brumme .

13 votes

Il y a des mensonges, des foutus mensonges et des repères :)

0 votes

Malheureusement, plusieurs réponses très votées ici n'ont pas compris que la question demandait "à quel point les exceptions sont lentes", et ont spécifiquement demandé d'éviter le sujet de la fréquence de leur utilisation. Une réponse simple à la question posée est la suivante : ..... Sur le CLR de Windows, les exceptions sont 750 fois plus lentes que les valeurs de retour.

211voto

Jon Skeet Points 692016

Je suis du côté des "pas lents" - ou plus précisément "pas assez lents pour qu'il vaille la peine de les éviter en utilisation normale". J'ai écrit deux court articles à ce sujet. Il y a des critiques sur l'aspect benchmark, qui se résument principalement à "dans la vraie vie, il y aurait plus de pile à parcourir, donc vous feriez sauter le cache, etc. également faire sauter le cache, donc je ne vois pas ça comme un argument particulièrement bon.

Pour que ce soit clair, je ne suis pas favorable à l'utilisation d'exceptions lorsqu'elles ne sont pas logiques. Par exemple, int.TryParse est tout à fait approprié pour convertir les données d'un utilisateur. Elle est inappropriée pour la lecture d'un fichier généré par une machine, où l'échec signifie "Le fichier n'est pas dans le format qu'il est censé avoir, je ne veux vraiment pas essayer de le traiter car je ne sais pas ce qui pourrait encore être faux".

En utilisant les exceptions dans des "circonstances raisonnables", je n'ai jamais vu une application dont les performances étaient significativement affectées par les exceptions. En gros, les exceptions ne devraient pas être fréquentes, à moins que vous n'ayez des problèmes de correction importants, et si vous avez des problèmes de correction importants, les performances ne sont pas le plus gros problème auquel vous êtes confronté.

2 votes

Malheureusement, on dit aux gens que les exceptions sont gratuites, qu'il faut les utiliser pour des fonctionnalités triviales "correctes", alors qu'elles devraient être utilisées comme vous le dites, lorsque les choses ont mal tourné - dans des circonstances "exceptionnelles".

4 votes

Oui, les gens devraient certainement être conscients qu'il y a un coût de performance associé à l'utilisation inappropriée des exceptions. Je pense juste que ce n'est pas un problème quand ils sont utilisé à bon escient :)

0 votes

Un autre point à noter : tryparse devrait être utilisé lorsque vous pouvez récupérer d'un échec, sinon parse sera plus rapide que "if(!tryparse) throw".

34voto

gbjbaanb Points 31045

Vous trouverez la réponse définitive à cette question auprès de l'homme qui les a mis en œuvre - Chris Brumme. Il a écrit un excellent article de blog sur le sujet (avertissement - c'est très long)(avertissement2 - c'est très bien écrit, si vous êtes un techie vous le lirez jusqu'à la fin et devrez ensuite rattraper vos heures après le travail :) )

Le résumé : ils sont lents. Elles sont implémentées en tant qu'exceptions SEH Win32, donc certaines passeront même la limite de l'anneau 0 du CPU ! Évidemment, dans le monde réel, vous serez en train de faire beaucoup d'autres choses et l'exception bizarre ne sera pas du tout remarquée, mais si vous les utilisez pour le déroulement du programme, attendez-vous à ce que votre application soit mise à mal. C'est un autre exemple de la machine marketing de MS qui nous rend un mauvais service. Je me souviens d'un microsoftie nous disant qu'ils n'avaient absolument aucun frais généraux, ce qui est complètement faux.

Chris donne une citation pertinente :

En fait, le CLR utilise en interne exceptions même dans les parties non gérées du moteur. Cependant, il y a un sérieux problème à long terme problème de performance à long terme avec les exceptions et cela doit être pris en compte dans votre décision.

0 votes

Je peux mentionner ceci dans des tests réels, où un type nullable provoque la levée d'une exception de nombreuses fois dans un "déroulement normal du programme", cela s'est traduit par des problèmes de performance importants. Rappelez-vous toujours, les exceptions sont pour les cas exceptionnels, ne croyez pas ceux qui disent le contraire ou vous finirez avec un fil de discussion github comme celui-là !

19voto

Vincent McNabb Points 5747

Comme l'a dit MusiGenesis, "les exceptions sont lentes en .NET si elles sont lancées".

Donc, oui, vous ne voulez pas en jeter trop. Sur mon ordinateur, avec un simple lancer à l'intérieur d'une boucle, il faut 9,5 secondes pour lancer 1000 exceptions, mais ce temps augmente si l'exception est enterrée dans une grande pile.

C'est pourquoi le contrôle de flux ne devrait PAS être effectué par des exceptions (je sais que votre question ne demandait rien d'autre que la vitesse, mais vous pouvez le vérifier vous-même avec un test chronométré). Bien sûr, vous devez lancer des exceptions lorsque quelque chose ne va pas. Cependant, vous devez limiter au maximum le nombre de problèmes. Par exemple, ne pas passer de mauvaises données à une fonction.

Ha, et toutes les réponses jusqu'à présent (y compris celle-ci) parlent de quand lancer des exceptions et quand ne pas le faire. Ironique.


En fait, je suis entièrement d'accord avec Jon, et je n'avais pas vu sa réponse quand j'ai écrit ceci.

8voto

Cory Foy Points 5181

Je n'ai aucune idée de ce dont parlent les gens quand ils disent qu'ils sont lents seulement s'ils sont lancés.

EDIT : Si les exceptions ne sont pas lancées, cela signifie que vous faites new Exception() ou quelque chose comme ça. Sinon, l'exception va provoquer la suspension du thread et le déplacement de la pile. Cela peut être acceptable dans des situations mineures, mais dans les sites Web à fort trafic, le fait de s'appuyer sur les exceptions comme mécanisme de flux de travail ou de chemin d'exécution vous causera certainement des problèmes de performance. Les exceptions, en soi, ne sont pas mauvaises et sont utiles pour exprimer des conditions exceptionnelles.

Le flux des exceptions dans une application .NET utilise des exceptions de première et de seconde chance. Pour toutes les exceptions, même si vous les attrapez et les traitez, l'objet exception est toujours créé et le framework doit toujours parcourir la pile pour rechercher un gestionnaire. Si vous attrapez et relancez l'exception, cela va bien sûr prendre plus de temps - vous allez avoir une exception de première chance, l'attraper, la relancer, provoquant une autre exception de première chance, qui ne trouve pas de gestionnaire, ce qui provoque une exception de seconde chance.

Les exceptions sont également des objets sur le tas. Par conséquent, si vous lancez des tonnes d'exceptions, vous provoquez des problèmes de performance et de mémoire.

De plus, selon ma copie de "Performance Testing Microsoft .NET Web Applications" écrite par l'équipe ACE :

"Le traitement des exceptions est coûteux. L'exécution du thread concerné est suspendue pendant que le CLR parcourt la pile d'appels à la recherche du bon gestionnaire d'exception, et lorsqu'il est trouvé, le gestionnaire d'exception et un certain nombre de blocs finaux doivent tous avoir leur chance d'être exécutés avant que le traitement normal puisse être effectué."

Ma propre expérience sur le terrain a montré que la réduction des exceptions améliorait considérablement les performances. Bien sûr, il y a d'autres éléments à prendre en compte lors des tests de performance - par exemple, si vos entrées/sorties de disque sont très élevées ou si vos requêtes sont effectuées en quelques secondes, vous devez vous concentrer sur ces éléments. Mais la recherche et la suppression des exceptions doivent constituer un élément essentiel de cette stratégie.

1 votes

Rien de ce que vous avez écrit ne contredit l'affirmation selon laquelle les exceptions ne sont lentes que si elles sont lancées. Vous avez seulement parlé de situations où elles sont jeté. Lorsque vous avez "considérablement amélioré les performances" en supprimant les exceptions : 1) Étaient-elles de vraies conditions d'erreur, ou juste utilisateur erreur ?

0 votes

2) Avez-vous exécuté sous le débogueur, ou non ?

0 votes

La seule chose que vous pouvez faire avec une exception, si vous ne la lancez pas, est de la créer en tant qu'objet, ce qui n'a aucun sens. Le fait d'être sous le débogueur ou non n'a pas d'importance - ce sera toujours plus lent. Oui, il y a des crochets qui se produisent avec un débogueur attaché, mais c'est toujours lent.

4voto

Mon serveur XMPP a gagné en rapidité (désolé, je n'ai pas de chiffres réels, je ne fais que constater) après avoir systématiquement essayé de les empêcher de se produire (comme vérifier si un socket est connecté avant d'essayer de lire plus de données) et m'être donné des moyens de les éviter (les méthodes TryX mentionnées). Et ce, avec seulement une cinquantaine d'utilisateurs virtuels actifs (en train de chatter).

3 votes

Des chiffres seraient utiles, malheureusement :( Des choses comme les opérations sur les sockets devraient largement dépasser les coûts des exceptions, certainement en dehors du débogage. Si vous faites un jour un benchmark complet, je serais vraiment intéressé de voir les résultats.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X