Diferencias de rendimiento entre compilaciones de depuración y versiones


Debo admitir que generalmente no me he molestado en cambiar entre las configuraciones Debugy Releaseen mi programa, y generalmente he optado por la configuración Debug, incluso cuando los programas están realmente desplegados en el lugar del cliente.

Por lo que sé, la única diferencia entre estas configuraciones si no lo cambia manualmente es que Debug tiene la DEBUG constante definida, y Release tienen la Optimizar código marcado.

Así que mi pregunta es en realidad doble:

  1. Hay muchas diferencias de rendimiento entre estas dos configuraciones. ¿Hay algún tipo específico de código que cause grandes diferencias en el rendimiento aquí, o en realidad no es tan importante?

  2. ¿Hay algún tipo de código que se ejecutará bien bajo la configuración Debug que podría fallar bajo la configuración Release, o puede estar seguro de que el código que se prueba y funciona bien bajo la configuración Debug también funcionará bien bajo la configuración de Release.

Author: shA.t, 2010-10-28

8 answers

El compilador de C# no altera mucho el IL emitido en la compilación de la versión. Notable es que ya no emite los opcodes NOP que le permiten establecer un punto de interrupción en un corsé rizado. El grande es el optimizador que está integrado en el compilador JIT. Sé que hace las siguientes optimizaciones:

  • Método de inserción. Una llamada a un método es reemplazada por la inyección del código del método. Este es uno grande, hace que los accessors de propiedad esencialmente libre.

  • Asignación de registros de CPU. Las variables locales y los argumentos de los métodos pueden permanecer almacenados en un registro de CPU sin ser almacenados (o con menos frecuencia) en el marco de la pila. Este es uno grande, notable por hacer que la depuración de código optimizado sea tan difícil. Y dando un significado a la palabra clave volátil.

  • Eliminación de comprobación de índice de matriz. Una optimización importante cuando se trabaja con matrices (todas las clases de la colección.NET usan una matriz internamente). Cuando el El compilador JIT puede verificar que un bucle nunca indexe una matriz fuera de los límites, entonces eliminará la comprobación de índice. Uno grande.

  • Bucle de desenrollado. Los bucles con cuerpos pequeños se mejoran repitiendo el código hasta 4 veces en el cuerpo y haciendo menos bucles. Reduce el coste de la rama y mejora las opciones de ejecución superescalar del procesador.

  • Eliminación de código Muerto. Una declaración como if (false) {/.../} se elimina completamente. Esto puede ocurrir debido a plegado constante e incrustación. Otros casos es donde el compilador JIT puede determinar que el código no tiene ningún efecto secundario posible. Esta optimización es lo que hace que el código de creación de perfiles sea tan complicado.

  • Código de elevación. El código dentro de un bucle que no se ve afectado por el bucle se puede mover fuera del bucle. El optimizador de un compilador de C pasará mucho más tiempo en encontrar oportunidades para ho. Sin embargo, es una optimización costosa debido al análisis de flujo de datos requerido y el jitter no puede permitir el tiempo por lo que solo ho casos obvios. Forzando a los programadores de. NET a escribir mejor código fuente y elevarse a sí mismos.

  • Eliminación de subexpresión común. x = y + 4; z = y + 4; se convierte en z = x; Bastante común en sentencias como dest[ix+1] = src[ix+1]; escrito para facilitar la lectura sin introducir una variable auxiliar. No hay necesidad de comprometer la legibilidad.

  • Plegado constante. x = 1 + 2; se convierte en x = 3; Este ejemplo simple es captado temprano por el compilador, pero sucede en el momento JIT cuando otras optimizaciones hacen esto posible.

  • Propagación de copias. x = a; y = x; se convierte en y = a; Esto ayuda al asignador de registros a tomar mejores decisiones. Es un gran problema en el jitter x86 porque tiene pocos registros con los que trabajar. Hacer que seleccione los correctos es crítico para perforar.

Estas son optimizaciones muy importantes que pueden hacer una gran diferencia cuando, por ejemplo, perfilas la compilación de depuración de tu aplicación y compáralo con la versión de lanzamiento. Eso solo importa realmente cuando el código está en su ruta crítica, el 5 a 10% del código que escribe que en realidad afecta la perf de su programa. El JIT optimizer no es lo suficientemente inteligente como para saber de antemano lo que es crítico, solo puede aplicar el dial "turn it to eleven" para todo el código.

El resultado efectivo de estas optimizaciones en el tiempo de ejecución de su programa a menudo se ve afectado por el código que se ejecuta en otro lugar. Leer un archivo, ejecutar una consulta dbase, etc. Haciendo el trabajo que el optimizador JIT hace completamente invisible. Sin embargo, no le importa:)

