首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

托管 C++ 函式呼叫的雙重入口點與 __clrcall 效能優化

     編輯:關於C++

雙重入口點機制

在 VC.NET 使用預設 /clr 編譯時,一個托管函式會產生兩個入口點:一個供托管程式碼呼叫,另一個供非托管程式碼呼叫。但函式位址(特別是虛函式指標)只能有一個值,因此編譯器必須選擇一個預設入口點。

在 Visual Studio .NET 2003 中,編譯器總選擇非托管入口點作為預設;而在 Visual Studio 2005 中,若參數或傳回值包含托管類型,則選擇托管入口點。另一個入口點則透過互操作功能轉發呼叫。當托管函式互相呼叫時,這可能導致不必要的托管/非托管上下文切換與參數/傳回值複製,影響效能。

__clrcall 修飾符

若函式不會被非托管程式碼透過指標呼叫,可在宣告時加上 VC2005 新增的 __clrcall 修飾符,阻止編譯器產生雙重入口點,強制僅使用托管呼叫慣例,從而消除上下文切換開銷。

效能比較實測:氣泡排序

以下程式碼比較一般虛函式與 __clrcall 虛函式在氣泡排序中的效能差異:

using namespace System;
#define ARRAY_SIZE 1000

struct bubbleBase { int value; };

class bubble1 : public bubbleBase {
public:
    virtual int getvalue() { return value; }
    virtual void setvalue(int newvalue) { value = newvalue; }
};

class bubble2 : public bubbleBase {
public:
    virtual int __clrcall getvalue() { return value; }
    virtual void __clrcall setvalue(int newvalue) { value = newvalue; }
};

template<class T> void bubbleSort(int length) {
    TimeSpan ts;
    T* array1 = new T[ARRAY_SIZE];
    for (int i = 0; i < ARRAY_SIZE; i++)
        array1[i].setvalue(ARRAY_SIZE - i - 1);

    Int64 ticks = DateTime::Now.Ticks;
    int i, j, temp, test;
    for (i = length - 1; i > 0; i--) {
        test = 0;
        for (j = 0; j < i; j++) {
            if (array1[j].getvalue() > array1[j+1].getvalue()) {
                temp = array1[j].getvalue();
                array1[j].setvalue(array1[j+1].getvalue());
                array1[j+1].setvalue(temp);
                test = 1;
            }
        }
        if (test == 0) break;
    }
    ts = TimeSpan::FromTicks(DateTime::Now.Ticks - ticks);
    Console::WriteLine("BubbleSort {0} Items: {1} Ticks", ARRAY_SIZE, ts.Ticks);
    delete array1;
}

int main(array<System::String^>^ args) {
    bubbleSort<bubble1>(ARRAY_SIZE);
    bubbleSort<bubble2>(ARRAY_SIZE);
    return 0;
}

執行結果

BubbleSort 1000 Items: 3281250 Ticks
BubbleSort 1000 Items: 312500 Ticks

結果顯示,加上 __clrcall 後效能提升超過 10 倍,顯著減少了托管代碼內部呼叫的開銷。

補充提示:_SECURE_SCL

VC8.0 附帶的 STL 加入許多安全檢查,會降低執行速度。若確定程式無緩衝區溢位或記憶體越界風險,可定義 _SECURE_SCL=0 關閉此特性以提升效能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved