管理C++における関数呼び出しの二重変換(Double Thunking)


VCでNetでデフォルト設定/clrコンパイルを使用すると、1つの管理関数に2つのエントリポイントが生成されます.1つは管理され、管理コード呼び出しに使用され、もう1つは非管理され、非管理コード呼び出しに使用されます.ただし、関数アドレス、特に虚関数ポインタには1つの値しかないので、デフォルトのエントリが必要です.
非管理エントリポイントは、すべての呼び出しのデフォルトエントリである可能性があります(Visual Studio.NET 2003では、コンパイラは常に非管理エントリを選択しますが、Visual Studio 2005では、パラメータまたは戻り値に管理タイプが含まれている場合、コンパイラは管理エントリを選択します).もう1つは、管理C++の相互運用機能を使用してデフォルトエントリを呼び出すだけです.1つの管理関数が別の管理関数によって呼び出されると、管理/非管理コンテキストの切り替えやパラメータ/戻り値のコピーが不要になる可能性があります.ポインタを使用して関数が非管理コードによって呼び出されない場合、関数を宣言するときにVC 2005で追加された__を使用することができる.clrcall修飾子は、コンパイラが2つのエントリを生成することを阻止します.
簡単な泡立ちソートアルゴリズムで比較してみましょう_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は、管理コードで管理関数を呼び出す速度を大幅に速めます.
ちなみに、VC 8.0リリースのSTLには多くのセキュリティ機能が追加されていますが、これによりプログラムの実行速度が低下します.プログラムにバッファオーバーフローやメモリオーバーフローの問題がないことを確認したら、_SECURE_SCLは、この特性をオフにするために0として定義される.リファレンス
  • http://msdn2.microsoft.com/en-us/library/ms140915(en-US,VS.80).aspx
  • http://msdn2.microsoft.com/en-us/library/ec7sfckb(en-US,VS.80).aspx
  • http://msdn2.microsoft.com/en-us/library/y9ww7c1a