views:

798

answers:

8

Question is as stated in the title: What are the performance implications of marking methods / properties as virtual?

Note - I'm assuming the virtual methods will not be overloaded in the common case; I'll usually be working with the base class here.

+1  A: 

From your tags, you're talking c#. I can only answer from a Delphi perspective. I think it will be similar. (I am expecting negative feedback here :) )

A static method will be linked at compile time. A virtual method requires a lookup at run-time to decide which method to call, so there is a small overhead. It is only significant if the method is small and called often.

Richard A
+14  A: 

Virtual functions only have a very small performance overhead compared to direct calls. At a low level, you're basically looking at an array lookup to get a function pointer, and then a call via a function pointer. Modern CPUs can even predict indirect function calls reasonably well in their branch predictors, so they generally won't hurt modern CPU pipelines too badly. At the assembly level, a virtual function call translates to something like the following, where I is an arbitrary immediate value.

MOV EAX, [EBP + I] ; Move pointer to class instance into register
MOV EBX, [EAX] ;  Move vtbl pointer into register.
CALL [EBX + I]  ;   Call function

Vs. the following for a direct function call:

CALL I  ;  Call function directly

The real overhead comes in that virtual functions can't be inlined, for the most part. (They can be in JIT languages if the VM realizes they're always going to the same address anyhow.) Besides the speedup you get from inlining itself, inlining enables several other optimizations such as constant folding, because the caller can know how the callee works internally. For functions that are large enough not to be inlined anyhow, the performance hit will likely be negligible. For very small functions that might be inlined, that's when you need to be careful about virtual functions.

Edit: Another thing to keep in mind is that all programs require flow control, and this is never free. What would replace your virtual function? A switch statement? A series of if statements? These are still branches that may be unpredictable. Furthermore, given an N-way branch, a series of if statements will find the proper path in O(N), while a virtual function will find it in O(1). The switch statement may be O(N) or O(1) depending on whether it is optimized to a jump table.

dsimcha
One of the most informative posts I've seen in a while that I had no knowledge of before hand and was still easily understandable.
Chris Marisic
Excellent answer - thank you very much. As I'm not planning on calling my methods in a very tight loop, I won't worry too much about this overhead. Thank you for the help =)
Erik Forbes
A: 

Not a great deal. If you're using any of the following then it's likely to be negligible to the overall performance of your application: networks, databases, files, reflection, XML... in fact pretty much anything interesting.

It might take an extra clock cycle... but then again it might not. Certainly not worth losing any sleep over.

I did some timing tests a while back on static vs instance method performance; it would be simple to modify the code to check virtual method dispatch as well if you really want some figures.

Greg Beech
A: 

On the desktop side it doesn't matter if the method are overloaded or not, they incur a extra level of indirection through the method pointer table (Virtual method table), which means roughly 2 extra memory reads through indirection before the method call compared a non virtual methods on non sealed classes and non final methods.

[As an interesting fact, on compact framework version 1.0 the overheat is greater as it doesn't use virtual method tables but simply reflection to discover the right method to execute when calling a virtual method.]

Also virtual methods are far less likely to be candidates for inlining or other optimizations like tail call than non virtual methods.

Roughly this is the performance hierarchy of method calls:

Non virtual methods < Virtual Metods < Interface methods (on classes) < Delegate dispatch < MethodInfo.Invoke < Type.InvokeMember

But none of these performance implications of various dispatch mechanisms don't matter unless you proven it by measuring ;) (And even then the architecture implications, readability etc might have a big weight on which one to chose)

Pop Catalin
+7  A: 

Typically a virtual method simply goes through one table-of-function-pointers to reach the actual method. This means one extra dereference and one more round-trip to memory.

While the cost is not absolutely ZERO, it is extremely minimal. If it helps your program at all to have virtual functions, by all means, do it.

Its far better to have a well-designed program with a tiny, tiny, tiny performance hit rather than a clumsy program just for the sake of avoiding the v-table.

abelenky
The biggest cost of virtual function calls isn't the pointer load from the vtable, but the pipeline clear that results from a mispredicted branch (and vjumps are usually mispredicted). That can be as long as the pipeline itself. For very frequently called functions, it adds up.
Crashworks
+2  A: 

It's hard to say for sure, because the .NET JIT compiler may be able to optimize the overhead away in some (many?) cases.

But if it does not optimize it away, we are basically talking about an extra pointer indirection.

That is, when you call a non-virtual method, you have to

  1. Save registers, generate the function prologue/epilogue to set up arguments, copy the return value and such.
  2. jump to a fixed, and statically known, address

1 is the same in both cases. As for 2, with a virtual method, you have to instead read from a fixed offset in the object's vtable, and then jump to wherever that points. That makes branch prediction harder, and it may push some data out of the CPU cache. So the difference isn't huge, but it can add up if you make every function call virtual.

It can also inhibit optimizations. The compiler can easily inline a call to a nonvirtual function, because it knows exactly which function is called. With a virtual function, that is a bit trickier. The JIT-compiler may still be able to do it, once it's determined which function is called, but it's a lot more work.

All in all, it can still add up, especially in performance-critical areas. But it's not something you need to worry about unless the function is called at the very least a few hundred thousand times per second.

jalf
+1  A: 

I ran this test in C++. A virtual function call takes (on a 3ghz PowerPC) between 7-20 nanoseconds longer than a direct function call. That means it really only matters for functions you plan on calling a million times per second, or for functions that are so small that the overhead may be larger than the function itself. (For example, making accessor functions virtual out of blind habit is probably unwise.)

I haven't run my test in C#, but I expect that the difference will be even less there, since nearly every operation in the CLR involves an indirect anyway.

Crashworks
"interpreted runtime"? ah cmon people, .Net is not even a real virtual machine, and there still are people after 9 years that think .Net is interpreted....pff
Pop Catalin
my bad -- fixed.
Crashworks
+5  A: 

Rico Mariani outlines issues regarding performance in his Performance Tidbits blog, where he stated:

Virtual Methods: Are you using virtual methods when direct calls would do? Many times people go with virtual methods to allow for future extensibility. Extensibility is a good thing but it does come at a price – make sure your full extensibility story is worked out and that your use of virtual functions is actually going to get you to where you need to be. For instance, sometimes people think through the call site issues but then don’t consider how the “extended” objects are going to be created. Later they realize that (most of) the virtual functions didn’t help at all and they needed an entirely different model to get the “extended” objects into the system.

Sealing: Sealing can be a way of limiting the polymorphism of your class to just those sites where polymorphism is needed. If you will fully control the type then sealing can be a great thing for performance as it enables direct calls and inlining.

Basically the argument against virtual methods is that it disallows the code to be a candidate of in-lining, as opposed to direct calls.

In the MSDN article Improving .NET Application Performance and Scalability, this is further expounded:

Consider the Tradeoffs of Virtual Members

Use virtual members to provide extensibility. If you do not need to extend your class design, avoid virtual members because they are more expensive to call due to a virtual table lookup and they defeat certain run-time performance optimizations. For example, virtual members cannot be inlined by the compiler. Additionally, when you allow subtyping, you actually present a very complex contract to consumers and you inevitably end up with versioning problems when you attempt to upgrade your class in the future.

A criticism of the above, however, comes from the TDD/BDD camp (who wants methods defaulting to virtual) arguing that the performance impact is negligible anyway, especially as we get access to much faster machines.

Jon Limjap