C#与C++混合编程及性能分析
概要:
  众所周知,⽤C#做界⾯⽐C++开发效率要⾼得多,但在有性能问题的情况下不得不将部分模块使⽤C++,这时就需要使⽤C#与C++混合编程。本⽂给出了两种混合编程的⽅法以及性能对⽐。
开发环境:
  ThinkPad T430 i5-3230M 2.6G 8G,Win7 64Bit,VS2013(C++开发设置),C++,C#都采⽤x64平台,性能验证使⽤Release版本。
测试纯C++项⽬性能:
  1. 新建空解决⽅案:⽂件|新建|项⽬|已安装|模板|其他项⽬类型|Visual Studio解决⽅案|空⽩解决⽅案
  2. 新建PureCpp项⽬:右击解决⽅案|添加|新建项⽬|已安装|Visual C++|Win32控制台程序,按缺省设置⽣成项⽬
  3. 在配置管理器中新建x64平台,删除其他平台
  4. 新建CppFunction,并添加测试代码,完整代码如下,程序结果:Result: 1733793664 Elapsed: 109
// CppFunction.h
#pragma once
class CppFunction
{
public:
CppFunction(){}
~CppFunction(){}
int TestFunc(int a, int b);
};
// CppFunction.cpp
#include "stdafx.h"
#include "CppFunction.h"
class CCalc
{
public:
CCalc(int a, int b)
{
m_a = a;
m_b = b;
}
int Calc()
{
if (m_a % 2 == 0){
return m_a + m_b;
}
if (m_b % 2 == 0){
return m_a - m_b;
}
return m_b - m_a;
}
private:
int m_a;
int m_b;
};
int CppFunction::TestFunc(int a, int b)
{
CCalc calc(a, b);
return calc.Calc();
}
// PureCpp.cpp : 定义控制台应⽤程序的⼊⼝点。
//
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include "CppFunction.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
DWORD start = ::GetTickCount();
CppFunction cppFunction;
int result = 0;
for (int i = 0; i < 10000; i++){
for (int j = 0; j < 10000; j++){
result += cppFunction.TestFunc(i, j);
}
}
DWORD end = ::GetTickCount();
cout << "Result: " << result << " Elapsed: " << end - start << endl;
return0;
}
View Code
测试纯Csharp项⽬性能:
  1. 新建PureCsharp项⽬:右击解决⽅案|添加|新建项⽬|已安装|其他语⾔|Visual C#|控制台应⽤程序,按缺省设置⽣成项⽬
  2. 在配置管理器中新建x64平台,删除其他平台,去掉【创建新的解决⽅案平台】勾选,否则会报x64平台已经存在
  3. 将C++项⽬中的代码复制过来稍作改动,完整代码如下,程序结果:Result: 1733793664 Elapsed: 729
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PureCsharp
{
class CCalc
{
public CCalc(int a, int b)
{
m_a = a;
m_b = b;
}
public int Calc()
{
if (m_a % 2 == 0)
{
return m_a + m_b;
}
if (m_b % 2 == 0)
{
return m_a - m_b;
}
return m_b - m_a;
}
private int m_a;
private int m_b;
}
class CppFunction
{
public int TestFunc(int a, int b)
{
CCalc calc = new CCalc(a, b);
return calc.Calc();
}
}
class Program
{
static void Main(string[] args)
{
DateTime start = System.DateTime.Now;
CppFunction cppFunction = new CppFunction();
int result = 0;
for (int i = 0; i < 10000; i++){
for (int j = 0; j < 10000; j++){
result += cppFunction.TestFunc(i, j);
}
}
DateTime end = System.DateTime.Now;
System.Console.WriteLine("Result: " + result + " Elapsed: " + (end - start).Milliseconds);
}
}
}
View Code
性能分析:
  从上⾯的对⽐可以看出,同样的功能,C#的耗时⼏乎是C++的7倍,这个例⼦⾥的主要原因是,C++可以使⽤⾼效的栈内存对象(CCalc),⽽C#所有对象只能放在托管堆中。
