Tuesday, November 23, 2010

Optimization -05

Tips for Optimizing C++ Code

12. Careful when declaring C++ object variables.
  • Use initialization instead of assignment (Color c(black); is faster than Color c; c = black;).

13. Make default class constructors as lightweight as possible.
  • Particularly for simple, frequently used classes (e.g., color, vector, point, etc.) that are manipulated frequently.
  • These default constructors are often called behind your back, where you are not expecting it.
  • Use constructor initializer lists. (Use Color::Color() : r(0), g(0), b(0) {} rather than Color::Color() { r = g = b = 0; } .)

16. For most classes, use the operators +=, -=, *=, and /=, instead of the operators +, -, *, and /.
  • The simple operations need to create an unnamed, temporary intermediate object.
  • For instance: Vector v = Vector(1,0,0) + Vector(0,1,0) + Vector(0,0,1); creates five unnamed, temporary Vectors: Vector(1,0,0), Vector(0,1,0), Vector(0,0,1), Vector(1,0,0) + Vector(0,1,0), and Vector(1,0,0) + Vector(0,1,0) + Vector(0,0,1).
  • The slightly more verbose code: Vector v(1,0,0); v+= Vector(0,1,0); v+= Vector(0,0,1); only creates two temporary Vectors: Vector(0,1,0) and Vector(0,0,1). This saves 6 functions calls (3 constructors and 3 destructors).

18. Delay declaring local variables.
  • Declaring object variable always involves a function call (to the constructor).
  • If a variable is only needed sometimes (e.g., inside an if statement) only declare when necessary, so the constructor is only called if the variable will be used.

19. For objects, use the prefix operator (++obj) instead of the postfix operator (obj++).
  • This probably will not be an issue in your ray tracer.
  • A copy of the object must be made with the postfix operator (which thus involves an extra call the the constructor and destructor), whereas the prefix operator does not need a temporary copy.

20. Careful using templates.
  • Optimizations for various instantiations may need to be different!
  • The standard template library is reasonably well optimized, but I would avoid using it if you plan to implement an interactive ray tracer.
  • Why? By implementing it yourself, you'll know the algorithms it uses, so you will know the most efficient way to use the code.
  • More importantly, my experience is that debug compiles of STL libraries are slow. Normally this isn't a problem, except you will be using debug versions for profiling. You'll find STL constructors, iterators, etc. use 15+% of your run time, which can make reading the profile output more confusing.