2010-07-29 45 views
9

可以做些什么来加快从托管代码调用本地方法?优化托管为本地调用

我正在编写一个程序,它需要能够管理任意大小的对象列表并从它们中高速检索信息,并将其提供给脚本。脚本是已编译的C#代码的一部分。我正在编写一个从C++(native)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接口去完成它,但除非它适用于所有3个平台,否则我无法使用它。

+1

也许有一些字符串和字符集转换发生,这会降低速度。如果您使用即时测量功能,您是否会获得类似的性能比率int而不是字符串? – x4u 2010-07-29 02:01:14

+2

我的意思不是说明显,但我会因为100x似乎不符合我的经验,但是您没有运行调试版本\和/或在对.Net代码进行性能测试时附加了调试器? – 2010-07-29 02:15:48

+0

@chibacity:这确实是一个带有调试器的调试版本。虽然所有组件,本地和托管,都是用调试器进行调试。我将再次使用发布版本运行我的编号并检查差异。 – ssube 2010-07-29 03:12:47

回答

3

而且我的问题的评论,我们已经建立,这是一个调试版本附带的调试器。这对于.Net代码的运行时性能产生了巨大的影响。容易犯错。 :)

我猜测与发布构建和没有附加调试器,性能差异现在更合理。

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

如果在对调试器问题进行排序后性能可以接受,那么通过添加一个属性,我就可以轻松地通过简单的技术在chatty API中大幅提高性能。

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

+0

奇怪的是,没有调试器的版本构建(全部)具有1:100的性能。我试图测试interop的开销,所以我设计了一个函数,编译成4/5 asm指令(一个cmp,一个jmp,两个mov和一个ret)。 至于创建一个不那么健谈的API,它看起来就是我将要做的。类似于驱动程序的最小状态更改,缓冲某些信息,可能写入非托管内存中的共享缓冲区并偶尔调用同步功能。感谢您的安全提示。 – ssube 2010-07-29 17:43:32

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); 
} 
+0

我应该指定,但除非Linux和Mac能够运行,否则不幸的是不可能。我的第一选择是C++/CLI接口,所以你的回答是正确的,因为我提到了这个问题,但我忘记了指定的跨平台,并且没有看到任何方式可以为Windows以外的其他操作系统执行此操作。 :\ – ssube 2010-07-29 03:15:06

+0

Bugger,这肯定排除了C++/CLI。 – 2010-07-29 03:39:20