Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

The Darkness Behind DateTime.Now

DZone's Guide to

The Darkness Behind DateTime.Now

·
Free Resource

A short while ago David Penton and Peter Bromberg had a conversation on Twitter about performance differences between using DateTime.Now and DateTime.UtcNow properties and the best practices related to them. I jumped in their discussion with my thoughts and Peter did a nice job by putting a summary on EggHeadCafe. While that summary suffices for many developers to understand the problems associated with wrong usage of DateTime.Now (which is very commonplace), I thought that it may be a good idea to dedicate a blog post to this topic with more details for two reasons: first, we need to repeat certain stuff to spread the word about a good or bad practice and inform developers about it, and second, it may be worth seeing the reasons, numbers, and performance measurements for everyone to understand the points.

In this post I’m going to discuss the applications of two properties of DateTime structure, Now and UtcNow, as well as Stopwatch class, and provide a set of measurements of performance impacts associated with each one.

DateTime.Now

A very commonly-used and well-known property of the DateTime structure in .NET is Now which simply returns the current date and time on the machine executing the code. Such a property is provided in almost all programming languages as a built-in feature and has many applications. Unfortunately, most of the .NET developers have been misusing this property for years for purposes other than what it’s supposed to serve for. I can outline two possible reasons for this problem:

  • Most of the developers are careless about all the properties and methods provided by built-in types in a language, so they don’t discover all the details about them. In fact, they use something that just solves their problem regardless of the side-effects.
  • The traditional use of similar methods in languages used by .NET developers in the past has left some bad habits for them while the internal working of this property is slightly different from what is available in some other languages.

I have to admit that I was a developer who used to apply this property for wrong purposes in the early years of my .NET development, and may still misuse that for simple codes where I don’t care much about performance, but it’s not something to use in each and every situation.

To clarify the use of the Now property of DateTime structure I have to state that this property is not designed to be used in cases such as when you want to retrieve the time for internal calculations in your program, store a DateTime value in database, or calculate the runtime performance of a piece of code. In contrast, it is designed to be used when you want to display the current date and time on a machine to your users or store such a value in local log files where you want the local time to be used.

Although it’s hard to give a general guideline on good and bad uses of this property, I guess that the abovementioned examples can give you enough hints on when and where to use this property. A good question that you may ask about this property is why we distinguish these cases and consider some uses as bad practices. The answer is laid in the internal implementation of the Now property.

public static DateTime Now
{
	get
	{
		DateTime utcNow = DateTime.UtcNow;
		bool isAmbiguousDst = false;
		long ticks = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utcNow, out isAmbiguousDst).Ticks;
		long num = utcNow.Ticks + ticks;
		if (num > 3155378975999999999L)
		{
			return new DateTime(3155378975999999999L, DateTimeKind.Local);
		}
		if (num < 0L)
		{
			return new DateTime(0L, DateTimeKind.Local);
		}
		return new DateTime(num, DateTimeKind.Local, isAmbiguousDst);
	}
}

Essentially, this property is converting the current date and time in UTC to the local values and has an extra processing associated with this which is the source of the overhead that I will discuss later.

DateTime.UtcNow

Another commonly-used property of DateTime is UtcNow even though it’s not used as commonly as the Now property. This property returns the current date and time in UTC. This property is designed to serve for many places where Now is being misused and I listed some of the highlights in the previous section.

In general, if you’re going to store DateTime values in database or perform calculations on such values, it’s better to use UtcNow because in the former case, this helps you have a universal value regardless of the local time of the machine where you host your program and in the latter case there is no difference between the duration of time calculated by Now and UtcNow.

As you can see below, UtcNow has a simpler implementation than Now and in fact, Now is written based on UtcNow with some additions.

public static DateTime UtcNow
{
	[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), SecuritySafeCritical]
	get
	{
		long systemTimeAsFileTime = DateTime.GetSystemTimeAsFileTime();
		return new DateTime((ulong)(systemTimeAsFileTime + 504911232000000000L | 4611686018427387904L));
	}
}

Stopwatch

A lesser-used aspect of DateTime calculations in .NET is Stopwatch type that is designed to assist programmers to calculate the runtime performance of a piece of code. Most programmers tend to use DateTime.Now and DateTime.UtcNow before and after a piece of code to find the duration of time that it takes to execute.

Stopwatch relies on a public static method called GetTimeStamp which works in two modes. If it’s not used in high resolution mode, it applies DateTime.UtcNow, otherwise it applies QueryPerformanceCounter from Windows API that I will discuss in the next section.

public static long GetTimestamp()
{
	if (Stopwatch.IsHighResolution)
	{
		long result = 0L;
		SafeNativeMethods.QueryPerformanceCounter(out result);
		return result;
	}
	return DateTime.UtcNow.Ticks;
}

QueryPerformanceCounter

While this is something that a .NET developer doesn’t need to use and care about, I have to point out that QueryPerformanceCounter is a Windows API method that is used by some built-in .NET types behind the scenes. This is considered an outdated approach in .NET development and you need to use interoperability APIs to have access to this function which provides access to a high-resolution performance counter.

[DllImport("Kernel32.dll")]
public static extern void QueryPerformanceCounter(ref long ticks);

In the next section I apply this method to compute the time taken to execute my benchmarks and the main reason is that I want to have a higher precision, so using a more fundamental operating system function can help.

