Montag, 22. April 2013

C++: Schleifen: Zähler inkrementieren

Ich habe heute überlegt wie ich meinen Code optimieren könnte. Dabei habe ich folgende Quellcodes verglichen (disassembliert):

for(int i = 0; i < 10; ++i) {}

versus

for(int i = 0; i < 10;) {++i;}

Der Unterschied ist, dass beim oberen auch im disassemblierten Code das inkrementieren vor dem Ausführen des Schleifenrumpfs geschieht, aber warum auch immer wird dabei eine Anweisung (jmp) mehr erzeugt als bei dem Unteren.
Somit ist der untere Code tatsächlich schneller. Dies ist aber nicht Allgemeingültig. Bei komplexeren Code sieht das ganz anders aus.

for(vector::iterator it = rle.begin(); it != rle.end(); ++it)
{
  if (it->parent == &*it)
    it->region = i++;
  else
    it->region = it->parent->region;
}

Wenn man nun hier aus dem

it->region
it++->region

macht und das Inkrementieren im Schleifenkopf entfernt, dann wird der Code (disassembliert) tatsächlich größer (ca. 20 Anweisungen mehr).

Daraus schließe ich, dass es sinnvoller ist, das Inkrementieren eines Zählers im Schleifenkopf zu behalten.

Ob Postinkrement, oder Preinkrement, im Schleifenkopf ist hier egal gewesen, da beides so trivial ist, dass der Compiler das optimiert bekommen hat.
Für dieses Experiment wurde Microsoft Visual Studio 2012 benutzt und im Debugmodus der disassemblierten Code betrachtet.