11
votes

A followup to Does .NET JIT optimize empty loops away?:

The following program just runs an empty loop a billion times and prints out the time to run. It takes 700 ms on my machine, and I'm curious if there's a way to get the jitter to optimize away the empty loop.

using System;

namespace ConsoleApplication1 {
    class Program {
        static void Main() {
            var start = DateTime.Now;
            for (var i = 0; i < 1000000000; i++) {}
            Console.WriteLine((DateTime.Now - start).TotalMilliseconds);
        }
    }
}

As far as I can tell the answer is no, but I don't know if there are hidden compiler options I might not have tried. I have made sure to compile in release mode and run with no debugger attached, but still 700 ms is being taken to run this empty loop. I also tried NGEN with the same result (though my understanding is that it should produce the same compiled code as the JIT anyway, right?). However I've never used NGEN before and may be using it wrong.

It seems like this would be something easy for the JIT to find and optimize away, but knowing very little about how jitters work in general, I'm curious if there's a specific reason this optimization would have been left out. Also the VC++ compiler definitely does seem to make this optimization, so I wonder why the discrepancy. Any ideas?

1
Why is this an issue for you in reality? If you've got an empty loop, just get rid of it.Jon Skeet
How is this different than the question you're referencing?Reed Copsey
It isn't an empty loop. It's incrementing i one billion times.Bryan Walker
@Dax: that article is bad. The code snippets don't do the same thing (hint: order of operations on floating-point numbers matters). You can't say if apples are faster than oranges.R. Martinho Fernandes
One admittedly unusual use-case for this optimization would be loops that contain only Debug code and therefore are empty in a Release build. That said, it would be odd to have Debug code executing a very large number of times, so any performance impact would be pretty minimal. You can also manually create this optimization by putting the loop in a method and annotating the method so that it only gets called in a Debug build.Dan Bryant

1 Answers

8
votes

No, none of the .NET jitters I know eliminate empty for loops. The exact reason why isn't that clear to me, the jitter optimizer certainly knows how to make optimizations like that and readily eliminates dead code. Check this answer for details. I believe this was intentional, leaving the loop in place for its possibly intended side-effect, consuming time. Which of course only makes sense for very short loops to implement a spinwait.