Debo admitir, que por lo general yo no he molestado el cambio entre el de Depuración y Liberación configuraciones en mi programa, y he optado por ir por la de Depuración de configuración, incluso cuando los programas se desplegó en el lugar de los clientes.
Hasta donde yo sé, la única diferencia entre estas configuraciones si no cambia de forma manual es que de Depuración tienen la DEBUG
constante definida, y Liberación tienen la Optimizar el código marcado.
Así que mi pregunta es en realidad doble:
-
Hay mucha diferencias de rendimiento entre estas dos configuraciones. ¿Hay algún tipo específico de código que va a causar grandes diferencias en el rendimiento de aquí, o es que realmente no es tan importante?
-
¿Hay algún tipo de código que se ejecuta bien en virtud de la de Depuración configuración que pueda fallar en Liberación de configuración, o puede usted estar seguro de que el código que está probado y funcionando muy bien en el de Depuración de configuración va a funcionar bajo la configuración de Lanzamiento.
- Relacionados: stackoverflow.com/questions/33871181/…
El compilador de C# no alterar la emisión IL mucho en la versión de Lanzamiento. Notable es que ya no se emite el NOP códigos de operación que permiten establecer un punto de interrupción en una llave. El grande es el optimizador de que la integrada en el compilador JIT. Sé que hace las siguientes optimizaciones:
Método inline. Una llamada al método se sustituye por el de inyectar el código del método. Este es un grande, hace descriptores de acceso esencialmente libre.
Registro de CPU de asignación. Las variables locales y argumentos de método puede permanecer almacenado en un registro de CPU sin (o con menos frecuencia) se almacena de regreso al marco de pila. Este es un grande, notable para hacer la depuración de código optimizado tan difícil. Y dando la volátiles las palabras clave de un significado.
Índice de la matriz de comprobación de la eliminación. Una importante optimización cuando se trabaja con matrices (de todos .NET clases de colección de utilizar una matriz internamente). Cuando el compilador JIT, se puede comprobar que un bucle nunca los índices de un array fuera de los límites, a continuación, se eliminará el índice de verificación. Uno grande.
Bucle desenrollado. Bucles con cuerpos pequeños, mejoran de repetir el código de 4 veces en el cuerpo de un bucle de menos. Reduce la rama de costos y mejora el procesador de super-escalar las opciones de ejecución.
Eliminación de código muerto. Una declaración como if (false) { /…/} consigue completamente eliminado. Esto puede ocurrir debido a la constante plegable y alineaciones. Otro de los casos es donde el compilador JIT, se puede determinar que el código no tiene ningún efecto secundario posible. Esta optimización es lo que hace el código de generación de perfiles tan complicado.
Código de elevación. El código dentro de un bucle que no está afectada por el bucle se puede mover fuera del bucle. El optimizador de un compilador de C va a pasar mucho más tiempo en la búsqueda de oportunidades para la grúa. Sin embargo es una cara de optimización debido a la necesidad de flujo de datos y análisis de la fluctuación no puede permitirse el tiempo tan sólo polipastos casos obvios. Forzando .NET programadores a escribir mejor código fuente y de la grúa a sí mismos.
Común de la sub-expresión de la eliminación. x = y + 4; z = y + 4; se hace z = x; Bastante común en declaraciones como dest[ix+1] = src[ix+1]; escrito para mejorar la legibilidad, sin la introducción de una variable auxiliar. No hay necesidad de comprometer la legibilidad.
Constante de plegado. x = 1 + 2; se convierte en x = 3; Este simple ejemplo se detecta temprano por el compilador, pero que sucede en el JIT tiempo cuando otras optimizaciones que esto sea posible.
Copia de propagación. x = a; y = x; se convierte en y = a; Esto ayuda a que el registro de asignación de tomar mejores decisiones. Es una gran cosa en el x86 jitter porque tiene pocos registros para trabajar con. Tener que seleccionar los más adecuados es fundamental para perf.
Estos son muy importantes optimizaciones que pueden hacer que un gran gran diferencia cuando, por ejemplo, el perfil de la compilación de Depuración de la aplicación y la comparamos con la versión de Lanzamiento. Que la única que realmente importa, sin embargo, cuando el código está en la ruta crítica, el 5 al 10% de el código de escritura que en realidad afecta a la perf de su programa. El JIT optimizador no es lo suficientemente inteligente como para saber lo que es fundamental, sólo puede aplicar la «vuelta a las once» marcado para todo el código.
El resultado efectivo de estas optimizaciones en su ejecución del programa el tiempo es a menudo afectada por el código que se ejecuta en otros lugares. La lectura de un archivo, ejecutar una consulta de dbase, etc. Hacer el trabajo que el JIT optimizador hace completamente invisible. No cuenta, sin embargo 🙂
El JIT optimizer es bastante fiable de código, sobre todo porque se ha puesto a la prueba de millones de veces. Es muy raro tener problemas en la versión de Lanzamiento de la versión de su programa. Sucede sin embargo. Tanto x64 y x86 nerviosismo ha tenido problemas con las estructuras. El x86 jitter tiene problemas con punto flotante de consistencia, produciendo sutilmente diferentes resultados cuando los productos intermedios de punto flotante, el cálculo se mantienen en un FPU registrarse en 80 bits de precisión en lugar de obtener truncado cuando tiraba a la memoria.
LinkedList<T>
no, aunque no se utiliza muy a menudo.volatile
palabra clave no se aplica a las variables locales se almacenan en un marco de pila. A partir de la documentación en msdn.microsoft.com/en-us/library/x13ttww7.aspx: «La palabra clave volatile sólo puede ser aplicado a los campos de una clase o estructura. Las variables locales pueden ser declaradas volátil».Debug
yRelease
construye en este sentido es la «optimizar el código» casilla de verificación que se encuentra normalmente en paraRelease
, pero fuera deDebug
. Es sólo para asegurarse de que los lectores no empezar a pensar que hay «magia», invisibles las diferencias entre las dos configuraciones de compilación que van más allá de lo que se encuentra en la página de propiedades del proyecto en Visual Studio.Sí, hay muchas diferencias de rendimiento y estos realmente se aplican en todo el código. Depurar hace muy poco la optimización del rendimiento, y el modo de disparador mucho;
Sólo el código que se basa en la
DEBUG
constante puede realizar de forma diferente con una versión de lanzamiento. Además de eso, usted no debería ver ningún problema.Un ejemplo de marco de trabajo de código que depende de la
DEBUG
constante es laDebug.Assert()
método, que tiene el atributo de[Conditional("DEBUG)"]
definido. Esto significa que también depende de laDEBUG
constante y esto no está incluido en la versión de lanzamiento.DEBUG
:AppDomain.CurrentDomain.GetAssemblies().Sum(p => p.GetTypes().Sum(p1 => p1.GetProperties().Length))
.asp.net
y el uso de depuración en lugar de la liberación de algunas secuencias de comandos pueden ser añadidos en la página, tales como:MicrosoftAjax.debug.js
que tiene unos 7k líneas.Esto depende en gran medida de la naturaleza de su aplicación. Si su aplicación es la interfaz de usuario pesado, probablemente no notará ninguna diferencia desde el componente más lento conectado a un ordenador moderno es el usuario. Si utiliza una interfaz de usuario animaciones, es posible que desee probar si se puede percibir notable retraso cuando se ejecuta en la versión de DEPURACIÓN.
Sin embargo, si usted tiene muchos de cálculo pesados cálculos, entonces te darías cuenta de las diferencias (podría ser tan alto como el 40% como @Pieter de mencionar, aunque dependerá de la naturaleza de los cálculos).
Es básicamente un diseño de equilibrio. Si usted está liberando en virtud de la generación de DEPURACIÓN, entonces, si las experiencias de los usuarios de los problemas, usted puede obtener más significativos sobre la procedencia del producto y que pueden hacer mucho más flexible de diagnóstico. Por la liberación en la generación de DEPURACIÓN, que también se evita el optimizador de la producción de ocultar Heisenbugs.
Mi experiencia ha sido que las medianas o grandes aplicaciones son notablemente más sensible en una versión de Lanzamiento. Pruébalo con tu aplicación y ver cómo se siente.
Una cosa que puede morder con las versiones de Lanzamiento es que la versión de Depuración de código a veces puede suprimir las condiciones de carrera y otros roscado relacionados con errores. Código optimizado puede resultar en la instrucción de reordenación y de ejecución más rápido puede exacerbar ciertas condiciones de carrera.
Nunca se debe soltar una .RED de Depuración en la producción. Puede contener feo código para apoyar a Editar y Continuar o quién sabe qué otra cosa. Hasta donde yo sé, esto sucede sólo en VB no C# (nota: el post original está etiquetada C#), pero que todavía debe dar la razón para hacer una pausa en cuanto a lo que Microsoft piensa que se puede hacer con una versión de Depuración. De hecho, antes de la .NET 4.0, el código de VB fugas de memoria proporcional al número de instancias de objetos con eventos que se construye en apoyo de Editar y Continuar. (Aunque esto es informado de 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 de aspecto desagradable, la creación de
WeakReference
los objetos y añadirlos a una lista estática mientras mantiene un bloqueo) yo ciertamente no quiero ninguna de este tipo de soporte de depuración en un entorno de producción!En mi experiencia, lo peor que ha salido de la Liberación modo oscura de la «liberación de errores». Desde la IL (intermediate language) es optimizado en modo de Lanzamiento, existe la posibilidad de errores que no se han manifestado en modo de Depuración. Hay otros PARA preguntas relativas a este problema:
Las razones más comunes para bugs en la versión no está presente en el modo de depuración
Esto me ha sucedido una o dos veces donde una sencilla aplicación de consola iba a ejecutar a la perfección en el modo de Depuración, pero dada la exacta misma entrada, sería error en el modo de Lanzamiento. Estos errores son MUY difíciles de depurar (por la definición de modo de Lanzamiento, irónicamente).
Yo diría que 1) depende en gran medida de su aplicación. Generalmente, la diferencia no es enorme. Hice muchas de las mediciones y, a menudo, no podía ver una diferencia. Si utiliza el código no administrado, un montón de grandes matrices y cosas por el estilo, la diferencia de rendimiento es ligeramente más grande, pero no un mundo diferente (como en C++). 2) por lo general en el código de liberación menos errores se muestran (mayor tolerancia), por lo tanto, un interruptor debería funcionar bien.