Optimizing alternatives to DateTime.Now
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.UtcNow
is 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.
Related videos on Youtube
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, 2020Comments
-
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:- 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).
- 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.
- 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 viaFastDateTime.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:
- 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? - Can anyone else perhaps think of an even faster way of getting the current time?
-
PaulMcG over 14 yearsThe 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 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 about 14 yearsI'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 almost 13 yearsIt's the presentation that's important: there is no single local time so it can only be calculated when presented.
-
Esben von Buchwald about 4 yearsI 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