Optimizing alternatives to DateTime.Now

10,471

Solution 1

Could you just use DateTime.UtcNow, and only convert to local time when the data is presented? You've already determined that DateTime.UtcNow is much faster and it will remove any ambiguity around DST.

Solution 2

One difference between the result of

DateTime.Now

and

DateTime.UtcNow + LocalUtcOffset 

is the value of the Kind property - Local vs Utc respectively. If the resultant DateTime is being passed to a third party library consider returning

DateTime.SpecifyKind(DateTime.UtcNow + LocalUtcOffset, DateTimeKind.Local)

Solution 3

I like your solution. I made some tests to see how much faster it is compared to regular DateTime.Now

DateTime.UtcNow is 117 times faster than DateTime.Now

using DateTime.UtcNow is good enough if we are only interested in the duration and not the time itself. If all we need is to calculate the duration of a specific code section ( doing duration= End_time - Start_time ) then the time zone is not important and DateTime.UtcNow is sufficient.

But if we need the time itself then we need to do DateTime.UtcNow + LocalUtcOffset

Just adding the time span slows down a little bit and now according to my tests we are just 49 times faster than the regular DateTime.Now

If we put this calculation in a separate function/class as suggested then calling the method slows us down even more and we are only 34 times faster.

But even 34 times faster is a lot !!!

In short, Using DateTime.UtcNowis much faster than DateTime.Now

The only way I found to improve the suggested class is to use inline code: DateTime.UtcNow + LocalUtcOffset instead of calling the class method

BTW trying to force the compiler to compile as inline by using [MethodImpl(MethodImplOptions.AggressiveInlining)] didnt seem to speed things up.

Solution 4

To answer in reverse order:

2) I cannot think of a faster way.

1) It would be worth checking if there are any framework improvements in the pipeline like they have just announced for System.IO

It's hard to be sure about safety but it's something that is crying out for a lot of unit tests. Daylight savings comes to mind. The System one is obviously very battle hardened while yours is not.

Share:
10,471

Related videos on Youtube

Dan Tao
Author by

Dan Tao

Author of the blog The Philosopher Developer and the open source libraries lazy.js and nearest-color (among others), and cohost of the podcast Spaceflix. GitHub: dtao Twitter: @dan_tao SoundCloud: dantao I’m the Head of Engineering for Bitbucket Cloud. Previously I've worked at Google, Cardpool, and ThoughtWorks.

Updated on October 17, 2020

Comments

  • Dan Tao
    Dan Tao over 3 years

    A colleague and I are going back and forth on this issue and I'm hoping to get some outside opinions as to whether or not my proposed solution is a good idea.

    First, a disclaimer: I realize that the notion of "optimizing DateTime.Now" sounds crazy to some of you. I have a couple of pre-emptive defenses:

    1. I sometimes suspect that those people who always say, "Computers are fast; readability always comes before optimization" are often speaking from experience developing applications where performance, though it may be important, is not critical. I'm talking about needing things to happen as close to instantaneously as possible -- like, within nanoseconds (in certain industries, this does matter -- for instance, real-time high-frequency trading).
    2. Even with that in mind, the alternative approach I describe below is, in fact, quite readable. It is not a bizarre hack, just a simple method that works reliably and fast.
    3. We have runs tests. DateTime.Now is slow (relatively speaking). The method below is faster.

    Now, onto the question itself.

    Basically, from tests, we've found that DateTime.Now takes roughly 25 ticks (around 2.5 microseconds) to run. This is averaged out over thousands to millions of calls, of course. It appears that the first call actually takes a significant amount of time and subsequent calls are much faster. But still, 25 ticks is the average.

    However, my colleague and I noticed that DateTime.UtcNow takes substantially less time to run -- on average, a mere 0.03 microseconds.

    Given that our application will never be running while there is a change in Daylight Savings Time, my suggestion was to create the following class:

    public static class FastDateTime {
        public static TimeSpan LocalUtcOffset { get; private set; }
    
        public static DateTime Now {
            get { return DateTime.UtcNow + LocalUtcOffset; }
        }
    
        static FastDateTime() {
            LocalUtcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
        }
    }
    

    In other words, determine the UTC offset for the local timezone once -- at startup -- and from that point onward leverage the speed of DateTime.UtcNow to get the current time a lot faster via FastDateTime.Now.

    I could see this being a problem if the UTC offset changed during the time the application was running (if, for example, the application was running overnight); but as I stated already, in our case, that will not happen.

    My colleague has a different idea about how to do it, which is a bit too involved for me to explain here. Ultimately, as far as I can tell, both of our approaches return an accurate result, mine being slightly faster (~0.07 microseconds vs. ~0.21 microseconds).

    What I want to know is:

    1. Am I missing something here? Given the abovementioned fact that the application will only run within the time frame of a single date, is FastDateTime.Now safe?
    2. Can anyone else perhaps think of an even faster way of getting the current time?
    • PaulMcG
      PaulMcG over 14 years
      The DST transition is the usual oversight when making these kind of simplifications, and you have already stipulated that this wont be an issue. It catches people off guard to discover that they (and their application software) live in 2 timezones, without moving an inch. And it is doubly tricky that the only time that your test suite catches this is if it happens to run during the DST transition, a rare occurrence at best (or is mocked up as part of the test suite, which I would assert is an even rarer thing).
  • kenny
    kenny over 14 years
    +1 I read that UtcNow is a lot faster, which was surprising to me. blogs.msdn.com/clrperfblog/archive/2009/09/08/…
  • Dan Tao
    Dan Tao about 14 years
    I'm going to go ahead and just accept this answer because it makes so much darned sense. Unfortunately I don't think we'll be doing this (at least not yet) because of the amount of code we'd have to change. But it's an incredibly logical suggestion.
  • Steve Dunn
    Steve Dunn almost 13 years
    It's the presentation that's important: there is no single local time so it can only be calculated when presented.
  • Esben von Buchwald
    Esben von Buchwald about 4 years
    I ran some benchmarks with .net 4.8 and today UtcNow is "only" 6.4x slower than Now. Also! For fun I tested Stopwatch.ElapsedTicks (19x faster) and Stopwatch.GetTimeStamp() (22x faster). :D