2010-07-29 7 views
9

Что можно сделать, чтобы ускорить вызов собственных методов из управляемого кода?Оптимизация управляемых нативных вызовов

Я пишу программу, которая должна иметь возможность управлять произвольными размерами списков объектов и извлекать из них информацию с высокой скоростью, которую она передает в скрипты. Скрипты - это бит скомпилированного кода на C#. Я пишу базовый уровень интерфейса с C++ (родной) DLL/SO/etc на уровень управления C# (.Net или Mono).

Теперь я тестировал, и я обнаружил, что в среднем PInvoking собственный метод из управляемого кода примерно в 100 раз медленнее, чем все это в управлении (все родные и все управляемые идентичны быстро, для справки).

Синтаксис Я использую это:

[DllImport("test.dll")] 
extern static public String test_method(String value); 

String returnedValue = test_method("hello world"); 

Есть ли способ, чтобы кэшировать указатель на функцию, код быстрого запустившего, что приведет к увеличению скорости после загрузки родной библиотеки? Это решило бы проблему довольно аккуратно, поэтому я сомневаюсь, что она существует. : P

Редактировать: Я не указал, но это должно работать на Windows, Linux (по крайней мере, Ubuntu) и Mac OS X, все для x86 и x64. В противном случае я бы пошел с интерфейсом C++/CLI и был сделан с ним, но если это не работает для всех трех платформ, я не могу его использовать.

+1

Возможно, произошла конверсия строки и кодировки, которая замедляет это. Получаете ли вы аналогичное соотношение производительности, если вы измеряете функции с помощью i.e.int вместо строки? – x4u

+2

Я не хочу упомянуть очевидное, но с тех пор, как 100x кажется мне непонятным в моем опыте, но вы не используете отладочные сборки \ и/или с отладчиком, приложенным при выполнении первичного измерения в коде .Net? –

+0

@chibacity: Это действительно была отладочная версия с прикрепленным отладчиком. Хотя все компоненты, родные и управляемые, отлаживались отладчиками. Я снова запустил свой номер с релизами и проверил разницу. – ssube

ответ

3

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

Я предполагаю, что с выпуском сборки и без отладчика прилагается, разница в производительности теперь намного разумнее.

Если у вас очень чатный API, а методы, называемые native, дешевы, то служебные данные метода могут быть проблемой производительности. Попробуйте и создайте менее чатный API. Это типичный метод, используемый для повышения производительности пограничных системных коммуникаций.

Если производительность является приемлемой после сортировки проблемы отладчика, есть простой способ, который я использовал, чтобы легко получить существенное увеличение производительности в chatty API, просто добавив один атрибут.

В классах, где у вас есть импортированные функции (т. Е. Функции DllImport), поместите атрибут SuppressUnmanagedCodeSecurity в классы. Это приведет к удалению некоторых дорогих проверок безопасности из каждого вызова P/Invoke. Пожалуйста, ознакомьтесь с документацией по адресу SuppressUnmanagedCodeSecurity, чтобы понять последствия этого. Я стараюсь, чтобы мои импортированные функции группировались во внутренних классах (которые содержат только импортированные функции) с применением этого атрибута.

+0

Как ни странно, релизная сборка (со всех сторон) без отладки имеет одинаковую производительность 1: 100. Я пытался проверить накладные расходы interop, поэтому я разработал функцию, которая скомпилирована до инструкций 4/5 asm (один cmp, один jmp, два mov и один ret). Что касается создания менее чатного API, похоже, вот что я буду делать. Что-то похожее на минимальное изменение состояния драйвера, буферизацию некоторой информации, возможно, запись в общий буфер в неуправляемой памяти и иногда вызов функции синхронизации. Спасибо за отзыв безопасности. – ssube

3

Возможно, строковое сортирование является тем, что вызывает замедление. Для сравнения попробуйте профилировать функцию, которая принимает и возвращает элементарные типы C++, такие как int.

Вы также можете попробовать поэкспериментировать с C++/CLI. Таким образом, вы можете взять явный контроль над сортировкой и, возможно, увидеть улучшение.

В ++/CLI сборки C:

System::String^test_method(System::String^args) 
{ 
    pin_ptr<const wchar_t> pp = PtrToStringChars(args); 
    //This might leak, probably needs a smart pointer to wrap it 
    wchar_t* ret = native_method(pp); 
    return gcnew String^(ret); 
} 
+0

Я должен был указать, но если это не будет работать для Linux и Mac, это, к сожалению, не может быть и речи. Мой первый выбор был бы интерфейсом C++/CLI, поэтому ваш ответ прав, когда я задал вопрос, но я забыл указать кросс-платформу и не видел никакого способа сделать это для других ОС, чем Windows. : \ – ssube

+0

Bugger, это определенно исключает C++/CLI. –

Смежные вопросы