Comparison

Nothing is better than seeing some numbers reflecting the points mentioned above, so here I try to write simple programs that compare the performance of DateTime.Now, DateTime.UtcNow, and Stopwatch. Normally, it’s hard to compare the properties of DateTime structure with Stopwatch as they are different by nature, however, thinking a little bit about good examples, it’s possible to relate them together and compare their runtime performance.

Here I develop three pieces of code that accomplish the same goal using these three approaches. I generate different sample sizes (incremented by a unit of 500 for 10 sample data batches) and perform a very basic (and senseless) task. I use DateTime.Now, DateTime.UtcNow, and Stopwatch to calculate the time that it takes to run my code. I measure my elapsed time using QueryPerformanceCounter to have a good precision.

The first code is for DateTime.Now.

private static void TestDateTimeNow()
{
    Console.WriteLine("Testing DateTime.Now ...");

    for (int sampleSize = 500; sampleSize <= 5000; sampleSize += 500)
    {
        long start = 0;
        QueryPerformanceCounter(ref start);

        for (int counter = 0; counter < sampleSize; counter++)
        {
            DateTime startTime = DateTime.Now;

                int dumbSum = 0;
                for (int temp = 0; temp < 5; temp++)
                    dumbSum++;

            DateTime endTime = DateTime.Now;

            TimeSpan duration = endTime - startTime;
        }

        long end = 0;
        QueryPerformanceCounter(ref end);
		
        long time = 0;
        time = end - start;

        Console.WriteLine("Sample Size: {0} - Time: {1}", sampleSize, time);
    }
}

A very similar code can be used with DateTime.UtcNow.

private static void TestDateTimeNow()
{
    Console.WriteLine("Testing DateTime.UtcNow ...");

    for (int sampleSize = 500; sampleSize <= 5000; sampleSize += 500)
    {
        long start = 0;
        QueryPerformanceCounter(ref start);

        for (int counter = 0; counter < sampleSize; counter++)
        {
            DateTime startTime = DateTime.UtcNow;

                int dumbSum = 0;
                for (int temp = 0; temp < 5; temp++)
                    dumbSum++;

            DateTime endTime = DateTime.UtcNow;

            TimeSpan duration = endTime - startTime;
        }

        long end = 0;
        QueryPerformanceCounter(ref end);
		
        long time = 0;
        time = end - start;

        Console.WriteLine("Sample Size: {0} - Time: {1}", sampleSize, time);
    }
}

And finally, Stopwatch can be applied to measure the duration of time to execute this code using its Start and Stop methods as well as its Elapsed property.

private static void TestStopwatch()
{
    Console.WriteLine("Testing Stopwatch ...");

    for (int sampleSize = 500; sampleSize <= 5000; sampleSize += 500)
    {
        long start = 0;
        QueryPerformanceCounter(ref start);

        for (int counter = 0; counter < sampleSize; counter++)
        {
            Stopwatch watch = new Stopwatch();

            watch.Start();

            int dumbSum = 0;
            for (int temp = 0; temp < 5; temp++)
                dumbSum++;

            watch.Stop();

            TimeSpan duration = watch.Elapsed;
        }

        long end = 0;
        QueryPerformanceCounter(ref end);

        long time = 0;
        time = end - start;

        Console.WriteLine("Sample Size: {0} - Time: {1}", sampleSize, time);
    }
}

Sometimes a picture is worth a thousand words and the below diagram can reflect whatever I’ve mentioned so far.

Quantitative comparison between DateTime.Now, DateTime.UtcNow, and StopWatch in .NET

Here we see some interesting results and it’s more interesting when we consider the fact that these codes are tested with realistic sample data sizes between 500 to 5000. Here DateTime.Now (the blue line) has the worst performance at top followed by Stopwatch (the green line) and DateTime.UtcNow (the red line). UtcNow stands much lower than the other options with a very steady pace (unlike other two options) and surprisingly, performs better than Stopwatch. This is of course expected as I showed you the internal implementation of Stopwatch which is using DateTime.UtcNow with some extra processing.

Here a good question is why we need to use Stopwatch when DateTime.UtcNow is performing better. The answer is that it’s possible to do that and actually, it’s much better if you’re sure that you get such a significant difference by applying UtcNow rather than Stopwatch. But there is a major and a minor advantage for Stopwatch over UtcNow. The major advantage is that Stopwatch can perform in a higher resolution by applying QueryPerformanceCounter rather than DateTime.UtcNow. The minor advantage is that Stopwatch provides a more fluent and human-readable method to perform this task.

Summary

Many .NET developers misuse the properties of DateTime structure and apply Now for purposes where it’s not designed for which reduces the performance of the code. UtcNow is what should be used for many cases rather than Now, and even for timing measurements there is a particular class called Stopwatch.

Seeing a quantitative comparison between these approaches visualized in a simple diagram, you can understand why it’s recommended to use each property or type in its own place. I am very sure that the misuse of these options in the .NET codes written in the past decade has had a major impact on many .NET applications and it’s sad to say this because despite a decade of existence and six major releases of the .NET Framework with a lot of investments in training and documentation, there hasn’t been a good focus on the underlying infrastructure of the framework and such important practices.

I’ve uploaded the sample code for this post that you can run on your machine to compare these three approaches yourself.

Topics:

Published at DZone with permission of Keyvan Nayyeri. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}