3
votes

I know that vtable lookup for virtual functions is a lot slower than straight up function calling since the base class has to search through the vtable to get the derived function. I was wandering if it would be even slower if there were more derived layers of classes. Basically, my question is the following:

Is Base->Derived (1 layer of inheritance) virtual function calling faster than Base->Derived1->Derived2->Derived3->DerivedEtc (multiple layers) virtual function calling?

1
If the inheritance is static, i.e. non virtual, then there's no searching. Dynamic dispatch is a single table lookup. And with virtual inheritance you only add one single extra step of indirection.Kerrek SB
"I know that vtable lookup for virtual functions is a lot slower than straight up function calling since the base class has to search through the vtable to get the derived function." According to the TR Performance, a virtual function call is typically not much slower than a normal function call. The cost you're paying is mostly that you cannot inline this function call. "Want performance? Measure."dyp
Short answer: No. Long answer: stackoverflow.com/questions/5868431/… Also note from the long answer that the table doesn't have to be "searched through". It's an indexed lookup known at compile time.Drew Dormann
The number of levels of inheritance doesn't matter. Only the most derived function address will be placed in the vtable, so the access is equally fast. Note that this is not necessarily the case for constructors or destructors during initialization.Rudy Velthuis

1 Answers

7
votes

There's no difference in the performance of a one-indirection lookup to find a virtual function to be called in the case of a two-levels inheritance derived class rather than a 40-levels inheritance derived class.

The reason is the following: each class holds a pointer to a virtual table which is used to resolve which function needs to be called for that specific object:

class Base
{
public:
    virtual void function1() {};
    virtual void function2() {};
};

class D1: public Base
{
public:
    virtual void function1() {};
};

class D2: public Base
{
public:
    virtual void function2() {};
};

the above code generates three virtual tables: one for objects of class Base, one for objects of class D1 and one for objects of class D2.

The important takeaway point here is that you don't need to traverse all virtual tables from the base up to find which function to call for a specific object:

enter image description here

in the diagram above you just

  1. Follow the vptr for your object (one indirection)
  2. Call the address of the function you're interested in

Modern compilers are able to optimize this process in the two points I listed above and except some particular cases this won't noticeably affect performances.

Credits: http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/


Extra: as dyp noted, the "slow performances" of virtual functions usually refers to the fact that these functions cannot be inlined due to the vtable indirection. Whether that matters or not really boils down to the code and architecture you're dealing with (e.g. register pressure and other factors).