托管C++混合⽅式:
  1. 新建C#控制台项⽬,命名为BenchCsharp,使⽤它来调⽤C++项⽬,修改⽣成⽬录为:..\x64\Release\
  2. 新建C++DLL项⽬,命名为DLLCpp,选择空项⽬,⽣成成功,但由于是空项⽬,不会真正⽣成dll⽂件
  3. 在DLLCpp为空项⽬时,在BenchCsharp中可以成功添加引⽤,但当DLLCpp中添加类后,就不能成功添加引⽤了,已经添加的引⽤也会显⽰警告
  4. 修改DLLCpp项⽬属性,右击项⽬|属性|配置属性|常规|公共语⾔运⾏时⽀持,修改后就可以成功引⽤了
  5. 在DLLCpp中添加CppFunction类,并复制代码,完整代码如下,程序结果:Result: 1733793664 Elapsed: 405
// CppFunction.h
#pragma once
public ref class CppFunction
{
public:
CppFunction(){}
~CppFunction(){}
int TestFunc(int a, int b);
};
// CppFunction.cpp
#include "CppFunction.h"
class CCalc
{
public:
CCalc(int a, int b)
{
m_a = a;
m_b = b;
}
int Calc()
{
if (m_a % 2 == 0){
return m_a + m_b;
}
if (m_b % 2 == 0){
return m_a - m_b;
}
return m_b - m_a;
}
private:
int m_a;
int m_b;
};
int CppFunction::TestFunc(int a, int b)
{
CCalc calc(a, b);
return calc.Calc();
}
View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BenchCsharp
{
class Program
{
static void Main(string[] args)
{
DateTime start = System.DateTime.Now;
CppFunction cppFunction = new CppFunction();
int result = 0;
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
result += cppFunction.TestFunc(i, j);
}
}
DateTime end = System.DateTime.Now;
System.Console.WriteLine("Result: " + result + " Elapsed: " + (end - start).Milliseconds);
}
}
}
View Code
性能分析:
  使⽤混合编程后,性能得到了⼀定程度的提升,但⽐起单纯的C++项⽬,还是差了很多
  将C#主函数中的逻辑转移到DLLCpp项⽬中,即添加如下的static⽅法,C#中只要调⽤该⽅法,程序结果:Result: 1733793664 Elapsed: 405
int CppFunction::Test()
{
DWORD start = ::GetTickCount();
CppFunction cppFunction;
int result = 0;
for (int i = 0; i < 10000; i++){
for (int j = 0; j < 10000; j++){
result += cppFunction.TestFunc(i, j);
}
}
DWORD end = ::GetTickCount();
cout << "Result: " << result << " Elapsed: " << end - start << endl;
return result;
}
View Code
  并没有变得更快,估计是当使⽤【公共语⾔运⾏时⽀持】⽅式编译C++时,不能发挥C++的性能优势
DLLImport混合⽅式:
  1. 新建⾮空的C++DLL项⽬,命名为NativeDLLCpp
  2. 将CppFunction类从PureCpp中复制过来
  3. 代码如下,运⾏结果:Result: 1733793664 Elapsed: 125
// NativeDLLCpp.cpp : 定义 DLL 应⽤程序的导出函数。
/
/
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include "CppFunction.h"
using namespace std;
#ifdef __cplusplus
#define TEXPORT extern "C" _declspec(dllexport)
#else
#define TEXPORT _declspec(dllexport)
#endif
TEXPORT int Test()
{
DWORD start = ::GetTickCount();
CppFunction cppFunction;
int result = 0;
for (int i = 0; i < 10000; i++){
for (int j = 0; j < 10000; j++){
result += cppFunction.TestFunc(i, j);
}
}
DWORD end = ::GetTickCount();
cout << "Result: " << result << " Elapsed: " << end - start << endl;
return result;
writeline方法的作用
}
View Code
public class NativeDLLCpp
{
[DllImport("NativeDLLCpp.dll")]
public static extern int Test();
}
class Program
{
static void Main(string[] args)
{
DateTime start = System.DateTime.Now;
int result = NativeDLLCpp.Test();
DateTime end = System.DateTime.Now;
System.Console.WriteLine("Result: " + result + " Elapsed: " + (end - start).Milliseconds);        }
}
View Code
性能分析:
  跟纯C++项⽬性能⼏乎⼀致。
  项⽬依赖项需要⼿动设置。
  实现联调的⽅法:修改C#项⽬属性|调试|启⽤本机代码调试

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。