virtual funcs... performance penalty?

Started by
15 comments, last by A. Buza 23 years, 5 months ago
I was just curious as to any performance penalties incurred from using virutal and pure virtual functions when creating derived classes.
Advertisement
Don''t worry about it. For most of us, the speed difference is negligible.
Yes, there is a performance penalty (pointer to a function call).
Yes it is negligible in most every circumstance.

Basically, unless you''re doing a virtual function call in one of your inner most loops, you shouldn''t worry about it.

If you do still worry about it, there are ways to get some compilers to inline virtual functions. There was a Tip of the Day describing the basics of this on flipcode (www.flipcode.com) not too long ago...

You can also find information here:

http://msdn.microsoft.com/msdnmag/issues/0600/c/c0600.asp
Don''t worry at all. I''ve looked at the code produced by my compiler, and here''s the difference:

Non-virtual:
call ABCD;

Virtual:
call [0123];

That''s it! A memory reference, which (on a 386) take the clock count up to 10, instead of 7. Oh no.



David Owen
Actually, there''s a few more penalities than indicated.

First off, every instance of a class that has virtual functions has as an implicit member variable that is a pointer to the vtable for the function. So on an x86, that would double the memory required for a class that has only one variable. This leads to increased cache misses, memory motion costs, etc. Also it adds an mov instruction to the constructor for the class. For most classes that you use virtual functions for this isn''t a big deal, but it''s a good reason to never make a linked list node with a virtual function.

Second the function invocation code is slightly more complicated than previously indicated. Let''s say I have a class like so:
class Base {  virtual int Func1(int a);  virtual int Func2(int a);  int Func3(int a);};Base * b; 

Then
b->Func3(5);
would produce the following assembly (assuming eax was already loaded with b:

push 5
push eax
call @@Base@Func3$qi
add esp,8

on the other hand
b->Func2(5);
would produce the following assembly:

push 5
push eax
mov edx,dword ptr [eax]
call dword ptr [edx+4]
add esp,8

There is one additional instruction, and two additional pointer indirections, one of which is indexed. Again not a big deal, but you can see how in a tight loop it could be murder.
For those of you interested, I ran a simple performance test.

Basically I created an instance of a leaf class that was the 5th deriviation from a base class. This leaf class contained an empty virtual function and an empty normal function. I created an instance of the class as a pointer, and ran both functions in a loop 1 million times.

Virtual function time: 0.011080 seconds
Normal function time: 0.008243 seconds

FYI, If it''s a normal variable then the time is exactly the same.

My compiler: VC6


- Houdini
- Houdini
How do you look at the compiler output/browse it/find certain sections?

By ''virtual'' function, do you mean one that has overriden a virtual one, but is no longer declared as virtual anymore??? If I override in the first child class down, can I override again in the next one down, even if the one in the first one down isn''t marked as virtual over again. Are all versions ''virtual''...?

Thanks
If function declared as virtual in base class, it will be virtual in all derived class, independly you write ''virtual'' world in derived class or not
The big performance penalty is when you use a base class pointer to a derived class and call an overridden function (all pure virtuals, and some virtuals).

Then again, the "big" performance penalty made by code about 200% slower on a 33MHz machine... I suppose it would only be about 6% slower on a 1000MHz machine... but still, that''s 6%!
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Yes, but do you think that most of the processing power your game takes up is in function calls? It''s spent displaying graphics and calculating AI. In my tests (using a base class pointer to a derived class and calling an overridden function) you lose a whole 0.003 seconds (3 milliseconds) for every 1 million virtual function calls.

- Houdini
- Houdini

This topic is closed to new replies.

Advertisement