C#与C++混合编程及性能分析

简介: C#与C++混合编程及性能分析

概要:


 众所周知,用C#做界面比C++开发效率要高得多,但在有性能问题的情况下不得不将部分模块使用C++,这时就需要使用C#与C++混合编程。本文给出了两种混合编程的方法以及性能对比。


开发环境:


 I5-8400 CPU 2.8G 8G,Win10 64Bit,VS2017(C++开发设置),C++,C#都采用x32平台,性能验证使用Release版本。


测试纯C++项目性能:

 1. 新建空解决方案:文件|新建|项目|已安装|模板|其他项目类型|Visual Studio解决方案|空白解决方案


 2. 新建C++项目:右击解决方案|添加|新建项目|已安装|Visual C++|Win32控制台程序,按缺省设置生成项目


 3. 在配置管理器中新建x32平台,删除其他平台


 4. 新建CppFunction,并添加测试代码,完整代码如下,程序结果:Result: 1733793664 Elapsed:65


// 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;


   return 0;


}

tt.png

测试纯Csharp项目性能:

 1. 新建PureCsharp项目:右击解决方案|添加|新建项目|已安装|其他语言|Visual C#|控制台应用程序,按缺省设置生成项目


 2. 在配置管理器中新建x32平台,删除其他平台,去掉【创建新的解决方案平台】勾选,否则会报x32平台已经存在


 3. 将C++项目中的代码复制过来稍作改动,完整代码如下,程序结果:Result: 1733793664 Elapsed: 607


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);


      }


   }


}


tt.png

性能分析:


 从上面的对比可以看出,同样的功能,C#的耗时几乎是C++的10倍,这个例子里的主要原因是,C++可以使用高效的栈内存对象(CCalc),而C#所有对象只能放在托管堆中。


托管C++混合方式:

 1. 新建C#控制台项目,命名为CSxingneng,使用它来调用C++项目,修改生成目录为:..\x32\Release\


 2. 在CLR中,新建CLR C++DLL项目,命名为C++1。


 3. 在C++1中添加CppFunction类,并复制代码,完整代码如下,程序结果:Result: 1733793664 Elapsed: 325


// 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();


}


using System;


using System.Collections.Generic;


using System.Linq;


using System.Text;


using System.Threading.Tasks;



namespace CSxingneng


{


   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);


       }


   }


}


 tt.png

性能分析:


 使用混合编程后,性能得到了一定程度的提升,但比起单纯的C++项目,还是差了很多


 将C#主函数中的逻辑转移到C++1项目中,即添加如下的static方法,C#中只要调用该方法,程序结果:Result: 1733793664 Elapsed: 325


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;


}


 并没有变得更快,估计是当使用【公共语言运行时支持】方式编译C++时,不能发挥C++的性能优势


DLLImport混合方式:

 1. 新建非空的C++DLL项目,命名为NativeDLLCpp


 2. 将CppFunction类从PureCpp中复制过来


 3. 代码如下,运行结果:Result: 1733793664 Elapsed: 75


// 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 << "C++ Result: " << result << " Elapsed: " << end - start << endl;


   return result;


}


   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);


       }


}


tt.png


性能分析:

  跟纯C++项目性能几乎一致。

  项目依赖项需要手动设置。

  实现联调的方法:修改C#项目属性|调试|启用本机代码调试



目录
相关文章
|
2月前
|
算法 Unix Linux
【C/C++ 实用工具】性能分析工具一览
【C/C++ 实用工具】性能分析工具一览
43 0
|
2月前
|
数据处理 C# C++
如何使用C#和C++结构体实现Socket通信
如何使用C#和C++结构体实现Socket通信
|
7月前
|
C# 开发工具 C++
简单C#类转非托管C++
简单C#类转非托管C++
|
2月前
|
数据可视化 关系型数据库 编译器
【C/C++ 单线程性能分析工具 Gprof】 GNU的C/C++ 性能分析工具 Gprof 使用全面指南
【C/C++ 单线程性能分析工具 Gprof】 GNU的C/C++ 性能分析工具 Gprof 使用全面指南
117 2
|
7月前
|
C# C++
[闻缺陷则喜]C#调用C++的类
[闻缺陷则喜]C#调用C++的类
|
2月前
|
算法 Java 测试技术
【深入探究 C++ 日志库性能比较】glog、log4cplus 和 spdlog 的日志输出性能分析
【深入探究 C++ 日志库性能比较】glog、log4cplus 和 spdlog 的日志输出性能分析
92 0
|
2月前
|
缓存 Linux iOS开发
【C/C++ 集成内存调试、内存泄漏检测和性能分析的工具 Valgrind 】Linux 下 Valgrind 工具的全面使用指南
【C/C++ 集成内存调试、内存泄漏检测和性能分析的工具 Valgrind 】Linux 下 Valgrind 工具的全面使用指南
68 1
|
2月前
|
Java API C++
【C++ 与Qt 线程】C++ std::thread 与Qt qthread多线程混合编程
【C++ 与Qt 线程】C++ std::thread 与Qt qthread多线程混合编程
48 1
|
2月前
|
监控 Linux 测试技术
【 C/C++ 性能分析工具 CPU 采样分析器 perf 】掀开Linux perf性能分析的神秘面纱
【 C/C++ 性能分析工具 CPU 采样分析器 perf 】掀开Linux perf性能分析的神秘面纱
69 0
|
2月前
|
开发框架 Java .NET
C#编程语言的优势与C++对比
C#编程语言的优势与C++对比