Soy un desarrollador de C ++ y C #. He desarrollado aplicaciones C # desde la primera versión beta del framework .NET y tengo más de 20 años de experiencia en el desarrollo de aplicaciones C ++. En primer lugar, el código C # NUNCA será más rápido que una aplicación C ++, pero no pasaré por una larga discusión sobre el código administrado, cómo funciona, la capa inter-op, los componentes internos de la administración de memoria, el sistema de tipos dinámicos y el recolector de basura. Sin embargo, permítanme continuar diciendo que los puntos de referencia enumerados aquí producen resultados INCORRECTOS.
Déjame explicarte: lo primero que debemos considerar es el compilador JIT para C # (.NET Framework 4). Ahora, el JIT produce código nativo para la CPU utilizando varios algoritmos de optimización (que tienden a ser más agresivos que el optimizador C ++ predeterminado que viene con Visual Studio) y el conjunto de instrucciones utilizado por el compilador .NET JIT es un reflejo más cercano de la CPU real. en la máquina, por lo que se podrían realizar ciertas sustituciones en el código de la máquina para reducir los ciclos de reloj y mejorar la tasa de aciertos en la caché de la canalización de la CPU y producir más optimizaciones de hiperprocesamiento, como el reordenamiento de instrucciones y mejoras relacionadas con la predicción de rama.
Lo que esto significa es que a menos que compile su aplicación C ++ usando los parámetros correctos para la compilación RELEASE (no la compilación DEBUG), su aplicación C ++ puede funcionar más lentamente que la correspondiente aplicación basada en C # o .NET. Al especificar las propiedades del proyecto en su aplicación C ++, asegúrese de habilitar "optimización completa" y "favorecer el código rápido". Si tiene una máquina de 64 bits, DEBE especificar generar x64 como plataforma de destino; de lo contrario, su código se ejecutará a través de una subcapa de conversión (WOW64) que reducirá sustancialmente el rendimiento.
Una vez que realiza las optimizaciones correctas en el compilador, obtengo .72 segundos para la aplicación C ++ y 1.16 segundos para la aplicación C # (ambos en la versión de compilación). Dado que la aplicación C # es muy básica y asigna la memoria utilizada en el bucle en la pila y no en el montón, en realidad se está desempeñando mucho mejor que una aplicación real involucrada en objetos, cálculos pesados y con conjuntos de datos más grandes. Entonces, las cifras proporcionadas son cifras optimistas sesgadas hacia C # y el marco .NET. Incluso con este sesgo, la aplicación C ++ se completa en poco más de la mitad del tiempo que la aplicación C # equivalente. Tenga en cuenta que el compilador de Microsoft C ++ que utilicé no tenía las optimizaciones correctas de canalización y subprocesamiento (usando WinDBG para ver las instrucciones de ensamblaje).
Ahora bien, si usamos el compilador Intel (que por cierto es un secreto de la industria para generar aplicaciones de alto rendimiento en procesadores AMD / Intel), el mismo código se ejecuta en .54 segundos para el ejecutable C ++ frente a .72 segundos usando Microsoft Visual Studio 2010 Entonces, al final, los resultados finales son .54 segundos para C ++ y 1.16 segundos para C #. Por tanto, el código producido por el compilador .NET JIT tarda un 214% más que el ejecutable de C ++. La mayor parte del tiempo invertido en los .54 segundos fue para obtener el tiempo del sistema y no dentro del bucle en sí.
Lo que también falta en las estadísticas son los tiempos de inicio y limpieza que no están incluidos en los tiempos. Las aplicaciones C # tienden a dedicar mucho más tiempo al inicio y finalización que las aplicaciones C ++. La razón detrás de esto es complicada y tiene que ver con las rutinas de validación de código en tiempo de ejecución .NET y el subsistema de administración de memoria que realiza mucho trabajo al principio (y en consecuencia, al final) del programa para optimizar las asignaciones de memoria y la basura. coleccionista.
Al medir el rendimiento de C ++ y .NET IL, es importante mirar el código ensamblador para asegurarse de que TODOS los cálculos estén ahí. Lo que encontré es que sin poner código adicional en C #, la mayor parte del código en los ejemplos anteriores se eliminó del binario. Este también fue el caso con C ++ cuando usó un optimizador más agresivo como el que viene con el compilador Intel C ++. Los resultados que proporcioné anteriormente son 100% correctos y están validados a nivel de ensamblaje.
El principal problema con muchos foros en Internet es que muchos novatos escuchan la propaganda de marketing de Microsoft sin comprender la tecnología y hacen afirmaciones falsas de que C # es más rápido que C ++. La afirmación es que, en teoría, C # es más rápido que C ++ porque el compilador JIT puede optimizar el código para la CPU. El problema con esta teoría es que existe una gran cantidad de plomería en el marco .NET que ralentiza el rendimiento; plomería que no existe en la aplicación C ++. Además, un desarrollador experimentado sabrá cuál es el compilador correcto para usar para la plataforma dada y usará los indicadores apropiados al compilar la aplicación. En las plataformas Linux o de código abierto, esto no es un problema porque puede distribuir su fuente y crear scripts de instalación que compilen el código utilizando la optimización adecuada. En Windows o plataforma de código cerrado, tendrá que distribuir varios ejecutables, cada uno con optimizaciones específicas. Los binarios de Windows que se implementarán se basan en la CPU detectada por el instalador de msi (mediante acciones personalizadas).