web-dev-qa-db-fra.com

Différences de performances entre les versions de débogage et de version

Je dois admettre que d'habitude, je n'ai pas pris la peine de basculer entre les configurations Debug et Release de mon programme, et j'ai généralement opté pour l'option = Debug configuration, même lorsque les programmes sont réellement déployés chez le client.

Autant que je sache, la seule différence entre ces configurations si vous ne le modifiez pas manuellement est que Debug avez le DEBUG défini, et Release faites cocher la case Optimiser le code.

Donc, ma question est en fait double:

  1. Existe-t-il de grandes différences de performances entre ces deux configurations? Existe-t-il un type de code spécifique susceptible d’entraîner de grandes différences de performances, ou n’est-ce pas si important?

  2. Existe-t-il un type de code qui fonctionne correctement sous la configuration Debug qui pourrait échouer sous la configuration Release, ou pouvez-vous être sûr que le code testé et fonctionne bien sous la configuration Debug fonctionnera également bien sous la configuration de la version.

273
Øyvind Bråthen

Le compilateur C # lui-même ne modifie pas beaucoup le IL émis dans la version Release. Il convient de noter qu’il n’émet plus les codes opération NOP qui vous permettent de définir un point d’arrêt sur une accolade. Le plus important est l'optimiseur intégré au compilateur JIT. Je sais que cela fait les optimisations suivantes:

  • Méthode en ligne. Un appel de méthode est remplacé par l’injection du code de la méthode. C’est un gros projet qui rend les accesseurs de propriété essentiellement gratuits.

  • Allocation du registre de la CPU. Les variables locales et les arguments de méthode peuvent rester stockés dans un registre de la CPU sans jamais (ou moins fréquemment) être stockés dans le cadre de la pile. C'est un gros problème, qui rend difficile le débogage d'un code optimisé. Et donner une signification au mot-clé volatile.

  • Elimination de la vérification d'index de tableau. Une optimisation importante lorsque vous travaillez avec des tableaux (toutes les classes de la collection .NET utilisent un tableau en interne). Lorsque le compilateur JIT peut vérifier qu'une boucle n'indexe jamais un tableau en dehors des limites, la vérification de l'index est alors éliminée. Un gros.

  • Boucle qui se déroule. 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 succursale et améliore les options d'exécution super-scalaires du processeur.

  • Élimination du code mort. Une déclaration du type if (false) {/.../} est complètement éliminée. Cela peut se produire en raison du pliage et de l'inline continus. 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 difficile.

  • Code de levage. Le code dans une boucle qui n'est pas affectée par la boucle peut être retiré de la boucle. L'optimiseur d'un compilateur C passera beaucoup plus de temps à rechercher des opportunités de levage. Cependant, il s’agit d’une optimisation coûteuse en raison de l’analyse des flux de données requise, et la gigue ne permet pas de gagner du temps. Forcer les programmeurs .NET à écrire un meilleur code source et à se hisser eux-mêmes.

  • Élimination de sous-expression commune. x = y + 4; z = y + 4; devient z = x; Assez commun dans des déclarations comme dest [ix + 1] = src [ix + 1]; écrit pour la lisibilité sans introduire de variable auxiliaire. Pas besoin de compromettre la lisibilité.

  • Pliage constant. x = 1 + 2; devient x = 3; Cet exemple simple est saisi tôt par le compilateur, mais se produit au moment de JIT, lorsque d'autres optimisations le permettent.

  • Copier la propagation. x = a; y = x; devient y = a; Cela aide l’allocateur de registre à prendre de meilleures décisions. C'est un gros problème dans la gigue x86 car il a peu de registres pour travailler. Il est essentiel de sélectionner les bons.

Ce sont des optimisations très importantes qui peuvent faire une différence grande lorsque, par exemple, vous profilez la version Debug de votre application et la comparez à la version Release. Cela n'a vraiment d'importance que lorsque le code est sur votre chemin critique, les 5 à 10% du code que vous écrivez que réellement affecte la performance de votre programme. L'optimiseur JIT n'est pas assez intelligent pour savoir dès le départ ce qui est critique, il ne peut appliquer que le cadran "le tourner à onze" 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 exécuté ailleurs. Lecture d'un fichier, exécution d'une requête dbase, etc. Rendre le travail totalement invisible par l'optimiseur JIT. Ça ne me dérange pas si :)

