Connecting Tech Pros Worldwide Forums | Help | Site Map

runtime overhead of pure abstract classes

Needs Regular Fix
 
Join Date: Sep 2007
Location: The Netherlands
Posts: 427
#1: May 13 '08
If I have an base class consisting exclusively of abstract methods, would I incur any runtime overhead due to vtable lookups when calling methods of derived classes?

RRick's Avatar
Expert
 
Join Date: Feb 2007
Posts: 430
#2: May 14 '08

re: runtime overhead of pure abstract classes


You shouldn't incur any overhead beyond the vtable lookup of a virtual method. Remember, abstract methods are virtual methods. Also, verification that abstract methods are implemented is dealt with by the compiler and does not directly affect runtime performance.

Hmmmm, a base class with only abstract methods. Can you have an abstract destructor? Sounds possible, but I've never seen one.
Needs Regular Fix
 
Join Date: Sep 2007
Location: The Netherlands
Posts: 427
#3: May 14 '08

re: runtime overhead of pure abstract classes


Thanks, RRick. I was going to use an abstract class to define an interface for a number of closely related classes, so that I can store objects of different (derived classes) in a single array, for example. I hadn't thought of the consequences of using abstract constructors/desctructors, that shouldn't present any problems, should it?
Also, I could in principle use compile-time or static polymorphism through templates, that would save me vtable lookups. If we're dealing with millions of graphics objects, for example, that should save a lot of rendering time, right? Although I think the code could get a little abstruse then.
RRick's Avatar
Expert
 
Join Date: Feb 2007
Posts: 430
#4: May 14 '08

re: runtime overhead of pure abstract classes


You are talking about two issues here: class design and performance.

With your class design, you use abstract methods to force the derived class to implement them. This means the base class has no idea of what should be done.

You use virtual methods to allow overwriting but with a default behavior. In this case, it makes sense having the base class declare and define a virtual destruction. You want all of your derived classes to have one, but don't want to have to re-define a destructor if you don't need it.

Remember, use the correct design for the correct task.


As for performance of virtual methods, I simply don't worry about it. Vtable overhead is small (i.e. nano second small) and with Ghz machines, you can make millions or billions of vtable lookups in very little time.
Needs Regular Fix
 
Join Date: Sep 2007
Location: The Netherlands
Posts: 427
#5: May 14 '08

re: runtime overhead of pure abstract classes


OK. Just to check my idea is not flawed:
Say I'd like to put Fahrenheit and Celsius objects in the same vector array. To do this, I make F and C subclasses of a Temperature (T) class. Obviously, I don't have nor will ever have T objects, so the T class can be a purely abstract base class, then I can have vector<T> which will hold both F and C objects. The constructor/destructor of T can also be abstract if their counterparts differ in F and C classes. Does that sound right?

Now, since I'm running numerical analysis routines, the elements of the vector<T> will need to be iterated over roughly 1e12 times. So each 1 nanosecond vtable lookup translates to something around 1000 seconds or 15mins in total overhead. Not too bad, but is it worth the niceties of polymorphism here, or is there a better way?
Moderator
 
Join Date: Mar 2007
Location: North Bend Washington USA
Posts: 5,375
#6: May 14 '08

re: runtime overhead of pure abstract classes


Quote:

Originally Posted by arnaudk

To do this, I make F and C subclasses of a Temperature (T) class. Obviously, I don't have nor will ever have T objects, so the T class can be a purely abstract base class, then I can have vector<T> which will hold both F and C objects. The constructor/destructor of T can also be abstract if their counterparts differ in F and C classes. Does that sound right?

Close but not quite. C++ does not support the Liskov Substitution Principle where you substitute a derived object for a base object. With C++ you substitute a derived class object by using a base class pointer or reference.

That means your vector has to be a vector<T&> or a vector<T*>.

And that means you should be using handles: vector<Handle<T> >.

Read this article: http://bytes.com/forum/thread651599.html.
Needs Regular Fix
 
Join Date: Sep 2007
Location: The Netherlands
Posts: 427
#7: May 14 '08

re: runtime overhead of pure abstract classes


So you mean something like this?
Expand|Select|Wrap|Line Numbers
  1. #include "Handle.h"
  2.  
  3. class Temperature
  4. {
  5. public:
  6.     virtual Temperature() = 0;
  7.     virtual ~Temperature() = 0;
  8.     virtual float inDegreesKelvin() = 0;
  9. };
  10.  
  11. class Celsius: public Temperature
  12. {
  13. public:
  14.     Celsius(const float& degrees) : _degrees(degrees) { }
  15.     ~Celsius() { }
  16.     float inDegreesKelvin() const { return _degrees + 273.15 };
  17.     static Handle<Temperature> newhandle();
  18. private:
  19.     const float _degrees;
  20. }
  21.  
  22. inline Handle<Temperature> Celsius::newhandle(const float& degrees) 
  23.  {
  24.      Celsius* t = new Celsius( degrees );
  25.      Handle<Temperature> rval(t);
  26.      return rval;
  27.  }
  28.  
  29. int main()
  30. {
  31.     Handle<Temperature> boiling = Celsius::newhandle(100) ;
  32. }
  33.  
Now boiling is a (smart) pointer to the base class?
RRick's Avatar
Expert
 
Join Date: Feb 2007
Posts: 430
#8: May 14 '08

re: runtime overhead of pure abstract classes


Performance enhancements need to be compared to the total amount of time spent on performing a specific task.

In your example you are performing 10**12 operations. This means
  • 10**12 Vector accesses, object fetch and de-referencing
  • 10**12 method calls with parameter settings and register swapping
  • 10**12 Of actually doing something
In this type of environment, look up overhead is a small percent of the total time. I see no reason to try to improve performance on issues that take up 1% or less of my total time.
Reply