El JIT optimizer es un código bastante confiable, principalmente porque se ha puesto a prueba millones de veces. Es extremadamente raro tener problemas en la versión Release build de su programa. Sin embargo, sucede. Tanto el nerviosismo x64 como el x86 han tenido problemas con las estructuras. El jitter x86 tiene problemas con la consistencia de punto flotante, produciendo sutilmente diferentes resultados cuando los intermedios de un cálculo de punto flotante se mantienen en un registro FPU con una precisión de 80 bits en lugar de truncarse cuando se descargan a la memoria.

 487
Author: Hans Passant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-17 10:34:00
  1. Sí, hay muchas diferencias de rendimiento y estas realmente se aplican en todo su código. Debug hace muy poca optimización del rendimiento, y el modo de liberación mucho;

  2. Solo el código que se basa en la constante DEBUG puede funcionar de manera diferente con una compilación de release. Además de eso, no deberías ver ningún problema.

Un ejemplo de código de framework que depende de la constante DEBUG es el método Debug.Assert(), que tiene definido el atributo [Conditional("DEBUG)"]. Esto significa que también depende de la constante DEBUG y esto no está incluido en la compilación de la versión.

 23
Author: Pieter van Ginkel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-28 14:27:00

Esto depende en gran medida de la naturaleza de su aplicación. Si su aplicación es IU-heavy, probablemente no notará ninguna diferencia ya que el componente más lento conectado a un equipo moderno es el usuario. Si utiliza algunas animaciones de interfaz de usuario, es posible que desee probar si puede percibir algún retraso notable cuando se ejecuta en la compilación de DEPURACIÓN.

Sin embargo, si tiene muchos cálculos pesados de computación, entonces notará diferencias (podrían ser tan altas como el 40% como mencionó @Pieter, aunque lo haría depende de la naturaleza de los cálculos).

Es básicamente una compensación de diseño. Si está lanzando bajo compilación de DEPURACIÓN, entonces si los usuarios experimentan problemas, puede obtener un seguimiento más significativo y puede hacer un diagnóstico mucho más flexible. Al liberar en la compilación de DEPURACIÓN, también evita que el optimizador produzca oscuros Heisenbugs .

 12
Author: Lie Ryan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-28 15:02:24
  • Mi experiencia ha sido que las aplicaciones de tamaño mediano o grande son notablemente más sensibles en una versión. Pruébelo con su aplicación y vea cómo se siente.

  • Una cosa que puede morderte con las compilaciones de versiones es que el código de compilación de depuración a veces puede suprimir las condiciones de carrera y otros errores relacionados con el subproceso. El código optimizado puede dar lugar a un reordenamiento de las instrucciones y una ejecución más rápida puede exacerbar ciertas condiciones de carrera.

 11
Author: Dan Bryant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-28 14:51:21

Nunca debe lanzar una compilación de depuración. NET en producción. Puede contener código feo para soportar Editar y Continuar o quién sabe qué más. Por lo que sé, esto sucede solo en VB no en C# (nota: la publicación original está etiquetada con C#), pero todavía debería dar razones para hacer una pausa en cuanto a lo que Microsoft piensa que se les permite hacer con una compilación de depuración. De hecho, antes de. NET 4.0, el código VB pierde memoria de forma proporcional al número de instancias de objetos con eventos que se construyen en apoyo de Editar y Continuar. (Aunque esto se informa que se fija por https://connect.microsoft.com/VisualStudio/feedback/details/481671/vb-classes-with-events-are-not-garbage-collected-when-debugging, el código generado se ve desagradable, creando WeakReference objetos y agregándolos a una lista estática mientras mantiene un bloqueo) Ciertamente no quiero ningún tipo de este tipo de soporte de depuración en un entorno de producción!

 9
Author: Jason Kresowaty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-28 23:05:05

En mi experiencia, lo peor que ha salido del modo de liberación son los oscuros "errores de liberación". Dado que el IL (lenguaje intermedio) está optimizado en el modo de liberación, existe la posibilidad de errores que no se habrían manifestado en el modo de depuración. Hay otras preguntas que cubren este problema: Razones comunes para que los errores en la versión de lanzamiento no estén presentes en el modo de depuración

Esto me ha pasado una o dos veces donde una simple aplicación de consola se ejecutaría perfectamente bien en Debug modo, pero dada la misma entrada exacta, se produciría un error en el modo de liberación. Estos errores son extremadamente difíciles de depurar (por definición del modo de liberación, irónicamente).

 5
Author: Roly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:57

Yo diría que 1) depende en gran medida de su implementación. Por lo general, la diferencia no es tan grande. Hice muchas mediciones y a menudo no podía ver la diferencia. Si usas código no administrado, muchas matrices enormes y cosas por el estilo, la diferencia de rendimiento es un poco mayor, pero no un mundo diferente (como en C++). 2) Por lo general, en el código de lanzamiento se muestran menos errores (mayor tolerancia), por lo tanto, un interruptor debería funcionar bien.

 3
Author: testalino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
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
Author: Nandha kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-17 05:31:04