The DateTime.Now
gets updates around 10 times per second but don't quote me on this (could be depending on hardware and software setting). It's also slow because it needs to figure out what timezone the system is on. UtcNow
is faster but will still be cached for a bit. Therefore, it could be using the cached version on subsequent calls.
Use StopWatch
instead for more accurate measurement. StopWatch
uses high precision by utilizing hardware. You can check that using Stopwatch.IsHighResolution
.
using System.Diagnostics;
Stopwatch sw = new Stopwatch();
sw.Start();
// code to benchmark
sw.Stop();
Let's see if you get same metrics.
EDIT
While it is true that your method needs to be JIT compiled, the difference cannot be due to JIT compilation because it will be JIT compiled only once (not always but in your case it will be once) and then reused. Therefore, only the first call should take longer and the subsequent calls should be the same. To throw this assumption away, simply call Compress
once outside the benchmarking phase so it is JIT compiled. Then benchmark it, and now the JIT compilation will not occur, and DateTime
will still give you random results because it is cached.
Note: The JIT compiler does not necessarily always compile the whole method into machine code but only when execution passes through the code. So if you have if statements, the blocks may not be compiled until execution is passed through the block. But yours have no if statements so that is why it will be JIT compiled once.
Furthermore, we cannot say with confidence this was due to JIT compilation since it is possible Compress
method could have been inlined but in your case it was most likely not inlined since you most likely had the debugger on and therefore, JIT optimization will be disabled.
Try this code and you will notice it gives random results for elapsed time even though the same code is executed:
for (int i = 0; i < 1000; i++)
{
DateTime beginTime = DateTime.UtcNow;
var sw = Stopwatch.StartNew();
while (sw.ElapsedTicks < 100)
{
Console.WriteLine("*");
}
long elapsedTicks = DateTime.UtcNow.Ticks - beginTime.Ticks;
Console.WriteLine(" {0:N0} nanoseconds", elapsedTicks * 100);
}
On my system if I change this line to sw.ElapsedTicks < 2050
, then there is always is a difference of non zero reported consistently. Which means right around there is when DateTime.Now
gets a new value instead of using the cached one.
In conclusion, I do not buy that JIT compilation is the explanation for what you are noticing.