Cost of virtual calls with optimization

I have a question about the cost of virtual calls when the specified type is always the same:

class Base { Base() {}; virtual void Func() = 0; }; class Derived : public Base { Derived() : Base() {}; void Func() { /* Do something */ }; }; int main() { Base* base = new Derived; for (int i = 0; i < 1000; ++i) { base->Func(); } return 0; } 

Will the compiler optimize this virtual call?

+5
source share
5 answers

GCC with -O3 does not seem to optimize the virtual call.

https://goo.gl/TwZD6T

 .L5 movq (%rdx), %rdx cmpq Derived::Func(), %rdx je .L3 movq %rbp, %rdi call *%rdx subl $1, %ebx jne .L11 

This maps the function pointer and, if not equal, goes forward and performs an indirect function call.

+2
source

It is very difficult to optimize the virtuality of a function. You may not know at the correct compilation time that the virtual effect will have no effect. It is only during the connection, you can understand it.

What's even more problematic is that you won’t even be able to find out then, since you could dynamically load shared libraries that implement another subclass that can override a virtual function.

In principle, such an optimization requires quite smart connection-time optimizations, for which there is probably a rather small gain.

+2
source

VC ++, like GCC, does not optimize the call. built with Visual Studio 2013 in release mode with the / O 2 flag:

  base->Func(); 010B12D2 mov eax,dword ptr [esi] //load V-Table 010B12D4 mov ecx,esi //load this pointer into ecx 010B12D6 call dword ptr [eax] //call the first function in the V-Table. 

EDIT: Your question actually showed something very nice. esi contains this . how does smoothing this give a v-table? well, because a V-table is the first "variable" in which there is a polymorphic object. so the assembly, *this() actually calls the first function call, *(this+sizeof(void*))() calls the second function in the V table, and so on.
this is very similar to declaring your class as

 class A{ VTABLE vtable; //rest of the variables. } 
+1
source

It depends on the skill of your compiler; maybe he can optimize, maybe not. This is also an implementation detail β€” you care more about the overall performance of your code, rather than specific details. Measure your productivity and decide if you need optimization, and if so, your approach.

If you really like this code, you have options such as using the C ++ 11 final keyword and running a test for a type outside the loop instead of just using the vtable dispatcher inside the loop.

+1
source

The compiler cannot optimize this virtual call because the symbol for vtable for Derived externally visible and can be redefined at run time using the shared object and the environment variable LD_PRELOAD .

I think it should be able to optimize the call if you use the -fvisibility=hidden option.

0
source

Source: https://habr.com/ru/post/1233047/


All Articles