Wenn ich eine leere for-Schleife mit einer großen Anzahl von Iterationen durchführe, bekomme ich sehr unterschiedliche Zahlen, wie lange es dauert, um zu laufen:
%Vor%Das obige wird in etwa 200ms auf meinem Rechner laufen, aber wenn ich es auf 1000000001 erhöhe, dauert es 4x so lange! Dann, wenn ich es 1000000002 mache, dann ist es wieder auf 200ms!
Dieses scheint für eine gerade Anzahl von Iterationen zu passieren. Wenn ich for (var i = 1; i < 1000000001
beginne (Note beginnend bei 1 statt 0), dann sind es 200ms. Oder wenn ich i <= 1000000001
(Note weniger als oder gleich ) mache, dann sind es 200ms. Oder (var i = 0; i < 2000000000; i += 2)
ebenfalls.
Dies scheint nur auf x64 zu sein, aber auf allen .NET-Versionen bis (mindestens) 4.0. Auch erscheint es nur im Freigabemodus mit Debugger gelöst.
UPDATE Ich dachte, dass dies wahrscheinlich auf eine clevere Bitverschiebung im Jit zurückzuführen ist, aber das Folgende scheint das zu widerlegen: Wenn Sie etwas wie ein Objekt innerhalb dieser Schleife erstellen, dann < em> das dauert etwa viermal so lang:
%Vor%Dies dauert etwa 1 Sekunde auf meinem Computer, aber dann erhöht sich um 1 auf 1000000001 4 Sekunden . Das sind zusätzliche 3000ms, also könnte es nicht wirklich auf Bit-Shifting zurückzuführen sein, da dies auch beim ursprünglichen Problem einen Unterschied von 3000ms ergeben hätte.
Nun, hier sind die Demontagen:
%Vor%Und
%Vor% Der einzige Unterschied, den ich sehe, ist, dass in der geraden Schleife der Schleifenindex jeweils um 4 erhöht wird ( add eax 4
) anstatt 1 gleichzeitig ( inc eax
), so dass die Schleife 4x schneller beendet wird das.
Dies ist nur Spekulation, aber ich glaube, es ist die Schleife um einen Faktor von 4 abzurollen. So platziert es den Körper 4 mal innerhalb der Schleife und nur 4 mal schneller erhöht. Aber da der Körper leer ist, ist der leere Körper mal 4 noch leer, du gewinnst viel mehr Gewinn, als du vom Schleifenabwickeln erwarten würdest.
Tags und Links .net c# performance