Environment.TickCount vs DateTime.Now

Environment.TickCount is based on GetTickCount() WinAPI function. It’s in milliseconds
But the actual precision of it is about 15.6 ms. So you can’t measure shorter time intervals (or you’ll get 0)

Note: The returned value is Int32, so this counter rolls over each ~49.7 days. You shouldn’t use it to measure such long intervals.

DateTime.Ticks is based on GetSystemTimeAsFileTime() WinAPI function. It’s in 100s nanoseconds (tenths of microsoconds).
The actual precision of DateTime.Ticks depends on the system. On XP, the increment of system clock is about 15.6 ms, the same as in Environment.TickCount.
On Windows 7 its precision is 1 ms (while Environemnt.TickCount’s is still 15.6 ms), however if a power saving scheme is used (usually on laptops) it can go down to 15.6 ms as well.

Stopwatch is based on QueryPerformanceCounter() WinAPI function (but if high-resolution performance counter is not supported by your system, DateTime.Ticks is used)

Before using StopWatch notice two problems:

  • it can be unreliable on multiprocessor systems (see MS kb895980, kb896256)
  • it can be unreliable if CPU frequency varies (read this article)

You can evaluate the precision on your system with simple test:

static void Main(string[] args)
{
    int xcnt = 0;
    long xdelta, xstart;
    xstart = DateTime.UtcNow.Ticks;
    do {
        xdelta = DateTime.UtcNow.Ticks - xstart;
        xcnt++;
    } while (xdelta == 0);

    Console.WriteLine("DateTime:\t{0} ms, in {1} cycles", xdelta / (10000.0), xcnt);

    int ycnt = 0, ystart;
    long ydelta;
    ystart = Environment.TickCount;
    do {
        ydelta = Environment.TickCount - ystart;
        ycnt++;
    } while (ydelta == 0);

    Console.WriteLine("Environment:\t{0} ms, in {1} cycles ", ydelta, ycnt);


    Stopwatch sw = new Stopwatch();
    int zcnt = 0;
    long zstart, zdelta;

    sw.Start();
    zstart = sw.ElapsedTicks; // This minimizes the difference (opposed to just using 0)
    do {
        zdelta = sw.ElapsedTicks - zstart;
        zcnt++;
    } while (zdelta == 0);
    sw.Stop();

    Console.WriteLine("StopWatch:\t{0} ms, in {1} cycles", (zdelta * 1000.0) / Stopwatch.Frequency, zcnt);
    Console.ReadKey();
}

Leave a Comment