Накладные расходы для нативного взаимодействия с использованием только примитивных типов - PullRequest
4 голосов
/ 04 февраля 2009

Я рассматриваю возможность переноса небольшой части кода в моем проекте C # на C / ASM для повышения производительности. (Этот раздел кода использует много побитовых операций и является одним из немногих мест, где может существовать реальное увеличение производительности при использовании собственного кода.) Затем я планирую просто вызвать собственную функцию в отдельной DLL через P / Invoke. Теперь единственными данными, которые будут передаваться между управляемым и нативным кодом, будут чисто примитивные типы (bool, int, long, 1D-массивы и т. Д.). Итак, мой вопрос: будут ли какие-либо существенные издержки при использовании P / invoke просто с примитивными типами? Я знаю, что при использовании более сложных типов возникают незначительные накладные расходы, поскольку их нужно маршалировать (закреплять / копировать), но, возможно, в моей ситуации это будет относительно эффективно (по сравнению с вызовом кода из самой нативной библиотеки DLL даже )? Если бы кто-то мог прояснить этот вопрос для меня, объяснив степень преимуществ / хитов производительности и причины их возникновения, это было бы очень ценно. Также приветствуется альтернативный способ выполнения всей задачи, хотя, поскольку в C # отсутствует поддержка встроенной сборки / CIL, я не верю, что он существует.

Ответы [ 5 ]

5 голосов
/ 04 февраля 2009

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

"PInvoke имеет накладные расходы от 10 до 30 команд x86 на вызов. В дополнение к этой фиксированной стоимости, маршалинг создает дополнительные издержки. Не существует затрат на маршалинг между blittable типами, которые имеют одинаковое представление в управляемом и неуправляемом коде. Например, перевод между int и Int32 бесплатен. "

Итак, это достаточно дешево, но, как всегда, вы должны тщательно измерять, чтобы быть уверенным, что вы извлекаете из этого пользу, и помнить о любых накладных расходах на техническое обслуживание. Кроме того, я бы порекомендовал C ++ / CLI («управляемый» C ++) вместо P / Invoke для любого сложного взаимодействия, особенно если вы знакомы с C ++.

1 голос
/ 04 февраля 2009

Кажется, я слышал, что на каждый вызов P / Invoke приходится как минимум 30 машинных операций. Но игнорируйте теорию, профилируйте свои варианты и выбирайте самый быстрый.

1 голос
/ 04 февраля 2009

Я бы лично настроил тестовый комплект с простым выражением, написанным на C # и неуправляемом C ++, а затем профилировал приложение, чтобы увидеть, с каким перепадом производительности вы работаете.

Еще одна вещь, которую следует учитывать, - это то, что вы столкнетесь с проблемой обслуживания приложения, особенно если у вас есть разработчики младшего уровня, которые должны поддерживать код. Убедитесь, что вы знаете, что вы получаете и что вы теряете, в зависимости от производительности, а также ясности кода и удобства сопровождения.

Кроме того, JIT-код C # должен иметь производительность наравне с C ++ в отношении арифметических операций.

0 голосов
/ 18 июня 2014

Эта ссылка дает некоторые идеи: http://www.codeproject.com/Articles/253444/PInvoke-Performance

Также обратите внимание на разницу в производительности при применении атрибута [SuppressUnmanagedCodeSecurity].

0 голосов
/ 04 февраля 2009

Вы можете создать скомпилированную оптимизированную версию сборки .NET, используя ngen на компьютере конечного пользователя (как часть процесса установки).

По моему опыту, правильно отформатированный C # (например, сохранить выделение вне циклов) будет работать очень хорошо.

...