Optimization tip: reduce the amount of code to execute

21 Jul

Reducing the amount of code to execute is not always the work of the compiler, the person writing the code has to be conscious of how the code will end up in instructions in order to obtain optimized binary code.

Order the statements in your if clauses

Statements in if clauses are evaluated from left to right.That is why we can write statements like

if (ptr && ptr->method())

without having our program crash when ptr is NULL. It means that we can speed up things if we order the expressions on complexity. So we should first check booleans expressions, then comparisons and finally heavy functions. Since the compiler cannot know whether it can safely reorder the expressions, it is the person writing the code which should do this work.

Use pre increment, unless you need a return value

Most of the time when I see for loops with iterators people are using post operators. A post operator however is slower as it needs to make a copy first, which is returned after incrementing the original iterator. The overhead is dependent on the complexity of the iterator. For basic types, int, float etc, the compiler will see that you don’t need a return value and optimizes it, however for custom operators the compiler will leave it as is as it cannot foresee the possible side effects.

for (type::iterator i = container.begin(); i != container.end(); ++i)

The post operator is handy when you need to conditionally remove items, since the copy of the iterator is used to remove, and the original iterator stays valid. However that depends on the container’s implementation of course, so check the documentation first.

type::iterator i = container.begin();
while (i != container.end()) {
  if (i->condition)
    container.remove(i++);
  else ++i;
}

Use default objects

When making your own vector, matrix and color classes, it is always good to reduce the overhead of allocating and initing often used objects. For example the zero Vector (0, 0) or the color black (0, 0, 0, 1.0f) are objects which will often appear in your code. Instead of using Vector(0, 0) each time or Vector(), it is best to use a static const Vector::zero. This way it is only allocated once and can be used without overhead, given that your api should take const vector & parameters in order to avoid copies.

class Vector {
  ..
static const Vector zero;
  ..
};

const Vector Vector::zero(0.0f, 0.0f);

How much time does this save?

This all depends on the application, how many times particular code is run and what hardware it runs on. Nowadays we use a lot of different devices. While you might write code on a shiny quad-core android 4.x device, someone else might be going to run your game or application on a cheaper 2.3 device. While they say you shouldn’t be trying to optimize code before it’s finished, I think these micro optimizations are just a matter of changing style. It doesn’t cost more time when writing the code, and if they appear in code which is ran a lot, they will definitely make a difference.

Advertisements

2 Responses to “Optimization tip: reduce the amount of code to execute”

  1. Paul Hewlett October 20, 2013 at 3:34 pm #

    Your note about using i++ instead of ++i used to be true. Most modern compilers detect when the result is not going to be used and silently convert to ++i for you.

    • mflerackers October 20, 2013 at 11:15 pm #

      The compiler only optimizes when you use the operators on basic types. Once you work with classes and overloaded operators it doesn’t replace them. While the compiler could technically do this, there are too many problems with this optimization. For example you are not obligated to write both pre and post-increment operators for your class, so the pre-increment operator might not be available. Even if you implemented both, the compiler cannot predict the side effects you may have implemented in the different operators, so it can’t know whether it is safe to replace them. For basic types this is no problem as it builds the code itself, but with custom operators it takes no chance and just uses the code as is. If you built and run this code http://pastebin.com/459zmhmp on GCC or LLVM it will print the operators exactly as you write them in the code.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: