优化DateTime.Now的替代方案

时间:2009-10-13 17:39:16

标签: c# .net performance datetime optimization

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

首先,免责声明:我意识到“优化DateTime.Now”的概念听起来很疯狂。我有几个先发制人的防御措施:

  1. 我有时会怀疑那些总是说“计算机速度快;可读性始终在优化之前”的人经常从开发性能应用程序的经验来讲,尽管它可能重要< / em>,不是严重。我正在谈论要尽可能接近瞬间发生事情 - 比如,在几纳秒内(在某些行业,这个确实重要 - 例如,实时高频交易)。
  2. 即使考虑到这一点,我在下面描述的替代方法实际上是非常易读的。这不是一个奇怪的黑客,只是一种可靠而快速的简单方法。
  3. 我们运行测试。 DateTime.Now 缓慢(相对而言)。 下面的方法更快。
  4. 现在,问题本身。

    基本上,通过测试,我们发现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);
        }
    }
    

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

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

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

    我想知道的是:

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

4 个答案:

答案 0 :(得分:26)

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

答案 1 :(得分:7)

的结果之间的一个区别
DateTime.Now

DateTime.UtcNow + LocalUtcOffset 

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

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

答案 2 :(得分:5)

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

相比有多快

DateTime.UtcNowDateTime.Now

快117倍 如果我们只关注持续时间而不是时间本身,那么

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

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

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

快49倍

如果我们按照建议将这个计算放在一个单独的函数/类中,那么调用该方法会减慢我们的速度 而且我们只快了34倍。

但即便快了34倍!

简而言之, 使用DateTime.UtcNow要比DateTime.Now

快得多

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

BTW尝试使用[MethodImpl(MethodImplOptions.AggressiveInlining)]强制编译器以内联方式编译 似乎没有加快速度。

答案 3 :(得分:2)

以相反顺序回答:

2)我想不出更快的方法。

1)值得检查管道中是否有任何框架改进,如just announced for System.IO

很难确定安全性,但这是很多单元测试的问题。想到夏令时。系统一显然是非常强硬的,而你的系统却没有。