当我将DLL构建选项从native更改为/ CLR,以便我可以跨c#/ c ++边界进行调试时,我的性能减少了一半。
我开发了一个带有特定高性能算法的原生C ++ DLL来解决我的计算问题。这个DLL我需要插入由业务合作伙伴开发的C#应用程序,它用于替换其性能较低的算法。一切都很顺利,我使用静态包装器调用插入我的DLL,DLL算法运行良好,显示比原始算法提高2倍的性能,但无法跨边界调试。然后我将c ++ DLL构建设置从native转换为/ CLR,以便能够跨c#/ c ++ DLL边界进行调试,并且我的性能下降了一半。
无法弄清楚为什么会这样。
c ++ DLL端:
extern "C"
{
__declspec(dllexport) void* NewCalc()
{
return (void*)new CalcCL;
}
__declspec(dllexport) double Calc(void* sCalc, int *Buf, int Cnt)
{
return ((CalcCl*)sCalc)->Calc(Buf, Cnt);
}
}
c#侧:
[DllImport("CalcDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int NewCalc();
[DllImport("CalcDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern double Calc(int sCalc, int[] Buf, int Cnt);
...
int sCalc = NewCalc();
...
double res;
int[] MyBuf = new int[1000];
// <Code that fills MyBuf with target data for algorithm>
res = Calc(sCalc, MyBuf, 1000);
使用给定的接口,使用/ clr进行编译没有任何好处。通过右键单击主C#项目> Properties> Debug选项卡>勾选“启用本机代码调试”复选框,使本机C ++代码可调试。这将启用托管和非托管调试引擎。您不能单步进入本机代码,需要在Calc()函数上使用断点来实现调试引擎更改。如果设置断点很尴尬,您可能仍然喜欢用本机C ++编写的单元测试。
您需要注意的另一件事是您正在构建启用了调试设置的C ++代码。你现在就得到了,这就是为什么代码似乎慢了一半。仅使用Release构建设置执行perf测试,以确保启用了优化程序。最好的办法是在C#解决方案中包含原生C ++项目,这样您就可以构建正确的风格。并且您必须确保将正确的DLL复制到C#主项目的构建目录中,通常使用后构建事件完成。对于调试和发布配置,该复制步骤必须不同。
请注意,[DllImport]声明不正确。 NewCalc()的返回类型必须是IntPtr,因此它也适用于64位代码。对C ++代码的64位版本进行Perf测试是您想要尝试的其他内容,如果Calc()函数使用浮点数学,它可以提升性能。实际上使用/ clr可以使界面更好,但是你必须学习如何编写C ++ / CLI代码并避免使用/ clr构建本机C ++代码。