Skip to content

Make DateTIme.Now as efficient as DateTime.UtcNow #24277

@custarddog

Description

@custarddog

@vancem commented on Tue Sep 05 2017

I thought we fixed this but I just checked and we have not, so I am logging an issue.

DateTime.Now is over 10X SLOWER than DateTime.UtcNow.
I ran the the trivial program below

            var start = DateTime.Now;
            while ((DateTime.Now-start).TotalSeconds < 5)
            {

            }

while profiling with PerfView to get the following data

Name Inc % Inc
||    |+ system.private.corelib!System.DateTime.get_Now() 95.4 4,832
||    | + system.private.corelib!TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc 88.1 4,462
||    | + system.private.corelib!System.DateTime.get_UtcNow() 5.8 293

which show that only 6% of time is spent actually fetching the time, and 95% of the time was figuring out what time zone we are in.

This mapping from Utc time to local time could be cached and all the inefficiency removed.

This is important because people DO use DateTIme.Now to measure the durations of fast things (in fact we improved DateTime.UtcNow so that it has a accuracy of < 1msec). Currently we tell people to avoid DateTime.Now (use DateTime.UtcNow), to avoid this inefficiency, but we could easily make DateTIme.Now almost the same cost

This is only a small amount of work, we should just do it.

@danmosemsft , @karelz


@mikedn commented on Tue Sep 05 2017

Currently we tell people to avoid DateTime.Now (use DateTime.UtcNow), to avoid this inefficiency

I don't know about others but I avoid DateTime.Now not because it's inefficient but because it is plain wrong to use it to measure durations. Or more generally, to use it for anything that doesn't involve displaying the local time to the user...

Let's keep DateTime.Now slow to encourage devs to do the right thing 😁


@karelz commented on Tue Sep 05 2017

Marking as up-for-grabs.
Moderate cost (as it requires perf measurements before and after the change)


@danmosemsft commented on Tue Sep 05 2017

mapping from Utc time to local time could be cached

Of course, daylight savings could begin one second from now so it presumably can't be trivially cached. @tarekgh is there a way that DateTime can be told when the local time offset changes, instead of asking each call? I'm sure there has been thinking about this in the past.


@tarekgh commented on Tue Sep 05 2017

is there a way that DateTime can be told when the local time offset changes

No, we don't have a way to know that. We looked before, and the way you can know that (on Windows) is either you have a Window and listen to some window message or you use WinRT API. Obviously, both are not a good solution for us.

Also, it is difficult to know if we are passing the daylight saving at any moment to know we need to adjust the calculation (or the cache).

We already have some optimization here:
http://source.dot.net/#System.Private.CoreLib/src/System/TimeZoneInfo.Win32.cs,50

but we still doing the calculations here:
http://source.dot.net/#System.Private.CoreLib/src/System/TimeZoneInfo.Win32.cs,402

because of we cannot know if we crossed the daylight or not.

by the way, the optimization we have there has a bug. that can tell when trying to optimize, you can run into some other problems.


@vancem commented on Tue Sep 05 2017

On the caching issue: It seems to me that when you calculate daylight savings time, you can also know when it will change (at worst you probe say 4 hours into the future and see if it is different, since you know that daylight savings time only happens 2 a year, if you get the same number for now and 4 hours from now, you can know that for the next 4 hours it will not change). The next time you want Now you can then just check if the time is in the 'known' region and if so use the cached DST value.

@mikedn - yes, arguably DateTime.Now is bad for computing deltas (since any time you cross DST, you get a weird value). However giving bad perf does not actually change behavior, it just makes their code that much worse. There are also correct usages (when you just want a timestamp). The bottom line is that if people use it at all frequently (and we have evidence that they do), it is worth optimizing.


@tarekgh commented on Tue Sep 05 2017

@vancem yes, in general, I agree there is a way we can optimize. we just want to be careful to not affect the functionality and not have a complex solution.

To mention, instead of probing for some time (4 hours in your example) we can just calculate the exact time we are going to switch the daylight when we create the cache. and then we always check against this time to know if we need to update the cache or just use the cached offset.


@danmosemsft commented on Tue Sep 05 2017

If the machine time zone changes, do we need to listen to that?


@tarekgh commented on Tue Sep 05 2017

If the machine time zone changes, do we need to listen to that?

Same answer:

No, we don't have a way to know that. We looked before, and the way you can know that (on Windows) is either you have a Window and listen to some window message or you use WinRT API. Obviously, both are not a good solution for us.

Today we ask the apps to listen to the TZ changes on the machine and then call us to clear the cache.


@danmosemsft commented on Wed Nov 29 2017

Moving to CoreFX to track more easily.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-System.DateTimeenhancementProduct code improvement that does NOT require public API changes/additionshelp wanted[up-for-grabs] Good issue for external contributorstenet-performancePerformance related issue

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions