优化托管到本机呼叫

时间:2010-07-29 01:46:01

标签: c# optimization pinvoke

如何加速从托管代码调用本机方法?

我正在编写一个程序,它需要能够管理任意大小的对象列表并高速检索它们的信息,并将其提供给脚本。脚本是编译的C#代码的一部分。我正在编写一个从C ++(本机)DLL / SO /等到C#(。Net或Mono)管理层的基本接口层。

现在,我一直在进行一些测试,而且我发现平均而言,从托管代码中调用本机方法比在托管代码中执行所有操作慢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接口并完成它,但除非它适用于所有3个平台,否则我无法使用它。

2 个答案:

答案 0 :(得分:4)

继我的问题评论之后,我们已经确定它是附带调试器的调试版本。这会对.Net代码的运行时性能产生大量影响。容易犯错误。 :)

我猜测发布版本并没有附加调试器,性能差异现在更加合理。

如果你有一个非常健谈的API,并且调用的本机方法很便宜,那么方法调用开销可能是一个性能问题。尝试并设计一个不太健谈的API。这是一种用于提高边界\系统通信性能的典型技术。

如果在对调试器问题进行排序后性能可以接受,那么通过添加单个属性,我可以使用一种简单的技术轻松地在繁琐的API中获得显着的性能提升。

在具有导入函数的类(即DllImport函数)中,将SuppressUnmanagedCodeSecurity属性放在类上。这将从每个P / Invoke调用中删除一些昂贵的安全检查。请参阅SuppressUnmanagedCodeSecurity上的文档,了解其中的后果。我倾向于将导入的函数组合在内部类(仅包含导入的函数)中并应用此属性。

答案 1 :(得分:3)

字符串编组可能是导致速度减慢的原因。为了比较,尝试分析一个函数,该函数接受并返回基本的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);
}