← Back to articles

Comparison of Environment.TickCount, DateTime.Now.Ticks and Stopwatch.ElapsedMilliseconds

Game loops check timers constantly, so how cheap is reading time? Environment.TickCount: 7ms for a million reads. DateTime.Now.Ticks: 1392ms. The numbers, and when each is the right choice.

Tedd

Doing game development I use a lot of timers. Every Update() I check if its time to do something. To make this as light as possible I made a small benchmark to check the speed of different ways of getting time.

When running the code ignore the first 1000-result from each test (used for warmup). Also ignore the number printed after “ignore:”, its just there just to ensure no compiler optimization is done that would affect the result.

Results on my computer:

Test1 1000000: 7ms - Environment.TickCount
Test2 1000000: 1392ms - DateTime.Now.Ticks
Test3 1000000: 933ms - Stopwatch.ElapsedMilliseconds

Both DateTime.Now.Ticks (test 2) and Stopwatch.ElapsedMilliseconds (test 3) are considerably slower than Environment.TickCount (test 1), but not enough to be noticeable unless you are performing a lot of calculations. For example I was investigating this because I need a cheap way of getting time in tight game loops. The thing to note is that Environment.TickCount is 32-bit signed which means that after 2147483 seconds of uptime (24,85513 days) the counter overflows and goes to –2147483648 (minus 24,85513 days).

Tip! You can force an overflow to 0 after a max value of 49 days by converting it to an unsigned integer: var value = unchecked((UInt32)Environment.TickCount)

Benchmark code:

static void Main(string[] args)
{
 Test1(1000);
 Test1(1000000);
 Test2(1000);
 Test2(1000000);
 Test3(1000);
 Test3(1000000);

 Console.ReadLine();
}

 

static void Test1(int c)
{
 var sw = new Stopwatch();
 sw.Start();
 long sum = 0;
 for (var i = 0; i < c; i++)
 {
 sum += Environment.TickCount;
 }
 sw.Stop();
 Console.WriteLine("Test1 " + c + ": " + sw.ElapsedMilliseconds + " (ignore: " + sum + ")");
}

static void Test2(int c)
{
 var sw = new Stopwatch();
 sw.Start();
 long sum = 0;
 for (var i = 0; i < c; i++)
 {
 sum += DateTime.Now.Ticks;
 }
 sw.Stop();
 Console.WriteLine("Test2 " + c + ": " + sw.ElapsedMilliseconds + " (ignore: " + sum + ")");
}
static void Test3(int c)
{
 var sw = new Stopwatch();
 sw.Start();
 long sum = 0;
 var stopwatch = new Stopwatch();
 stopwatch.Start();
 for (var i = 0; i < c; i++)
 {
 sum += stopwatch.ElapsedMilliseconds;
 }
 sw.Stop();
 Console.WriteLine("Test3 " + c + ": " + sw.ElapsedMilliseconds + " (ignore: " + sum + ")");
} 

Written by Tedd · Oslo, Norway

Updated 5 Jan 2017

Follow the journal via RSS