Je suis développeur C ++ et C #. J'ai développé des applications C # depuis la première version bêta du framework .NET et j'ai plus de 20 ans d'expérience dans le développement d'applications C ++. Premièrement, le code C # ne sera JAMAIS plus rapide qu'une application C ++, mais je ne passerai pas par une longue discussion sur le code managé, son fonctionnement, la couche interopératoire, les internes de gestion de la mémoire, le système de type dynamique et le ramasse-miettes. Néanmoins, permettez-moi de continuer en disant que les repères énumérés ici produisent tous des résultats INCORRECTS.
Laissez-moi vous expliquer: la première chose que nous devons considérer est le compilateur JIT pour C # (.NET Framework 4). Maintenant, le JIT produit du code natif pour le processeur à l'aide de divers algorithmes d'optimisation (qui ont tendance à être plus agressifs que l'optimiseur C ++ par défaut fourni avec Visual Studio) et le jeu d'instructions utilisé par le compilateur .NET JIT reflète de plus près le processeur réel sur la machine afin que certaines substitutions dans le code machine puissent être effectuées pour réduire les cycles d'horloge et améliorer le taux de réussite dans le cache du pipeline CPU et produire d'autres optimisations d'hyper-threading telles que la réorganisation des instructions et les améliorations relatives à la prédiction de branchement.
Cela signifie qu'à moins que vous ne compiliez votre application C ++ en utilisant les paramètres corrects pour la version RELEASE (pas la version DEBUG), votre application C ++ peut s'exécuter plus lentement que l'application C # ou .NET correspondante. Lorsque vous spécifiez les propriétés du projet sur votre application C ++, assurez-vous d'activer "l'optimisation complète" et "favoriser le code rapide". Si vous avez une machine 64 bits, vous DEVEZ spécifier de générer x64 comme plate-forme cible, sinon votre code sera exécuté via une sous-couche de conversion (WOW64) ce qui réduira considérablement les performances.
Une fois que vous avez effectué les optimisations correctes dans le compilateur, j'obtiens 0,72 seconde pour l'application C ++ et 1,16 seconde pour l'application C # (les deux dans la version de version). Étant donné que l'application C # est très basique et alloue la mémoire utilisée dans la boucle sur la pile et non sur le tas, elle fonctionne en fait beaucoup mieux qu'une application réelle impliquée dans des objets, des calculs lourds et avec des ensembles de données plus volumineux. Les chiffres fournis sont donc des chiffres optimistes biaisés vers C # et le framework .NET. Même avec ce biais, l'application C ++ se termine en un peu plus de la moitié du temps que l'application C # équivalente. Gardez à l'esprit que le compilateur Microsoft C ++ que j'ai utilisé n'avait pas le bon pipeline et les optimisations d'hyperthreading (en utilisant WinDBG pour afficher les instructions d'assemblage).
Maintenant, si nous utilisons le compilateur Intel (qui est d'ailleurs un secret de l'industrie pour générer des applications hautes performances sur des processeurs AMD / Intel), le même code s'exécute en 0,54 seconde pour l'exécutable C ++ contre 0,72 seconde en utilisant Microsoft Visual Studio 2010 Au final, les résultats finaux sont de 0,54 seconde pour C ++ et 1,16 seconde pour C #. Ainsi, le code produit par le compilateur .NET JIT prend 214% plus de temps que l'exécutable C ++. La plupart du temps passé dans les .54 secondes était pour obtenir l'heure du système et non dans la boucle elle-même!
Ce qui manque également dans les statistiques, ce sont les heures de démarrage et de nettoyage qui ne sont pas incluses dans les horaires. Les applications C # ont tendance à passer beaucoup plus de temps au démarrage et à l'arrêt que les applications C ++. La raison derrière cela est compliquée et a à voir avec les routines de validation du code d'exécution .NET et le sous-système de gestion de la mémoire qui effectue beaucoup de travail au début (et par conséquent, à la fin) du programme pour optimiser les allocations de mémoire et les déchets collectionneur.
Lors de la mesure des performances de C ++ et .NET IL, il est important de regarder le code d'assembly pour s'assurer que TOUS les calculs sont là. Ce que j'ai trouvé, c'est que sans mettre de code supplémentaire en C #, la plupart du code dans les exemples ci-dessus ont en fait été supprimés du binaire. C'était également le cas avec C ++ lorsque vous utilisiez un optimiseur plus agressif tel que celui fourni avec le compilateur Intel C ++. Les résultats que j'ai fournis ci-dessus sont 100% corrects et validés au niveau de l'assemblage.
Le principal problème avec beaucoup de forums sur Internet est que beaucoup de débutants écoutent la propagande marketing de Microsoft sans comprendre la technologie et font de fausses déclarations selon lesquelles C # est plus rapide que C ++. La prétention est qu'en théorie, C # est plus rapide que C ++ car le compilateur JIT peut optimiser le code pour le processeur. Le problème avec cette théorie est qu'il y a beaucoup de plomberie qui existe dans le framework .NET qui ralentit les performances; plomberie qui n'existe pas dans l'application C ++. De plus, un développeur expérimenté connaîtra le bon compilateur à utiliser pour la plate-forme donnée et utilisera les indicateurs appropriés lors de la compilation de l'application. Sur les plates-formes Linux ou open source, ce n'est pas un problème car vous pouvez distribuer votre source et créer des scripts d'installation qui compilent le code en utilisant l'optimisation appropriée. Sur les fenêtres ou la plate-forme source fermée, vous devrez distribuer plusieurs exécutables, chacun avec des optimisations spécifiques. Les binaires Windows qui seront déployés sont basés sur le processeur détecté par le programme d'installation msi (à l'aide d'actions personnalisées).