I am seeing a performance issue with virtual functions and it impacts every function call with virtual functions. why am i seeing virtual fns execute slower? Is it because virtual function call requires run time type of owning class to be identified or it has to search for proper class binding or it requires a table lookup at runtime before calling or class must use memory to maintain a table of virtual function pointers? please clarify me here.
In below code for both the call on obj.f(); and on
obj2ref.f(); there is the possibility that at run time obj is of some derived class, so it has to search for the actual type in order to determine which f() is to be called.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
struct Class{
virtualvoid f() {...}
};
struct Class2 : public Class {
virtualvoid f() {...}
};
Class obj;
obj.f();
Class2 obj2;
obj2.f();
Class& obj2ref = obj2;
obj2ref.f();
> Ok, so virtual function is slower than normal functions as it requires a table lookup at runtime before calling.
> Correct?
The cost of the v-table look up may not be the most significant overhead; inability to inline (and optimise across) the call, and (in large programs) poor cache performance may contribute more to the overhead.
A v-table look up may not be required if the compiler can determine the the final overrider at compile time.
For example: https://gcc.godbolt.org/z/9hhsWxdjz
The virtual function call has to search for the correct class binding. Does this impact the slowness or performance here? Also is there any way to overcome the slowness of virtual function in c++? any way to override it?
My understanding is that virtual function requires a table lookup at runtime before calling. Are there any other factors that might impact the performance by using virtual functions here?
Ok, so if runtime lookup is not needed here, does it mean slowness could be due to the fact that class must use memory to maintain a table of virtual function pointers?
> could be due to the fact that class must use memory to maintain a table of virtual function pointers?
Not usually; the v-table does not take a huge amount of storage. Certainly not relevant in such a small program.
How big are these functions? Did you compile the code with optimisations enabled? https://gcc.godbolt.org/z/M3We55s7K
I haven't tried optimizations on it as its big code base. But just want to clarify if the slowness is because "the virtual function call requires the run time type of the owning class to be identified", when comparing it to a statically bound call ?
> "the virtual function call requires the run time type of the owning class to be identified"
In the typical implementation, the object in question would have a v-table pointer as part of its object layout. That (and the table it points to) is what is looked up at run-time.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
struct Class{
virtualvoid f() = 0 ;
int i ;
};
int foo( Class& c )
{
c.f() ;
/*
mov rax, QWORD PTR [rdi] // get the vtbl pointer in the object (into rax)
call [QWORD PTR [rax]] // look up the vtbl and call the function
*/
}
> Could slowness be due to fact that virtual function call has to search for the correct class binding?
No, there is no elaborate 'search' involved.
1. Look into the object and get the v-table pointer
2. Look up the v-table, get the address of the function and call the function at that address.
Could slowness be due to fact that virtual function call has to search for the correct class binding?
Probably not. The pointer to the vtable is set when the object is constructed, so the "search for the correct class" is simply a dereferencing the vtable pointer.
Let's go back to the beginning:
I am seeing a performance issue with virtual functions and it impacts every function call with virtual functions.
Can you tell us more about this. What makes you think that the problem is the fact that the functions are virtual, rather than the content of the functions themselves? Unless the virtual functions are extremely small, I doubt that a performance problem is related to them being virtual.
I have read the doc from the link. Thanks for sharing it. so can I conclude that compared to a statically bound call, virtual function calls are slower as virtual function call requires the run time type of the owning class to be identified?