次のプログラムを作成して、自分のマシンでの仮想機能のコストをテストしました。
#include <iostream>
#include <ctime>
#define NUM_ITER 10000000000
// 5 seconds = 1000000000
static volatile int global_a;
void spin()
{
int a = global_a;
int b = a*a;
int c = a+5;
int d = a^b^c;
global_a = b*d;
}
struct A {
virtual void a() = 0;
};
struct B : A {
virtual void a() { spin(); }
};
struct C : A {
virtual void a() { spin(); }
};
void run_A1(A* a)
{
a->a();
}
void run_A(A* a)
{
for (long long i = 0; i < NUM_ITER; i++) {
run_A1(a);
}
}
void run()
{
for (long long i = 0; i < NUM_ITER; i++) {
spin();
}
}
int main()
{
global_a = 2;
A* a1 = new B;
A* a2 = new C;
std::clock_t c_begin, c_end;
c_begin = std::clock();
run_A(a1);
c_end = std::clock();
std::cout << "Virtual | CPU time used: "
<< 1000.0 * (c_end-c_begin) / CLOCKS_PER_SEC
<< " ms\n";
c_begin = std::clock();
run_A(a2);
c_end = std::clock();
std::cout << "Virtual | CPU time used: "
<< 1000.0 * (c_end-c_begin) / CLOCKS_PER_SEC
<< " ms\n";
c_begin = std::clock();
run();
c_end = std::clock();
std::cout << "Normal | CPU time used: "
<< 1000.0 * (c_end-c_begin) / CLOCKS_PER_SEC
<< " ms\n";
delete a1;
delete a2;
}
結果は予想とは逆で、仮想関数は一貫して高速でした。たとえば、これは私が得た出力の1つですNUM_ITER = 10000000000
:
Virtual | CPU time used: 49600 ms
Virtual | CPU time used: 50270 ms
Normal | CPU time used: 52890 ms
結果のアセンブラー ファイルの分析から、コンパイラーが重要なものを最適化していないことを確認できます。次のオプションで GCC-4.7 を使用しました。
g++ -O3 -std=c++11 -save-temps -masm=intel -g0 -fno-exceptions -fno-inline test.cc -o test
仮想関数の呼び出しが速いのはなぜですか? または、非仮想関数の呼び出しが遅いのはなぜですか? 分岐予測子は非常に優れていますか? または、それは私のマシンだけかもしれません。たぶん、誰かが彼のタイミングをテストして投稿することもできますか?