2009-02-04 8 views
4

Je songe à transférer une petite partie du code d'un projet C# de la mine vers C/ASM pour des avantages en termes de performances. (Cette section du code utilise plusieurs opérations au niveau du bit et est l'un des rares endroits où il peut exister une augmentation réelle des performances en utilisant du code natif.) Je prévois ensuite d'appeler simplement la fonction native dans la DLL séparée via P/Invoke. Maintenant, les seules données qui seront transmises entre le code géré et le code natif seront des types purement primitifs (bool, int, long, tableaux 1D, etc.). Donc ma question est la suivante: y aura-t-il un surcoût important utilisant P/invoquer simplement avec des types primitifs? Je suis conscient qu'il y a un surcoût substantiel quand on utilise des types plus complexes, puisqu'ils doivent être rassemblés (épinglés/copiés), mais peut-être dans ma situation ce sera relativement efficace (comparé à appeler le code depuis la DLL native même)? Si quelqu'un pouvait clarifier cette question pour moi, en expliquant les degrés d'avantages/coups de performance et les raisons qui les sous-tendent, ce serait très apprécié. Un autre moyen d'accomplir toute la tâche serait également le bienvenu, mais puisque C# manque de support pour l'assemblage en ligne/CIL, je ne crois pas qu'il y en ait un.Surcharge pour l'interopérabilité native utilisant uniquement des types primitifs

Répondre

5

De MSDN (http://msdn.microsoft.com/en-us/library/aa712982.aspx):

« PInvoke a une surcharge comprise entre 10 et 30 instructions x86 par appel Outre ce coût fixe, marshaling crée une charge supplémentaire Il n'y a pas de frais de marshaling entre les types blittables que.. ont la même représentation dans le code managé et non managé, par exemple, il n'y a aucun coût à traduire entre int et Int32. " Donc, il est raisonnablement bon marché, mais comme toujours, vous devriez mesurer avec soin pour vous assurer que vous en profitez, et gardez à l'esprit les frais généraux de maintenance. En aparté, je recommanderais C++/CLI ("managed" C++) sur P/Invoke pour tout interop complexe, surtout si vous êtes à l'aise avec C++.

+0

Merci, je dois avoir raté cela en regardant par-dessus les docs. En effet, je vais profiler les différentes implémentations pour être sûr.Vous faites également un bon point sur le C++ géré, mais savez-vous s'il est généralement moins coûteux d'appeler une fonction C++ managée que celle d'un natif via P/Invoke? – Noldorin

+0

Juste pour confirmer: géré C++ peut contenir ASM en ligne, non? Étant donné que c'est le cas, cela semblerait être la meilleure solution. – Noldorin

+0

L'avantage principal de l'utilisation de C++/CLI pour l'interopérabilité est qu'il prend en charge une grande partie du gabarit de marshaling pour vous. Je doute qu'il y ait une différence de performance, mais je ne sais pas à coup sûr. Et oui, vous pouvez utiliser inline asm aussi. –

0

Vous pouvez générer une version compilée et optimisée de votre assembly .NET en utilisant ngen sur l'ordinateur de l'utilisateur final (dans le cadre du processus d'installation). Dans mon expérience, le format C# correctement formaté (par exemple, conserver l'allocation en dehors des boucles) fonctionnera très bien.

+0

Je suis sûr que vous avez raison dans la grande majorité des cas. Cependant, je veux vraiment utiliser C/C++ ici pour les avantages de ses opérations très rapides au niveau du bit (accéléré en particulier par l'accès aux instructions x86 spécialisées via ASM inline). A noter le profil, en tout cas. – Noldorin

1

Je me souviens avoir entendu dire qu'il y avait au moins 30 frais généraux d'opération machine pour chaque appel P/Invoke. Mais ignorez la théorie, profilez vos options et choisissez le plus rapide.

1

Personnellement, je configurerais un harnais de test avec une expression simple écrite en C# et en C++ non géré, puis je profilerais l'application pour voir le type de delta de performance avec lequel vous travaillez.

Une autre chose à considérer est que vous introduiriez un problème de maintenance avec l'application, en particulier si vous avez des développeurs de niveau junior censés maintenir le code. Assurez-vous de savoir ce que vous gagnez et ce que vous perdez en fonction de la performance, de la clarté du code et de la maintenabilité. En outre, le code C# JIT devrait être performant au même niveau que C++ en ce qui concerne les opérations arithmétiques.

0

Ce lien fournit un aperçu: http://www.codeproject.com/Articles/253444/PInvoke-Performance

Notez également la différence de performance lorsque [SuppressUnmanagedCodeSecurity] attribut est appliqué.

+0

L'article derrière ce lien est tout simplement faux. Lisez les commentaires. L'auteur a promis de mettre à jour l'article mais c'était en 2011 ... –

Questions connexes