次の2つのファイルがあります:-
シングル.cpp :-
#include <iostream>
#include <stdlib.h>
using namespace std;
unsigned long a=0;
class A {
public:
virtual int f() __attribute__ ((noinline)) { return a; }
};
class B : public A {
public:
virtual int f() __attribute__ ((noinline)) { return a; }
void g() __attribute__ ((noinline)) { return; }
};
int main() {
cin>>a;
A* obj;
if (a>3)
obj = new B();
else
obj = new A();
unsigned long result=0;
for (int i=0; i<65535; i++) {
for (int j=0; j<65535; j++) {
result+=obj->f();
}
}
cout<<result<<"\n";
}
と
multiple.cpp :-
#include <iostream>
#include <stdlib.h>
using namespace std;
unsigned long a=0;
class A {
public:
virtual int f() __attribute__ ((noinline)) { return a; }
};
class dummy {
public:
virtual void g() __attribute__ ((noinline)) { return; }
};
class B : public A, public dummy {
public:
virtual int f() __attribute__ ((noinline)) { return a; }
virtual void g() __attribute__ ((noinline)) { return; }
};
int main() {
cin>>a;
A* obj;
if (a>3)
obj = new B();
else
obj = new A();
unsigned long result=0;
for (int i=0; i<65535; i++) {
for (int j=0; j<65535; j++) {
result+=obj->f();
}
}
cout<<result<<"\n";
}
フラグ -O2 で gcc バージョン 3.4.6 を使用しています
そして、これは私が得るタイミングの結果です:-
多数 :-
real 0m8.635s
user 0m8.608s
sys 0m0.003s
独身 :-
real 0m10.072s
user 0m10.045s
sys 0m0.001s
一方、 multiple.cpp でクラス派生の順序を逆にした場合:-
class B : public dummy, public A {
次に、次のタイミングを取得します (これは、コードが行う必要のある this ポインターへの「サンク」調整のおかげで、単一継承の場合よりもわずかに遅くなります) :-
real 0m11.516s
user 0m11.479s
sys 0m0.002s
なぜこれが起こっているのでしょうか?ループに関する限り、3 つのケースすべてで生成されたアセンブリに違いはないようです。私が見る必要がある他の場所はありますか?
また、プロセスを特定の CPU コアにバインドし、SCHED_RR を使用してリアルタイムの優先度で実行しています。
編集:- これは Mysticial によって認識され、私によって再現されました。する
cout << "vtable: " << *(void**)obj << endl;
single.cpp のループの直前に、パブリック A、パブリック ダミーのように、シングルも 8.4 秒で複数のクロッキングと同じくらい高速になります。