简体   繁体   English

优化DateTime.Now的替代方案

[英]Optimizing alternatives to DateTime.Now

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. 首先,免责声明:我意识到“优化DateTime.Now ”的概念对你们中的某些人来说听起来很疯狂。 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). DateTime.Now 慢(相对而言)。 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. 基本上,通过测试,我们发现DateTime.Now大约需要25个刻度(大约2.5微秒)才能运行。 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. 但仍然是25个蜱是平均值。

However, my colleague and I noticed that DateTime.UtcNow takes substantially less time to run -- on average, a mere 0.03 microseconds. 然而,我的同事和我注意到DateTime.UtcNow运行的时间要少得多 - 平均只有0.03微秒。

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 . 换句话说,确定UTC本地时区偏移一次 -在启动-并从该点开始利用速度DateTime.UtcNow通过获取当前的时间快了很多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); 如果在应用程序运行期间UTC偏移发生了变化(例如,如果应用程序在一夜之间运行),我可以看到这是一个问题; 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). 最终, 据我所知 ,我们的两种方法都返回了准确的结果,我的方法稍快一些(约0.07微秒与~0.21微秒)。

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? 鉴于上述事实,应用程序只能在一个日期的时间范围内运行, FastDateTime.Now安全?
  2. Can anyone else perhaps think of an even faster way of getting the current time? 任何人都可以想到更快获得当前时间的方法吗?

Could you just use DateTime.UtcNow, and only convert to local time when the data is presented? 你能使用DateTime.UtcNow,只在数据出现时转换为本地时间吗? You've already determined that DateTime.UtcNow is much faster and it will remove any ambiguity around DST. 您已经确定DateTime.UtcNow更快,它将消除DST周围的任何歧义。

One difference between the result of 结果之一的一个区别

DateTime.Now

and

DateTime.UtcNow + LocalUtcOffset 

is the value of the Kind property - Local vs Utc respectively. 是Kind属性的值 - Local vs Utc。 If the resultant DateTime is being passed to a third party library consider returning 如果将生成的DateTime传递给第三方库,请考虑返回

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

I like your solution. 我喜欢你的解决方案。 I made some tests to see how much faster it is compared to regular DateTime.Now 我做了一些测试,看看它与常规DateTime.Now相比有多快

DateTime.UtcNow is 117 times faster than DateTime.Now DateTime.UtcNowDateTime.Now快117倍

using DateTime.UtcNow is good enough if we are only interested in the duration and not the time itself. 如果我们只关注持续时间而不是时间本身,那么使用DateTime.UtcNow就足够了。 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. 如果我们只需要计算特定代码段的duration= End_time - Start_time (执行duration= End_time - Start_time ),那么时区并不重要,而DateTime.UtcNow就足够了。

But if we need the time itself then we need to do DateTime.UtcNow + LocalUtcOffset 但是如果我们需要时间本身,那么我们需要做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 只是添加时间跨度减慢了一点点,现在根据我的测试,我们只比常规DateTime.Now快49倍。现在

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. 如果我们按照建议将这个计算放在一个单独的函数/类中,那么调用该方法会使我们更慢,我们只会快34倍。

But even 34 times faster is a lot !!! 但即便快了34倍!

In short, Using DateTime.UtcNow is much faster than DateTime.Now 简而言之,使用DateTime.UtcNowDateTime.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 我发现改进建议类的唯一方法是使用内联代码: DateTime.UtcNow + LocalUtcOffset而不是调用类方法

BTW trying to force the compiler to compile as inline by using [MethodImpl(MethodImplOptions.AggressiveInlining)] didnt seem to speed things up. BTW试图强制编译器通过使用[MethodImpl(MethodImplOptions.AggressiveInlining)]内联编译似乎没有加快速度。

To answer in reverse order: 以相反的顺序回答:

2) I cannot think of a faster way. 2)我想不出更快的方法。

1) It would be worth checking if there are any framework improvements in the pipeline like they have just announced for System.IO 1)值得检查管道中是否有任何框架改进,就像他们刚刚宣布的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. 系统一显然是非常强硬的,而你的系统却没有。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM