Out of interest, I tested if there was any difference to a for loop and a while loop doing the same thing. What causes the while loop to take about 2-2.5 seconds longer on my computer (AMD Phenom II X6 1090T @ 3.20GHz) than the for loop? Aren’t they doing the same thing? Do you get similar results?
Also, when I replace the x = null; statement from the loops with just an empty statement, the while loop will be significantly faster. What’s going on here?
Sure, the number of iterations is pretty high, but isn’t the difference still pretty significant?
static void Main(string[] args)
{
String x;
const Int64 FIVE_BN = 5000000000;
Int64 i = 0;
DateTime start = DateTime.Now;
for (; FIVE_BN > i; i++)
x = null; //Replace with only ; in both loops and the for loop is faster
Console.Out.WriteLine(FIVE_BN.ToString() + " times (for): " + (DateTime.Now - start));
i = 0;
start = DateTime.Now;
while(FIVE_BN > i++)
x = null; //Replace with only ; in both loops and the for loop is faster
Console.Out.WriteLine(FIVE_BN.ToString() + " times (while): " + (DateTime.Now - start));
Console.Read();
return;
}
While this is entirely a micro optimization that would never be the performance bottleneck. It interesting that the two are actually different, interestingly when you extract methods both the loops with VS2010 I get the following:
And that is quite interesting… it shows that the two functions are indeed different.
now when we replace the logic in the loop with
;we get the following extracted methods instead:Which indicates why the loops run basically the same with this configuration.
To work out how they’re different when inline (and not extracted into methods) we need to see what the optimized CLR coded looks like (though the optimizer might actually remove any significant differences between the two functions).. That’s something for a later edit.
Edit:
The CIL reveals the differences:
The For loop has
.maxstack 2but the while loop has.maxstack 4, otherwise there’s a little diference in the order of operations due to the fact that the increment for thewhilehappens at the start of the loop but theforoperation happens at the end of the loop (change the content of the loop toConsole.WriteLine(i)and see that the While loop will print from 1 but the For loop will print from 0 (both do the same number of loop iterations though).When the loop contents is just a
;both loops are 2 lines shorter in CIL with the following lines removed (for both loops):However when we build in release the code is very different:
The difference between
x = null;and;is nothing, for either of the loops, as the optimizer has noticed that the value never changes to being not-null.The difference between the optimised for and while loops are as follows:
CIL
forloop:And CIL
whileloop:So we can see that an optimised while loop is faster than a for loop by 2 operations, however it uses more stack space.
The difference between these two seems entirely related to the difference in where the
i++occurs.Indeed this is confirmed by making a new method:
The CIL code for this
formethod when built (in either release or debug) is identical to that of thewhileloop.There in lies your difference. For loops perform exactly the same as while loops when they’re doing the exact same behaviour. The difference you noted is entirely due to running the code in debug and not release, combined with the JIT not always being as efficient as the release code optimizer.
I have enjoyed this question, I learnt something out of it; I hope others do as well. +1