Sou um desenvolvedor C ++ e C #. Tenho desenvolvido aplicativos C # desde a primeira versão beta do .NET framework e tenho mais de 20 anos de experiência no desenvolvimento de aplicativos C ++. Em primeiro lugar, o código C # NUNCA será mais rápido do que um aplicativo C ++, mas não vou passar por uma longa discussão sobre o código gerenciado, como ele funciona, a camada de interoperabilidade, componentes internos de gerenciamento de memória, o sistema de tipo dinâmico e o coletor de lixo. No entanto, deixe-me continuar dizendo que todos os benchmarks listados aqui produzem resultados INCORRETOS.
Deixe-me explicar: a primeira coisa que precisamos considerar é o compilador JIT para C # (.NET Framework 4). Agora, o JIT produz código nativo para a CPU usando vários algoritmos de otimização (que tendem a ser mais agressivos do que o otimizador C ++ padrão que vem com o Visual Studio) e o conjunto de instruções usado pelo compilador .NET JIT é um reflexo mais próximo da CPU real na máquina, de modo que certas substituições no código da máquina possam ser feitas para reduzir os ciclos de clock e melhorar a taxa de acerto no cache do pipeline da CPU e produzir mais otimizações de hyper-threading, como reordenamento de instruções e melhorias relacionadas à previsão de ramificação.
O que isso significa é que, a menos que você compile seu aplicativo C ++ usando os parâmetros corretos para o build RELEASE (não o build DEBUG), seu aplicativo C ++ pode executar mais lentamente do que o aplicativo baseado em C # ou .NET correspondente. Ao especificar as propriedades do projeto em seu aplicativo C ++, certifique-se de habilitar "otimização total" e "favorecer código rápido". Se você tiver uma máquina de 64 bits, você DEVE especificar gerar x64 como a plataforma de destino, caso contrário, seu código será executado por meio de uma subcamada de conversão (WOW64) que reduzirá substancialmente o desempenho.
Depois de executar as otimizações corretas no compilador, obtenho 0,72 segundo para o aplicativo C ++ e 1,16 segundo para o aplicativo C # (ambos na versão de compilação). Como o aplicativo C # é muito básico e aloca a memória usada no loop na pilha e não no heap, ele está, na verdade, tendo um desempenho muito melhor do que um aplicativo real envolvido em objetos, cálculos pesados e com conjuntos de dados maiores. Portanto, os números fornecidos são números otimistas tendenciosos para C # e a estrutura .NET. Mesmo com essa tendência, o aplicativo C ++ é concluído em pouco mais da metade do tempo do que o aplicativo C # equivalente. Lembre-se de que o compilador Microsoft C ++ que usei não tinha o pipeline correto e as otimizações de hyperthreading (usando WinDBG para visualizar as instruções de montagem).
Agora, se usarmos o compilador Intel (que, a propósito, é um segredo da indústria para gerar aplicativos de alto desempenho em processadores AMD / Intel), o mesmo código será executado em 0,54 segundos para o executável C ++ versus 0,72 segundos usando o Microsoft Visual Studio 2010 . Portanto, no final, os resultados finais são 0,54 segundos para C ++ e 1,16 segundos para C #. Portanto, o código produzido pelo compilador .NET JIT leva 214% mais tempo do que o executável C ++. A maior parte do tempo gasto nos 0,54 segundos foi para obter o tempo do sistema e não dentro do próprio loop!
O que também está faltando nas estatísticas são os tempos de inicialização e limpeza, que não estão incluídos nas temporizações. Os aplicativos C # tendem a gastar muito mais tempo na inicialização e no encerramento do que os aplicativos C ++. A razão por trás disso é complicada e tem a ver com as rotinas de validação de código em tempo de execução .NET e o subsistema de gerenciamento de memória que executa muito trabalho no início (e, conseqüentemente, no final) do programa para otimizar as alocações de memória e o lixo colecionador.
Ao medir o desempenho de C ++ e .NET IL, é importante observar o código do assembly para ter certeza de que TODOS os cálculos estão lá. O que descobri é que, sem colocar algum código adicional em C #, a maior parte do código nos exemplos acima foi realmente removida do binário. Este também foi o caso com C ++ quando você usou um otimizador mais agressivo, como o que vem com o compilador Intel C ++. Os resultados que forneci acima são 100% corretos e validados no nível de montagem.
O principal problema com muitos fóruns na internet é que muitos novatos ouvem a propaganda de marketing da Microsoft sem entender a tecnologia e fazem falsas alegações de que C # é mais rápido que C ++. A alegação é que, em teoria, C # é mais rápido que C ++ porque o compilador JIT pode otimizar o código para a CPU. O problema com essa teoria é que existem muitos encanamentos na estrutura .NET que tornam o desempenho mais lento; encanamento que não existe no aplicativo C ++. Além disso, um desenvolvedor experiente saberá o compilador certo a ser usado para a plataforma fornecida e usará os sinalizadores apropriados ao compilar o aplicativo. Nas plataformas Linux ou de código aberto, isso não é um problema porque você pode distribuir sua origem e criar scripts de instalação que compilam o código usando a otimização apropriada. Na plataforma Windows ou de código fechado, você terá que distribuir vários executáveis, cada um com otimizações específicas. Os binários do Windows que serão implantados são baseados na CPU detectada pelo instalador msi (usando ações personalizadas).