Différences de performances entre debug et release builds

je dois admettre, que d'habitude je n'ai pas pris la peine de passer entre les configurations Debug et Release dans mon programme, et j'ai habituellement opté pour la configuration Debug , même lorsque les programmes sont effectivement déployés à la place du client.

pour autant que je sache, la seule différence entre ces configurations si vous ne la changez pas manuellement est que Debug ont la DEBUG constante définie, et libération ont le code D'optimisation vérifié.

donc mes questions sont en fait doubles:

  1. " il existe de grandes différences de performances entre ces deux configurations. Y a-t-il un type de code spécifique qui causerait de grandes différences de performance ici, ou n'est-ce pas en fait que - il important?

  2. Existe-t-il un type de code qui fonctionnera correctement sous la configuration Debug qui pourrait échouer sous la configuration Release , ou pouvez-vous être certain que le code qui est testé et qui fonctionne correctement sous la configuration Debug fonctionnera aussi correctement sous la configuration "Release".

260
demandé sur shA.t 2010-10-28 18:23:56

8 réponses

le compilateur C# lui-même ne modifie pas les émissions IL beaucoup dans la construction de la version. Il est à noter qu'il n'émet plus les opcodes NOP qui vous permettent de définir un point de rupture sur un corset Bouclé. Le plus important est l'optimiseur qui est intégré dans le compilateur JIT. Je sais qu'il fait les optimisations suivantes:

  • Méthode inline. Un appel de méthode est remplacé par l'injection du code de la méthode. C'est un gros, ça rend bien accesseurs essentiellement gratuit.

  • allocation du registre CPU. Les variables locales et les arguments de méthode peuvent rester stockées dans un registre CPU sans jamais (ou moins fréquemment) être stockées dans le cadre de la pile. Il s'agit d'un gros, notable pour rendre le débogage du code optimisé si difficile. Et donner un sens au mot clé volatile .

  • vérification de l'élimination de L'index des tableaux. Un important optimisation lors du travail avec des tableaux (toutes les classes de collection .NET utilisent un tableau en interne). Quand le compilateur JIT peut vérifier qu'une boucle n'indexe jamais un tableau hors limites, alors il éliminera la vérification de l'index. Big one.

  • Boucle déroulante. Les boucles avec de petits corps sont améliorées en répétant le code jusqu'à 4 fois dans le corps et en bouclant moins. Réduit le coût de la branche et améliore les options d'exécution Super-scalaire du processeur.

  • élimination du code mort. Une déclaration comme si (false) { / ... /} est complètement éliminé. Cela peut se produire en raison de constantes et inline. Dans d'autres cas, le compilateur JIT peut déterminer que le code n'a aucun effet secondaire possible. Cette optimisation est ce qui rend le code de profilage si délicat.

  • hissage de Code. Code à l'intérieur d'une boucle qui n'est pas affecté par la boucle peut être déplacé en dehors de la boucle. L'optimiseur d'un compilateur C passerez beaucoup plus de temps à trouver des opportunités de levage. Il s'agit toutefois d'une optimisation onéreuse en raison de l'analyse du flux de données nécessaire et le jitter ne peut pas se permettre le temps, de sorte que seuls les cas évidents de levage. Forcer les programmeurs .NET à écrire un meilleur code source et à se hisser eux-mêmes.

  • Commune de la sous-expression de l'élimination. x = y + 4; z = y + 4; devient z = x; Assez commun dans des énoncés comme lest[ix+1] = src[ix+1]; écrit pour la lisibilité sans introduire de variable helper. Pas besoin de compromettre la lisibilité.

  • Constantes. x = 1 + 2; devient x = 3; cet exemple simple est saisi tôt par le compilateur, mais se produit au moment JIT lorsque d'autres optimisations rendent cela possible.

  • reproduction. x = a; y = x; devient y = a; cela aide l'allocateur de Registre à faire mieux décision. C'est une grosse affaire dans le jitter x86 parce qu'il a peu de registres pour travailler avec. Le fait de le faire sélectionner les bons est essentiel à perf.

ce sont des optimisations très importantes qui peuvent faire une grande grande différence lorsque, par exemple, vous profilez la construction de débogage de votre application et de le comparer à la construction de la version. Cela n'a d'importance que lorsque le code est sur votre chemin critique, les 5 à 10% du code vous écrivez que en fait affecte le perf de votre programme. L'optimiseur JIT n'est pas assez intelligent pour savoir à l'avance ce qui est critique, il ne peut appliquer que le cadran "turn it to eleven" pour tout le code.

le résultat effectif de ces optimisations sur le temps d'exécution de votre programme est souvent affecté par du code qui court ailleurs. Lire un fichier, exécuter une requête dbase, etc. Faire le travail le JIT optimizer fait complètement invisible. Il n'a pas l'esprit de bien :)

l'optimiseur JIT est un code assez fiable, surtout parce qu'il a été testé des millions de fois. Il est extrêmement rare d'avoir des problèmes dans la version Release build de votre programme. Il arrive cependant. Les jitters x64 et x86 ont tous deux eu des problèmes avec les structures. Le jitter x86 a des problèmes avec la cohérence en virgule flottante, produisant des résultats subtilement différents lorsque les intermédiaires d'un calcul en virgule flottante sont maintenus dans un FPU enregistrez avec une précision de 80 bits au lieu de vous faire tronquer en mémoire.

