views:

1796

answers:

11

In my class design, I use abstract classes and virtual functions extensively. I had a feeling that virtual functions affects the performance. Is this true? But I think this performance difference is not noticebale and looks like I am doing premature optimization. Right?

+11  A: 

A good rule of thumb is:

It's not a performance problem until you can prove it.

The use of virtual functions will have a very slight effect on performance, but it's unlikely to affect the overall performance of your application. Better places to look for performance improvements are in algorithms and I/O.

An excellent article that talks about virtual functions (and more) is Member Function Pointers and the Fastest Possible C++ Delegates.

Greg Hewgill
+3  A: 

absolutely. It was a problem way back when computers ran at 100Mhz, as every method call required a lookup on the vtable before it was called. But today.. on a 3Ghz CPU that has 1st level cache with more memory than my first computer had? Not at all. Allocating memory from main RAM will cost you more time than if all your functions were virtual.

Its like the old, old days where people said structured programming was slow because all the code was split into functions, each function required stack allocations and a function call!

The only time I would even think of bothering to consider the performance impact of a virtual function, is if it was very heavily used and instantiated in templated code that ended up throughout everything. Even then, I wouldn't spend too much effort on it!

PS think of other 'easy to use' languages - all their methods are virtual under the covers and they don't crawl nowadays.

gbjbaanb
+1  A: 

Yes, you're right and if you curious about the cost of virtual function call you might find this post interesting.

Serge
The article linked does not consider very important part of virtual call, and that is possible branch misprediction.
Suma
+2  A: 

The performance penalty of using virtual functions can never outweight the advantages you get at the design level. Supposedly a call to a virtual function would be 25% less efficient then a direct call to a static function. This is because there is a level of indirection throught the VMT. However the time taken to make the call is normally very small compared to the time taken in the actual execution of your function so the total performance cost will be nigligable, especially with current performance of hardware. Furthermore the compiler can sometimes optimise and see that no virtual call is needed and compile it into a static call. So don't worry use virtual functions and abstract classes as much as you need.

+8  A: 

When Objective-C (where all methods are virtual) is the primary language for the iPhone and freakin' Java is the main language for Android, I think it's pretty safe to use C++ virtual functions on our 3 GHz dual-core towers.

Chuck
+1  A: 

The only ever way that I can see that a virtual function will become a performance problem is if many virtual functions are called within a tight loop, and if and only if they cause a page fault or other "heavy" memory operation to occur.

Though like other people have said it's pretty much never going to be a problem for you in real life. And if you think it is, run a profiler, do some tests, and verify if this really is a problem before trying to "undesign" your code for a performance benefit.

Daemin
calling anything in a tight loop is likely to keep all that code and data hot in cache...
Greg Rogers
Yes, but if that right loop is iterating through a list of objects then each object could potentially be calling a virtual function at a different address through the same function call.
Daemin
+1  A: 

Duplicate of Performance penalty for working with interfaces in C++.

Does several levels of base classes slow down a class/struct in c++ seems also very close.

Suma
Why downvoting? You do not aggree this is a duplicate? Can you pleas comment?
Suma
+1  A: 

From page 44 of Agner Fog's "Optimizing Software in C++" manual:

The time it takes to call a virtual member function is a few clock cycles more than it takes to call a non-virtual member function, provided that the function call statement always calls the same version of the virtual function. If the version changes then you will get a misprediction penalty of 10 - 30 clock cycles. The rules for prediction and misprediction of virtual function calls is the same as for switch statements...

Boojum
+1  A: 

There's another performance criteria besides execution time. A Vtable takes up memory space as well, and in some cases can be avoided: ATL uses compile-time "simulated dynamic binding" with templates to get the effect of "static polymorphism", which is sort of hard to explain; you basically pass the derived class as a parameter to a base class template, so at compile time the base class "knows" what its derived class is in each instance. Won't let you store multiple different derived classes in a collection of base types (that's run-time polymorphism) but from a static sense, if you want to make a class Y that is the same as a preexisting template class X which has the hooks for this kind of overriding, you just need to override the methods you care about, and then you get the base methods of class X without having to have a vtable.

In classes with large memory footprints, the cost of a single vtable pointer is not much, but some of the ATL classes in COM are very small, and it's worth the vtable savings if the run-time polymorphism case is never going to occur.

See also this other SO question.

By the way here's a posting I found that talks about the CPU-time performance aspects.

Jason S
+4  A: 

In very performance critical applications (like video games) a virtual function call can be too slow. With modern hardware, the biggest performance concern is the cache miss. If data isn't in the cache, it may be hundreds of cycles before it's available.

A normal function call can generate an instruction cache miss when the CPU fetches the first instruction of the new function and it's not in the cache.

A virtual function call first needs to load the vtable pointer from the object. This can result in a data cache miss. Then it loads the function pointer from the vtable which can result in another data cache miss. Then it calls the function which can result in an instruction cache miss like a non-virtual function.

In many cases, two extra cache misses are not a concern, but in a tight loop on performance critical code it can dramatically reduce performance.

Mark James
+6  A: 

Your question made me curious, so I went ahead and ran some timings on the 3GHz in-order PowerPC CPU we work with. The test I ran was to make a simple 4d vector class with get/set functions

class TestVec 
{
    float x,y,z,w; 
public:
    float GetX() { return x; }
    float SetX(float to) { return x=to; }  // and so on for the other three 
}

Then I set up three 1024-vector arrays of these things (small enough to fit in L1) and ran a loop that added them to one another (A.x = B.x + C.x) 1000 times. I ran this with the functions defined as inline, virtual, and direct function calls, and the results were:

  • inline: 8ms
  • direct: 68ms
  • virtual: 160ms

So, in this case (where everything fits in cache) the virtual function calls were about 20x slower than the inline calls. But what does this really mean? Each trip through the loop caused exactly 12,288 function calls (1024 vectors times four components times three calls per add), so these times represent 12,288,000 function calls. The virtual loop took 92ms longer than the direct loop, so the additional overhead per call was 7 nanoseconds per function.

From this I conclude: yes, virtual functions are much slower than direct functions, and no, unless you're planning on calling them ten million times per second, it doesn't matter.

Crashworks
But if if they are called multiple times, they can often be cheaper than when only called one time. See my irrelevant blog: http://phresnel.org/blog/ , the posts titled "Virtual functions considered not harmful", but of course it depends on the complexity of your codepaths
phresnel
My test measures a small set of virtual functions called repeatedly. Your blog post assumes that the time-cost of code can be measured by counting operations, but that isn't always true; the major cost of a vfunc on modern processors is the pipeline bubble caused by a branch mispredict.
Crashworks