天天看點

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

   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 <iostream>

#include <windows.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;

C#與C++混合程式設計及性能分析

測試純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);

      }

C#與C++混合程式設計及性能分析

性能分析:

 從上面的對比可以看出,同樣的功能,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

public ref class CppFunction

namespace CSxingneng

           DateTime start = System.DateTime.Now;

           for (int i = 0; i < 10000; i++)

               for (int j = 0; j < 10000; j++)

               {

C#與C++混合程式設計及性能分析

 使用混合程式設計後,性能得到了一定程度的提升,但比起單純的C++項目,還是差了很多

 将C#主函數中的邏輯轉移到C++1項目中,即添加如下的static方法,C#中隻要調用該方法,程式結果:Result: 1733793664 Elapsed: 325

int CppFunction::Test()

   return result;

 并沒有變得更快,估計是當使用【公共語言運作時支援】方式編譯C++時,不能發揮C++的性能優勢

DLLImport混合方式:

 1. 建立非空的C++DLL項目,命名為NativeDLLCpp

 2. 将CppFunction類從PureCpp中複制過來

 3. 代碼如下,運作結果:Result: 1733793664 Elapsed: 75

// NativeDLLCpp.cpp : 定義 DLL 應用程式的導出函數。

#ifdef __cplusplus

#define TEXPORT extern "C" _declspec(dllexport)

#else

#define TEXPORT _declspec(dllexport)

#endif

TEXPORT int Test()

   cout << "C++ Result: " << result << " Elapsed: " << end - start << endl;

   public class NativeDLLCpp

       [DllImport("NativeDLLCpp.dll")]

       public static extern int Test();

           int result = NativeDLLCpp.Test();

C#與C++混合程式設計及性能分析

  跟純C++項目性能幾乎一緻。

  項目依賴項需要手動設定。

  實作聯調的方法:修改C#項目屬性|調試|啟用本機代碼調試