487
répondu Hans Passant 2017-02-17 10:34:00
  1. Oui, il y a beaucoup de différences de performances et celles-ci s'appliquent vraiment à tout votre code. Debug fait très peu d'optimisation des performances, et le mode de libération beaucoup;

  2. seul le code qui s'appuie sur la constante DEBUG peut fonctionner différemment avec une construction de version. De plus, vous ne devriez pas voir de problèmes.

un exemple de code-cadre qui dépend de la constante DEBUG est la méthode Debug.Assert() , dont l'attribut [Conditional("DEBUG)"] est défini. Cela signifie qu'il dépend aussi de la constante DEBUG et que celle-ci n'est pas incluse dans la construction de la version.

23
répondu Pieter van Ginkel 2010-10-28 14:27:00

Cela dépend fortement de la nature de votre demande. Si votre application est chargée, vous ne remarquerez probablement aucune différence puisque le composant le plus lent connecté à un ordinateur moderne est l'utilisateur. Si vous utilisez certaines animations UI, vous pourriez vouloir tester si vous pouvez percevoir un retard perceptible lors de l'exécution dans DEBUG build.

cependant, si vous avez beaucoup de calculs lourds, alors vous remarquerez des différences (pourrait être aussi haut que 40% que @Pieter mentionnée, mais cela dépend de la nature des calculs).

c'est essentiellement un compromis de design. Si vous lancez sous DEBUG build, alors si les utilisateurs rencontrent des problèmes, vous pouvez obtenir un traceback plus significatif et vous pouvez faire un diagnostic beaucoup plus flexible. En libérant dans DEBUG build, vous évitez également l'optimizer produisant obscur Heisenbugs .

12
répondu Lie Ryan 2010-10-28 15:02:24
  • D'après mon expérience, les applications de taille moyenne ou plus sont nettement plus sensibles dans une version. Essayez votre application et voyez ce que vous ressentez.

  • une chose qui peut vous piquer avec les constructions de publication est que le code de construction de débogage peut parfois supprimer les conditions de course et d'autres bogues liés au threading. Le code optimisé peut entraîner une réorganisation des instructions et une exécution plus rapide peut exacerber certaines conditions de course.

11
répondu Dan Bryant 2010-10-28 14:51:21

vous ne devez jamais sortir un .net Debug construire dans la production. il peut contenir du code laid pour soutenir L'édition-et-Continuer ou qui sait quoi d'autre. Pour autant que je sache, cela ne se produit que dans VB pas C# (note: le post original est étiqueté C#) , mais il devrait tout de même donner raison de s'arrêter sur ce que Microsoft pense qu'ils sont autorisés à faire avec une construction de débogage. En fait, avant .NET 4.0, le code VB fuit la mémoire proportionnellement au nombre de cas de les objets avec des événements que vous créez à l'appui de Modifier et Continuer. (Bien que ceci soit rapporté comme étant fixe par https://connect.microsoft.com/VisualStudio/feedback/details/481671/vb-classes-with-events-are-not-garbage-collected-when-debugging , le code généré a l'air méchant, créant des objets WeakReference et les ajoutant à une liste statique tandis que tenant une serrure ) Je ne veux certainement pas de ce genre de support de débogage dans une production l'environnement!

9
répondu Jason Kresowaty 2010-10-28 23:05:05

d'après mon expérience, la pire chose qui soit sortie du mode de publication est l'obscur"bogues de publication". Puisque le langage il (intermediate language) est optimisé en mode Release, il existe la possibilité de bogues qui ne se seraient pas manifestés en mode Debug. Il ya D'autres questions so couvrant ce problème:

""

cela m'est arrivé une ou deux fois où une simple console app fonctionnerait parfaitement bien en mode Debug, mais avec exactement la même entrée, il y aurait erreur en mode Release. Ces bogues sont extrêmement difficiles à déboguer (par définition en mode de publication, ironiquement).

5
répondu Roly 2017-05-23 12:02:57

je dirais que 1) dépend en grande partie de votre mise en œuvre. Généralement, la différence n'est pas énorme. J'ai fait beaucoup de mesures et souvent Je ne pouvais pas voir une différence. Si vous utilisez du code non géré, beaucoup de tableaux énormes et des trucs comme ça, la différence de performance est légèrement plus grande, mais pas un monde différent (comme en C++). 2) généralement dans le code de version moins d'erreurs sont indiquées (plus grande tolérance), donc un commutateur devrait fonctionner très bien.

3
répondu testalino 2017-10-17 07:22:42
    **Debug Mode:**
    Developer use debug mode for debugging the web application on live/local server. Debug mode allow developers to break the execution of program using interrupt 3 and step through the code. Debug mode has below features:
   1) Less optimized code
   2) Some additional instructions are added to enable the developer to set a breakpoint on every source code line.
   3) More memory is used by the source code at runtime.
   4) Scripts & images downloaded by webresource.axd are not cached.
   5) It has big size, and runs slower.

    **Release Mode:**
    Developer use release mode for final deployment of source code on live server. Release mode dlls contain optimized code and it is for customers. Release mode has below features:
    More optimized code
    Some additional instructions are removed and developer can’t set a breakpoint on every source code line.
   1) Less memory is used by the source code at runtime.
   2) Scripts & images downloaded by webresource.axd are cached.
   3) It has small size, and runs fast.
   4) Scripts & images downloaded by webresource.axd are cached.
   5) It has small size, and runs fast.
0
répondu Nandha kumar 2015-12-17 05:31:04