C++/CLI y C#: Asombrosas diferencias en el optimizador de código (y V)

Vamos para atrás, como los cangrejos. Vamos a finalizar esta serie de entradas no planeadas con un rápido repaso a nuestro código en C++/CLI compilado bajo Visual Studio 2008.


En primer lugar, recordemos el código en cuestión:

// TestCpp1.cpp : main project file. 

#include «stdafx.h»

using namespace System;

ref class Program
{
public:
static void CallPrint(void)
{
Console::WriteLine(«CallPrint»);
}
static void DoWork(void)
{
for(int i=0;i<1000;i++)
CallPrint();
}
};

int main(array<System::String ^> ^args)
{
Program::DoWork();
Console::WriteLine(L«Hello World»);
return 0;
}


Luego nos vamos a una instalación limpia del Visual Studio 2008 y creamos un proyecto, cambiando la configuración a Release.


Compilemos y comprobemos:


image


Lo que digo, un paso hacia atrás.


¡Ahora el C++/CLI genera el mismo código mierdoso que el C#!


Ya sabemos por qué compila más rápido, o con otras palabras: compila igual de mal que el C#.


Pero si nos vamos a las opciones del proyecto, y cambiamos el nivel de optimización por Full Optimization, podemos ver que el compilador sigue siendo igual de bueno, excepto que le han cambiado el comportamiento por defecto:


image


Vemos que todo ha sido un mal sueño.


Ahora volvamos al código en C#, el que nos permite mirar cómo actua el jitter:

using System;
using System.Collections.Generic;
using System.Text;

namespace TestCS1
{
class Program
{
static void CallPrint()
{
//Console.WriteLine(«CallPrint»);
}
static void DoWork()
{
for (int i = 0; i < 1000; i++)
CallPrint();
}
static void Main(string[] args)
{
for(uint i=0;i<UInt32.MaxValue;i++)
//while(true)
DoWork();
Console.WriteLine(«Hello World»);
}
}
}


Hagamos los pasos adecuados para obtener el código desensamblado y pasado por el optimizador, es decir, compilar y lanzar el proyecto sin el depurador y luego capturarlo con el Visual Studio:


image


No hace falta ni que miremos el código en ensamblador: lo hemos parado dentro del bucle que debería haber desaparecido.


Resumiendo: un pasito para atrás en cuanto a C++/CLI, y por otro lado, siempre lo mismo en cuanto al jitter.

6 comentarios sobre “C++/CLI y C#: Asombrosas diferencias en el optimizador de código (y V)”

  1. Hola,

    hay bastante gente por ahí hablando del IL ahora, mira este post:

    http://blogs.msdn.com/ericlippert/archive/2007/08/17/subtleties-of-c-il-codegen.aspx

    (linkea unos cuantos más interesantes)

    La verdad que no te se explicar que pasa, pero sinceramente dudo que las cosas sean tan «malas» como las pintas en tus posts, pero no llego a tanto nivel (aunque lo mismo en los foros de MSDN te pueden contestar a estas cosas).

    Por cierto, ¿para cuando las comparaciones de tiempo? :p Un saludo!

    Vicente

  2. Las pruebas están ahí. Han resistido con ligeras modificaciones todos los intentos de refutarlas. De hecho, de momento (aunque no llevan mucho tiempo puestas), en los privados de los MVPs nadie ha chistado (y que conste que allí he sido mucho más duro).

    Respecto a las pruebas de rendimiento de momento no las voy a hacer; para mi está claro lo que quería demostrar, pero son fáciles. Cambia el WriteLine por una operación matemática y lanza el profiler del Visual Studio.

    Mañana leeré el link que me pones. 🙂

  3. Lo del compilador haciendo debug no me extraña, ya que aunque lo compiles en modo release el te va a dejar hacerlo aunque se vale de un caché cosa que he podido verificar cuando por alguna extraña razon comienzas a debugguar un programa en modo release despues de haberlo hecho en modo debug, pues el sigue recorriendo a travez de los mismo simbolos.

    En cuanto a la generación de código : ya revisaste compilando desde el command prompt con las opciones maximas de optimizacion?

    Es curioso el porque sucede eso, pero en pruebas de performance cada vz que lanzas un programa en modo release easde visual studio el programa es mucho mas lento que enviandolo en modo release que desde consola, y ya que te encuentras haciendo pruebas valdria la pena verificar el codigo generado con opciones de compilacion desde consola contra el generado desde vs.

    Otra cosa que tambien deberias de tener en cuenta es que lo mas importante es el codigo generado despues de pasara por elk JIT porque finalmente el CIL es solo u codigo intermedio y el codigo nunca se ejecuta directamente desde CIL sino que pasa por el JIT y luego se ejecuta ya en lenguaje nativo. Has pruebas con NGEN y compara los codigos resultantes. Usando NGEN tienes un parametro de comparacion mas justo.

    Saludos.

  4. Solo me quedaría lo del ngen. Lo demás está comprobado. Si te fijas en las entradas anteriores de la serie ya me han comentado todo eso y he ido haciéndolo.

    Estas pruebas son lanzando la aplicación fuera del IDE y luego cogiéndola con él.

  5. Hombre, has demostrado que el IL de C++/CLI es más corto que el de C#, pero sin una muestra de rendimientos no podemos saber que significa exactamente 🙂 (ya que en el fondo lo que ocupen en memoria y en disco los programas es insignificante).

    Vamos, que ya que te has currado 5 artículos sobre el IL, un par de profiling no cuestan nada de nada :p

    Un saludo!

    Vicente

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *