Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Virtual method VS std::function member variable in terms of performance

A game engine has this class :

class  MouseListener{
public :
MouseListener();
virtual void OnMouseDown(int mx,int my);
virtual void OnMouseUp(int mx,int my);
.
.
.
};

Each object that wants to listen to mouse input , have to inherent that class and override it's methods . To not have to declare a new type each time , the class is modified to :

class  MouseListener{
public :
MouseListener();
std::function <void(MouseListener*,int,int)>OnMouseDown;
std::function <void(MouseListener*,int,int)>OnMouseUp;
.
.
.
};

now using the class can be done this way :

MouseListener * m = new MouseListener();
m->OnMouseDown = [](MouseListener * thiz,int x,int y){
   //// do something
};

From the input system , only the functions of MouseListener that are not null ( assigned ) are called ( with thiz = the mouse listener ). knowing that the class is used from an external library ( static link ) , which is better in terms of performance ?

NOTE : None of those function will be called unless a mouse event is received , when that happens , the appropriate function is called for each object listening to mouse input ( not supposed to be lot , <50)

like image 861
Dhia Hassen Avatar asked Dec 18 '16 13:12

Dhia Hassen


People also ask

Do virtual member functions run faster?

Virtual functions are by definition slower than their non-virtual counterparts; we wanted to measure the performance gains from inlining; using virtual functions would make the difference even more pronounced. In this particular example, CLANG 10 compiler inlined the functions and unrolled the test loop two times.

Is std :: function slow?

Code wrapped into std::function is always slower than inlining code directly into calling place. Especially if your code is very short, like 3-5 CPU instructions.

What is the advantage of virtual function in C++?

A virtual function allows derived classes to replace the implementation provided by the base class. The compiler makes sure the replacement is always called whenever the object in question is actually of the derived class, even if the object is accessed by a base pointer rather than a derived pointer.

How does virtual function differ from function in C++?

Virtual functions ensure that the correct function is called for an object, regardless of the type of reference (or pointer) used for function call. Functions are declared with a virtual keyword in base class. The resolving of function call is done at runtime.


1 Answers

It really depends on the usage of the virtual function vs. the function object.

although std::function may be slower than a virtual call*, std::function has short buffer optimization , which may prevent dynamic memory allocation (which you would probably have in the virtual version).
this itself may outperform anything you might do with regular polymorphism.

Internally (but not guaranteed), the std::function object anyway uses a virtual call for the type erasure, so I'd say the difference is negligible.

A tip - make sure to check if the std::function is valid (by calling if(static_cast<bool>(myFunction))). the compiler will insert a check to see if the function is empty. if not, the program will throw std::bad_function_call. the developer check will make the compiler remove his check and the code related to std::bad_function_call when optimizations are turned on, leaving much "smoother" assembly code.

when dealing with performance and C++ in my experience, it's much more important to optimize away memory allocations, inter-thread-contention and bad data structures which work bad with the cache. usually, it's much more worthy optimizations than optimizing CPU-stuff away (like virtual function vs. std::function)

*A decent compiler can implement the type erasure as a virtual function + the given lambda as inlined function. theoretically, it should not be slower than a regular virtual function. on the other hand, if the function object gets a non-inlinable callable, like a function pointer, it may use two indirection in order to launch the function. this may be slower than a regular virtual call. it depends.

like image 122
David Haim Avatar answered Oct 16 '22 12:10

David Haim