L'optimiseur JIT est un code assez fiable, principalement parce qu'il a été mis à l'épreuve des millions de fois. Il est extrêmement rare d’avoir des problèmes dans la version release de votre programme. Cela arrive cependant. Les tremblements x64 et x86 ont tous deux eu des problèmes de struct. La gigue x86 pose des problèmes de cohérence en virgule flottante, produisant des résultats légèrement différents lorsque les intermédiaires d'un calcul en virgule flottante sont conservés dans un registre FPU avec une précision de 80 bits au lieu d'être tronqués lorsqu'ils sont vidés en mémoire.

504
Hans Passant
  1. Oui, il existe de nombreuses différences de performances, qui s'appliquent vraiment à tout votre code. Le débogage optimise très peu les 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 version release. En plus de cela, vous ne devriez voir aucun problème.

Un exemple de code d'infrastructure qui dépend de la constante DEBUG est la méthode Debug.Assert(), qui définit l'attribut [Conditional("DEBUG)"]. Cela signifie que cela dépend également de la constante DEBUG et que cela n'est pas inclus dans la version de publication.

23
Pieter van Ginkel

Cela dépend fortement de la nature de votre application. Si votre application nécessite beaucoup d’UI, vous ne remarquerez probablement aucune différence, car le composant le plus lent connecté à un ordinateur moderne est l’utilisateur. Si vous utilisez certaines animations de l'interface utilisateur, vous pouvez tester si vous pouvez percevoir un décalage notable lors de l'exécution dans la version DEBUG.

Toutefois, si vous avez beaucoup de calculs à faire, vous remarquerez des différences (pouvant atteindre 40%, comme l'a mentionné @Pieter, bien que cela dépende de la nature des calculs).

C'est fondamentalement un compromis de conception. Si vous publiez sous DEBUG, si les utilisateurs rencontrent des problèmes, vous pouvez obtenir une trace plus significative et un diagnostic beaucoup plus souple. En libérant dans la compilation DEBUG, vous évitez également que l'optimiseur produise obscure Heisenbugs .

12
Lie Ryan
  • D'après mon expérience, les applications de taille moyenne ou plus grandes sont nettement plus réactives dans une version Release. Essayez-la avec votre application et voyez comment elle se sent.

  • Une chose qui peut vous mordre avec les versions Release est que le code de construction Debug peut parfois supprimer les conditions de concurrence et d’autres bogues liés aux threads. Un code optimisé peut entraîner une réorganisation des instructions et une exécution plus rapide peut exacerber certaines conditions de concurrence.

11
Dan Bryant

Vous ne devriez jamais publier une version .NET Debug en production. Elle peut contenir du code moche pour prendre en charge l'édition en continu ou qui sait quoi d'autre. Autant que je sache, cela ne se produit que dans VB pas C # (note: le message original est marqué C #) , mais il devrait quand même donner raison de faire une pause sur ce que Microsoft pense qu’ils sont autorisés à faire avec une construction Debug. En fait, avant .NET 4.0, VB le code perd de la mémoire proportionnellement au nombre d’occurrences d’objets avec événements que vous construisez en supportant Edit-and-Continue (bien que cela soit signalé comme étant résolu par https://connect.Microsoft.com/VisualStudio/feedback/details/481671/vb-classes-with-events -are-not-garbage-collection-when-debugging , le code généré a l'air méchant, il crée des objets WeakReference et les ajoute à une liste statique tout en maintenant un verrou ) Je ne veux certainement pas de ce type de support de débogage dans un environnement de production!

9
Jason Kresowaty

D'après mon expérience, la pire chose qui soit sortie du mode Release est l'obscur "bugs de release". Puisque le langage intermédiaire (IL) est optimisé en mode de publication, il est possible que des bogues ne se soient pas manifestés en mode de débogage. Il existe d’autres SO questions traitant de ce problème: Causes courantes des bogues dans la version publiée non présents en mode débogage

Cela m'est arrivé une ou deux fois lorsqu'une application de console simple fonctionnerait parfaitement en mode débogage, mais avec la même entrée, une erreur se produirait en mode de publication. Ces bugs sont extrêmement difficiles à déboguer (par définition, le mode Release, ironiquement).

5
Roly

Je dirais que 1) dépend en grande partie de votre mise en œuvre. Habituellement, la différence n'est pas si é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é, de nombreux tableaux énormes et ce genre de choses, la différence de performances est légèrement plus grande, mais ce n'est pas un monde différent (comme en C++). 2) Généralement, dans le code de version, moins d’erreurs sont affichées (tolérance plus élevée), un commutateur devrait donc fonctionner correctement.

3
testalino
    **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
Nandha kumar