Jochens Weblog

ESCde Developer Blog

  Home :: Kontakt :: RSS Feed
  12 Posts :: 0 Artikel :: 4 Kommentare :: 0 Trackbacks

Archiv

Post Kategorien

ESCde

ESCde Blogger

Haben Sie sich schon mal Gedanken darüber gemacht, ob eine foreach-Schleife schneller als eine For-Schleife ist? Zugegeben, in den meisten Windows Forms-Anwendungen spielt dies kaum eine Rolle, da die Anzahl der Schleifendurchläufe einfach zu gering ist, als dass ein Unterschied überhaupt auffallen würde. Allerdings gibt es auch Situationen, in denen solche kleinen Optimierungen in der Summe dann wieder relevant werden können, beispielsweise bei der Spieleentwicklung unter XNA oder bei Anwendungen, die mit komplexen, Schleifen-intensiven Algorithmen große Datenmengen durchkauen ("Number-Crunching").

Vergleichen Sie die beiden folgenden Schleifen:

foreach (int i in int_list) { DoSomething(i); }

for (int i = 0; i < int_list.Count; i++) { DoSomething(int_list[i]); }

Diese beiden Schleifen machen semantisch exakt das gleiche, allerdings passiert bei der foreach-Schleife intern deutlich mehr. Implementieren Sie einfach mal das generische Interface IEnumerable, dann sehen Sie sofort den Unterschied.

Je nach Anzahl der Schleifendurchläufe (und natürlich auch abhängig von den Operationen in der Schleife) schwankt der Performance-Unterschied deutlich, allerdings lässt sich festhalten, dass eine for-Schleife gegenüber foreach eigentlich immer die Nase vorn hat. Das heißt natürlich nicht, dass foreach nicht nützlich wäre: foreach geht sehr leicht von der Hand und kann komplexe Schleifenkonstrukte sehr schön darstellen. Wenn allerdings Performance das ausschlaggebende Kriterium ist, lässt sich mit for ein Quentchen mehr Leistung aus dem Rechner pressen.

Aber es geht noch besser: selbst die soeben hochgelobte for-Schleife lässt sich noch ein wenig "tieferlegen". Sehen Sie sich die folgende Schleife an:

int len = int_list.Count; for (int i = 0; i < len; i++) { DoSomething(li[i]); }

Diese for-Schleife spart gegenüber der Version weiter oben wieder ein paar Taktzyklen ein. Wieso? Properties scheinen auf den ersten Blick einfach nur eine Variable auszulesen. In Wahrheit versteckt sich hinter ihnen allerdings ein Methodenaufruf. Also ein Sprung, ablegen einer Rücksprungadresse auf den Stack, etc, alles nicht so schlimm, aber bei seeehr vielen Schleifendurchläufen irgendwann spürbar. Deshalb sparen wir uns die ständige Springerei und speichern die (sich nicht verändernde) Anzahl der zu iterierenden Listenelemente in einer Variablen. Noch schneller geht's wohl nur in Assembler...

veröffentlicht am 06.03.2007 15:23

Kommentare

# re: Performante Schleifen knüpfen vom 19.03.2007 15:45 von Elke
Das ist aber nur sinnvoll wenn man keinerlei Einfluss auf die Variablen braucht - wenn man z.b. in einem bestimmten Bereich (angenommen von i= 10 bis i = 20 ) die Schleife durchlaufen möchte

# re: Performante Schleifen knüpfen vom 02.04.2007 10:41 von Jochen Schimmel
Völlig richtig, sobald man in der Schleife Veränderungen durchführt, sollte man genau aufpassen, was man macht. Negativbeispiel:


void CheckList(List<MyClass> list)
{
int len = list.Count;

for (int i = 0; i < len; i++)
{
if (IsBadObject(list[i]) == true)
{
list.RemoveAt(i);
i--;
}
}
}



Kommentar abgeben

Titel:
Name:
Email:
(wird nicht angezeigt!)
Homepage:
Feedback:
Please add 5 and 5 and type the answer here: