- Why am I observing multiple inheritance to be faster than single?
- #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";
- }
- #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";
- }
- real 0m8.635s
- user 0m8.608s
- sys 0m0.003s
- real 0m10.072s
- user 0m10.045s
- sys 0m0.001s
- class B : public dummy, public A {
- real 0m11.516s
- user 0m11.479s
- sys 0m0.002s
- cout << "vtable: " << *(void**)obj << endl;
- #include <iostream>
- #include <stdlib.h>
- #include <time.h>
- using namespace std;
- unsigned long a=0;
- #ifdef SINGLE
- class A {
- public:
- virtual int f() { return a; }
- };
- class B : public A {
- public:
- virtual int f() { return a; }
- void g() { return; }
- };
- #endif
- #ifdef MULTIPLE
- class A {
- public:
- virtual int f() { return a; }
- };
- class dummy {
- public:
- virtual void g() { return; }
- };
- class B : public A, public dummy {
- public:
- virtual int f() { return a; }
- virtual void g() { return; }
- };
- #endif
- int main() {
- cin >> a;
- A* obj;
- if (a > 3)
- obj = new B();
- else
- obj = new A();
- unsigned long result = 0;
- clock_t time0 = clock();
- for (int i=0; i<65535; i++) {
- for (int j=0; j<65535; j++) {
- result += obj->f();
- }
- }
- clock_t time1 = clock();
- cout << (double)(time1 - time0) / CLOCKS_PER_SEC << endl;
- cout << result << "n";
- system("pause"); // This is useless in Linux, but I left it here for a reason.
- }
- .L5:
- call clock
- movl $65535, %r13d
- movq %rax, %r14
- xorl %r12d, %r12d
- .p2align 4,,10
- .p2align 3
- .L6:
- movl $65535, %ebx
- .p2align 4,,10
- .p2align 3
- .L7:
- movq 0(%rbp), %rax
- movq %rbp, %rdi
- call *(%rax)
- cltq
- addq %rax, %r12
- subl $1, %ebx
- jne .L7
- subl $1, %r13d
- jne .L6
- call clock
- ; %rbp = vtable
- movq 0(%rbp), %rax ; Dereference function pointer from vtable
- movq %rbp, %rdi
- call *(%rax) ; Call function pointer - f()
- #ifdef SINGLE
- class A {
- public:
- virtual int f() { return a; }
- };
- class B : public A {
- public:
- virtual int f() { return a; }
- void g() { return; }
- };
- #endif
- #ifdef MULTIPLE
- class A {
- public:
- virtual int f() { return a; }
- };
- class dummy {
- public:
- virtual void g() { return; }
- };
- class B : public A, public dummy {
- public:
- virtual int f() { return a; }
- virtual void g() { return; }
- };
- #endif
- int main() {
- cin >> a;
- A* obj;
- if (a > 3)
- obj = new B();
- else
- obj = new A();
- unsigned long result = 0;
- clock_t time0 = clock();
- for (int i=0; i<65535; i++) {
- for (int j=0; j<65535; j++) {
- result += obj->f();
- }
- }
- clock_t time1 = clock();
- cout << (double)(time1 - time0) / CLOCKS_PER_SEC << endl;
- cout << result << "n";
- // system("pause");
- }
- cout << "vtable: " << *(void**)obj << endl;
- for (int i=0; i<65535; i++) {
- for (int j=0; j<65535; j++) {
- result+=obj->f();
- }
- }
- 40092d: bb fe ff 00 00 mov $0xfffe,%ebx
- 400932: 48 8b 45 00 mov 0x0(%rbp),%rax
- 400936: 48 89 ef mov %rbp,%rdi
- 400939: ff 10 callq *(%rax)
- 40093b: 48 98 cltq
- 40093d: 49 01 c4 add %rax,%r12
- 400940: ff cb dec %ebx
- 400942: 79 ee jns 400932 <main+0x42>
- 400944: 41 ff c5 inc %r13d
- 400947: 41 81 fd fe ff 00 00 cmp $0xfffe,%r13d
- 40094e: 7e dd jle 40092d <main+0x3d>
- for (int i=0; i<65535; i++) {
- for (int j=0; j<65535; j++) {
- result+=obj->f();
- }
- }
- 400a54: bb fe ff 00 00 mov $0xfffe,%ebx
- 400a59: 66 data16
- 400a5a: 66 data16
- 400a5b: 66 data16
- 400a5c: 90 nop
- 400a5d: 66 data16
- 400a5e: 66 data16
- 400a5f: 90 nop
- 400a60: 48 8b 45 00 mov 0x0(%rbp),%rax
- 400a64: 48 89 ef mov %rbp,%rdi
- 400a67: ff 10 callq *(%rax)
- 400a69: 48 98 cltq
- 400a6b: 49 01 c4 add %rax,%r12
- 400a6e: ff cb dec %ebx
- 400a70: 79 ee jns 400a60 <main+0x70>
- 400a72: 41 ff c5 inc %r13d
- 400a75: 41 81 fd fe ff 00 00 cmp $0xfffe,%r13d
- 400a7c: 7e d6 jle 400a54 <main+0x64>
- .L30:
- movl $65534, %ebx
- .p2align 4,,7
- .L29:
- movq (%rbp), %rax
- movq %rbp, %rdi
- call *(%rax)
- cltq
- addq %rax, %r12
- decl %ebx
- jns .L29
- incl %r13d
- cmpl $65534, %r13d
- jle .L30
- 0x400a59 = 0b101001011001
- 0x400932 = 0b100100110010
- if (a>3) {
- B* objb = new B();
- objb->a = 5;
- obj = objb;
- }
- else
- obj = new A();