Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it worth it to avoid polymorphism in order to gain performance?

Is it worth it to avoid polymorphism in order to gain performance?

I read in Stroustrup's book that polymorphic function call is within 25% more expensive than an ordinary function call. Does this mean I should avoid polymorphism whenever possible? I mean should I always be thinking something like: OK polymorphism would solve this problem but it might mess up performance bla bla... Or given the power of modern CPUs, I should not even dare to think that?

like image 365
user3111311 Avatar asked Jan 16 '14 01:01

user3111311


3 Answers

I read in Stroustrup's book that polymorphic function call is within 25% more expensive than an ordinary function call.

This might be the case (probably a ball-park figure), but it's not that important. Even if a virtual function call is 25% more expensive than an ordinary function call, this is still just the cost of the function call, not the cost of the function execution. I just wanted to make that precision. The cost of the function call will often be much smaller than the cost of the function execution. But watch out, it's not always insignificant either, if you abuse polymorphism and have it for all functions, even the most trivial ones, then that extra overhead can add up very quickly.

Most importantly though, virtual function calls have to be dispatched through a function pointer, and function pointers mean no inlining, or any form of cross-contextual optimization. That is usually where most of the slow down will come from, i.e., you should not be comparing a "virtual function call" to a "function call", but rather a "virtual function call" to a "statically analyzable, potentially inline-able, lto-optimizable function call".

Is it worth it to avoid polymorphism in order to gain performance?

In C++, and in programming in general, whenever there's a price, there's a gain, and whenever there's a gain, there's a price. It's that simple. Dynamic polymorphism comes with a price in the form of (1) overhead on function calls, (2) blocking static analysis and optimizations, (3) often requiring heap-allocated objects and extra indirection (pointers, references, etc.), and so on, just to name a few. However, you also make substantial gains in the form of (1) run-time flexibility, (2) scalability (disjoint unions of problem domains), (3) reduced compilation times, (4) less code repetition, and so on.

The point is, if you want the things that polymorphism buys you, then you should use it. But if you don't need those things (and you'd be surprised how often you don't need those things), then you shouldn't pay an unnecessary price for it. It's that simple.

For more details on the alternatives and trade-offs, I suggest this article.

like image 120
Mikael Persson Avatar answered Oct 13 '22 11:10

Mikael Persson


I read in Stroustrup's book that polymorphic function call is within 25% more expensive than an ordinary function call. Does this mean I should avoid polymorphism whenever possible?

No, absolutely not! A non-virtual call is extremely fast, because the call itself is usually a single instruction. A virtual call requires an additional level of indirection; that's where the alleged 25% are coming from, but that is "pure overhead", i.e. one that you measure when you compare calls of two parameterless functions. Once you start adding parameters, especially ones that require copying, the gap between the two overheads is going to shrink: for example, passing a string by value to a virtual and a non-virtual function would make this gap very hard to measure.

Moreover, it is only the call instructions themselves that are more expensive, not the function. The overhead of calling a function represents a small percentage of the overall timing of the function. The longer the function, the smaller percentage the overhead of the call is representing.

Overall, you should strive for understandability of your code. If adding a subclass with virtual functions makes it easier to understand your design, then by all means you should use subclassing. The hardware on which your code runs becomes faster every year, so in the long run, readability wins.

like image 30
Sergey Kalinichenko Avatar answered Oct 13 '22 12:10

Sergey Kalinichenko


The virtual table lookup overhead is not a problem in "most" cases. That being said, if efficiency is a requirement:

  • For something like a visitor pattern, you can perhaps use a templated solution instead of a virtual function-based one.
  • One should also consider static polymorphism, with the Curiously Recurring Template Pattern.

Keep in mind that this is important only if you work on a "sensitive" system like a logging or monitoring interface, or algorithms which need to call different callbacks repeatedly, such as an A* or a behavior tree.

like image 1
armand Avatar answered Oct 13 '22 13:10

armand