优化DateTime.Now的替代方案

Dan*_*Tao 24 .net c# optimization performance datetime

我和一位同事在这个问题上来回走动,我希望得到一些外界意见,看看我提出的解决方案是否是一个好主意.

首先,免责声明:我意识到"优化DateTime.Now" 的概念对你们中的某些人来说听起来很疯狂.我有几个先发制人的防御措施:

  1. 我有时会怀疑那些总是说"计算机速度快;可读性总是在优化之前"的人经常从开发应用程序的经验来讲,其中性能虽然可能很重要,但并不重要.我正在谈论尽可能接近瞬间发生事情 - 比如,在几纳秒内(在某些行业,这确实很重要 - 例如,实时高频交易).
  2. 即使考虑到这一点,我在下面描述的替代方法实际上是非常易读的.这不是一个奇怪的黑客,只是一个可靠而快速工作的简单方法.
  3. 我们运行测试.DateTime.Now 慢(相对来说).下面的方法更快.

现在,问题本身.

基本上,通过测试,我们发现DateTime.Now运行大约需要25个滴答(大约2.5微秒).当然,这可以在数千到数百万次通话中取平均值.看起来第一个呼叫实际上需要花费大量时间,后续呼叫要快得多.但仍然是25个蜱是平均值.

然而,我和我的同事注意到,DateTime.UtcNow运行时间要少得多 - 平均只需0.03微秒.

鉴于我们的应用程序永远不会在夏令时发生变化时运行,我的建议是创建以下类:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

换句话说,确定本地时区的UTC偏移一次 - 在启动时 - 从那时起利用速度DateTime.UtcNow来更快地获得当前时间FastDateTime.Now.

如果在应用程序运行期间UTC偏移发生了变化(例如,如果应用程序在一夜之间运行),我可以看到这是一个问题; 但正如我已经说过的那样,在我们的情况下,这不会发生.

我的同事对如何做到这一点有不同的想法,这对我来说有点过于复杂.最终,据我所知,我们的两种方法都返回了准确的结果,我的方法稍快一些(约0.07微秒与~0.21微秒).

我想知道的是:

  1. 我在这里错过了什么吗?鉴于上述事实,申请只会在一个日期的时间范围内运行,是否FastDateTime.Now安全?
  2. 任何人都可以想到更快的方式获得当前时间吗?

Mic*_*ael 26

你能使用DateTime.UtcNow,只在数据出现时转换为本地时间吗?您已经确定DateTime.UtcNow更快,它将消除DST周围的任何歧义.

  • +1我读到UtcNow要快得多,这让我感到惊讶.http://blogs.msdn.com/clrperfblog/archive/2009/09/08/computing-time-in-net.aspx (2认同)
  • 我要继续接受这个答案,因为它让人感觉到了很多.不幸的是,由于我们必须改变的代码量,我认为我们不会这样做(至少现在还没有).但这是一个非常合乎逻辑的建议. (2认同)

Han*_*man 8

结果之一的一个区别

DateTime.Now
Run Code Online (Sandbox Code Playgroud)

DateTime.UtcNow + LocalUtcOffset 
Run Code Online (Sandbox Code Playgroud)

是Kind属性的值 - Local vs Utc.如果将生成的DateTime传递给第三方库,请考虑返回

DateTime.SpecifyKind(DateTime.UtcNow + LocalUtcOffset, DateTimeKind.Local)
Run Code Online (Sandbox Code Playgroud)


小智 5

我喜欢你的解决方案.我做了一些测试,看看它与常规相比有多快DateTime.Now

DateTime.UtcNow 是快117倍 DateTime.Now

DateTime.UtcNow如果我们只关注持续时间而不是时间本身,那么使用就足够了.如果我们只需要计算特定代码段(执行duration= End_time - Start_time)的持续时间,那么时区并不重要且DateTime.UtcNow足够.

但如果我们需要时间本身,那么我们需要这样做 DateTime.UtcNow + LocalUtcOffset

只是添加时间跨度减慢了一点点,现在根据我的测试,我们只比常规时间快49倍 DateTime.Now

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

但即便快了34倍!

简而言之,使用DateTime.UtcNow比快得多DateTime.Now

我发现改进建议类的唯一方法是使用内联代码:DateTime.UtcNow + LocalUtcOffset 而不是调用类方法

BTW试图强制编译器通过使用[MethodImpl(MethodImplOptions.AggressiveInlining)] didnt进行内联编译似乎加快了速度.