Что может быть сделано для ускорения собственных методов вызова из управляемого кода?
Я пишу программу, которая должна смочь управлять произвольно измеренными списками объектов и получить информацию от них в высокой скорости, которую она подает в сценарии. Сценарии являются битами скомпилированного кода C#. Я пишу основной интерфейсный слой из C++ (собственный компонент) DLL/таким образом/и т.д. к C# (.NET или Моно) уровень управления.
Теперь, я делал некоторое тестирование, и я нашел, что в среднем, PInvoking собственный метод из управляемого кода - что-то как в 100 раз медленнее, чем выполнение, все это справилось (весь собственный компонент, и все справились, тождественно быстры, для ссылки).
Синтаксис, который я использовал:
[DllImport("test.dll")]
extern static public String test_method(String value);
String returnedValue = test_method("hello world");
Существует ли способ кэшировать указатель на функцию, некоторый код быстрого invoker, который увеличил бы скорость после загрузки собственной библиотеки? Это решило бы проблему вполне аккуратно, таким образом, я сомневаюсь, что она существует.:P
Править: Я не указывал, но это должно работать над Windows, Linux (Ubuntu, по крайней мере) и Mac OS X, все и для x86 и для x64. Иначе я пошел бы с C++ / ИНТЕРФЕЙС CLI и был бы сделан с ним, но если это не работает на все 3 платформы, я не могу использовать его.
В дополнение к моему комментарию к вопросу мы установили, что это была отладочная сборка с прикрепленным отладчиком. Это имеет огромное влияние на производительность кода .Net во время выполнения. Сделать ошибку легко. :)
Я предполагаю, что с выпускной сборкой и без подключенного отладчика разница в производительности теперь намного более разумна.
Если у вас очень болтливый API и вызываемые собственные методы дешевы, то накладные расходы на вызов метода могут быть проблемой производительности. Попробуйте разработать менее разговорчивый API. Это типичный метод, используемый для повышения производительности пограничных \ системных коммуникаций.
Если после устранения проблемы с отладчиком производительность является приемлемой, есть простой метод, который я использовал, чтобы легко получить существенное повышение производительности болтливых API-интерфейсов, просто добавив один атрибут.
В классах, где у вас есть импортированные функции (т.е. функции DllImport), поместите атрибут SuppressUnmanagedCodeSecurity в классы. Это устранит некоторые дорогостоящие проверки безопасности из каждого вызова P / Invoke. См. Документацию по SuppressUnmanagedCodeSecurity , чтобы понять последствия этого. Я стараюсь группировать импортированные функции во внутренние классы (которые содержат только импортированные функции) с применением этого атрибута.
Возможно, именно сортировка строк вызывает замедление. Для сравнения попробуйте профилировать функцию, которая принимает и возвращает элементарные типы C ++, например int
.
Вы также можете попробовать поэкспериментировать с C ++ / CLI. Таким образом, вы можете получить явный контроль над сортировкой и, возможно, увидеть улучшения.
В сборке C ++ / CLI:
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);
}