Virtual function vs function pointer - performance?

Are C ++ virtual functions called in a polymorphic base class as fast as calling a C-style function pointer? Is there any difference?

I am considering refactoring some kind of performance-oriented code that uses pointers to functions and translates them into virtual functions in polymorphism.

+8
c ++ c
source share
5 answers

I would say that most C ++ implementations are similar to this (and probably the first implementation that compiled in C created the following code):

struct ClassVTABLE { void (* virtuamethod1)(Class *this); void (* virtuamethod2)(Class *this, int arg); }; struct Class { ClassVTABLE *vtable; }; 

Then, given the instance of Class x , calling virtualmethod1 for it is similar to x.vtable->virtualmethod1(&x) , so one extra dereference, one index search from vtable and one extra argument (= this ) pushed the stack.

However, the compiler can probably optimize method callbacks for the instance inside the function: since the Class x instance cannot change its class after it is built, the compiler can consider the whole x.vtable->virtualmethod1 as a common subexpression, and pull it out of loops. Thus, in this case, the repeated call of the virtual method within the same function will be equivalent in speed to the function call using a simple function pointer.

+19
source share

Are C ++ virtual functions implemented in a polymorphic base class as fast as calling a C-style function pointer? Is there any difference?

Apples and oranges. At the minimum one-to-one level, the level of calling a virtual function requires a bit more work, since there is overhead information about specifying / indexing to switch from vptr to vtable .

But calling a virtual function can be faster

Well, how could that be? I just said that calling a virtual function requires a bit more work, which is true.

What people tend to forget is to try to make a closer comparison here (to try to make it a little smaller than apples and oranges, although these are apples and oranges). Usually we do not create a class with one virtual function. If we did this, then performance (as well as even things like code size) would definitely support a function pointer. We often have something more:

 class Foo { public: virtual ~Foo() {} virtual f1() = 0; virtual f2() = 0; virtual f3() = 0; virtual f4() = 0; }; 

... in this case, there may be more โ€œdirectโ€ analogies to a function pointer:

 struct Bar { void (*f1)(); void (*f2)(); void (*f3)(); void (*f4)(); }; 

In this case, calling virtual functions in each case Foo can be significantly more efficient than Bar . This is because Foo only needs to store one vptr for the central vtable, which is accessed more than once. At the same time, we get improved locality of links (fewer Foos and those that can potentially fit better and in number in the cache line, more frequent access to the central vtable Foo's ).

Bar , on the other hand, requires more memory and effectively duplicates the contents of Foo's vtable in each instance of Bar (let's say there are a million instances of Foo and Bar ). In this case, the amount of redundant data inflating the size of Bar often far outweighs the cost of doing a little less work to call a pointer to a function.

If we only needed to save one pointer to an object, and it was a very strong spot, then it would be nice to just save a pointer to a function (for example: it can be useful for those who implement everything that remotely resembles std::function just to save a pointer per function).

So, itโ€™s kind of apples and oranges, but if we model an example of use, then close to this, an approach like vtable, which stores a central common table of function addresses (in C or C ++), can be much more efficient.

If we simulate a use case in which we have only one function pointer stored in an object vs. vtable, which has only one virtual function, then the function pointer will be somewhat more efficient.

+10
source share

It is not clear that you will see most of the difference, but, like all these things, often there are small details (such as a compiler that needs to pass the this pointer to a virtual function), which can cause differences in performance. The virtual function itself is a pointer to a function โ€œunder the hood,โ€ so you'll probably get very similar code in both cases once the compiler does its work.

It sounds like a good use of virtual functions, and if someone objected and said "there will be a difference in performance," I would say "prove it." But if you want to avoid this discussion, make a benchmark (if it is not already) that measures the performance of existing code, reorganizes it (or part of it), and compares the results. Ideally, test on several different machines so that you do not get results that work better on YOUR machine, but are not so good on some other types of machines (different generations of processors, different manufacturers or processors, etc.).

+6
source share

A virtual function call includes two differences, one of which is indexed, that is, something like *(object->_vtable[3])() .

Calling with a function pointer involves one dereferencing.

A method call also requires passing a hidden argument, which must be received as this .

If the body of the method is practically empty and there are no arguments or return values, you are unlikely to notice the difference.

+5
source share

The difference between calling a function pointer and calling a virtual function is negligible unless you have already measured that the above is a bottleneck.

The only difference:

  • virtual function has memory readable for vtable and indirect call of function address
  • a function pointer has only one indirect function call

This is because a virtual function requires looking up the address of the function that it will call while the function pointer already knows (since it is stored by itself).

I would add that since you are working with C ++, virtual methods should be on the way.

+2
source share

All Articles