J'ai les deux fichiers suivants :-
single.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";
}
Et
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";
}
Je suis en utilisant gcc version 3.4.6 avec des drapeaux-O2
Et c'est les timings résultats que j'obtiens :-
multiples :-
real 0m8.635s
user 0m8.608s
sys 0m0.003s
unique :-
real 0m10.072s
user 0m10.045s
sys 0m0.001s
D'autre part, si dans multiple.cpp j'ai inverser l'ordre de dérivation de classe ainsi :-
class B : public dummy, public A {
Puis-je obtenir le minutage suivant (qui est légèrement plus lente que celle de l'héritage simple, comme on peut le deviner grâce à 'thunk' " ajustement de la ce pointeur que le code aurait besoin de le faire) :-
real 0m11.516s
user 0m11.479s
sys 0m0.002s
Aucune idée de pourquoi cela peut-il se passer? Il ne semble pas y avoir de différence dans l'assembly généré pour tous les trois cas, aussi loin que la boucle est concerné. Est-il un autre endroit que je dois regarder?
Aussi, j'ai lié le processus à un cœur de processeur et je suis en cours d'exécution sur une priorité en temps réel avec SCHED_RR.
EDIT:- il a été remarqué par Mysticial et reproduit par moi. Faire un
cout << "vtable: " << *(void**)obj << endl;
juste avant la boucle single.cpp conduit à la seule aussi à être aussi rapide que plusieurs de pointage à 8,4 s tout comme le public A, public factice.