【问题标题】:TimeZoneInfo.ConvertTime is incredibly slow on DateTime.MinValueTimeZoneInfo.ConvertTime 在 DateTime.MinValue 上非常慢
【发布时间】:2018-06-14 08:35:15
【问题描述】:

我刚刚注意到我们的一个单元测试占用了十秒钟。在玩弄它之后,我创建了一个最小的 linqpad 示例来重现它:

void Main()
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    var timeZone = TimeZoneInfo.Local;
    for(int i=0; i<10000; i++)
    {
      //var dateTime = TimeZoneInfo.ConvertTime(DateTime.UtcNow, timeZone);   
      var dateTime = TimeZoneInfo.ConvertTime(DateTime.MinValue, timeZone);   
    }
    sw.Stop();
    (sw.ElapsedMilliseconds + " ms").Dump();
}

这在我的 PC 或我们的构建 PC 上需要 40 秒。如果我使用 DateTime.UtcNow,则需要 15 毫秒。

有什么原因或解决方法吗?


编辑:按照 cmets 中的建议,我反编译了 TimeZoneInfo,并且 DateTime.MinValue 有一个特殊情况:

static public DateTime ConvertTime(DateTime dateTime, TimeZoneInfo destinationTimeZone) {
    // Special case to give a way clearing the cache without exposing ClearCachedData()
    if (dateTime.Ticks == 0) {
        ClearCachedData();
    }

看起来(测试?)代码每次使用 DateTime.MinValue 调用时都会清除缓存。

留下为什么会发生这种情况的问题。

【问题讨论】:

  • 我猜你可以使用一些 Dll 反编译工具来检查你自己的代码,看看这两个属性是如何在幕后生成的。
  • 好点,我去看看。
  • // Special case to give a way clearing the cache without exposing ClearCachedData() 嗯,这有点邪恶。特别是因为它实际上是暴露的。不知何故,这通过了代码审查。幸运的是,从伯利恒转换一个古老的日期并不常见:)
  • 我们有很多命中的原因是 DateTime.MinValue 是默认值,它与使用 new DateTime() 相同。
  • “神奇值”出错的频率非常惊人。但是,是的,通常不止一个程序员认为它足够神奇。永远支持Nullable&lt;DateTime&gt;这里。

标签: c# .net timezone


【解决方案1】:

无需反编译。您可以在the .NET Framework Reference Sourcethe CoreCLR source code on GitHub 中找到它。

在 .NET 4.6 中添加了这种特殊情况,作为一种非官方的解决方法,用于在当时没有暴露 ClearCachedData 方法的 WinRT 等环境中清除时区缓存。 I describe this further here.

偶尔清除时区缓存通常不会产生明显的效果。你看到它是因为紧密的循环。如果这是您的用例所关心的问题,那么我建议使用ConvertTimeFromUtc 方法,或者与DateTimeOffset 一起使用的ConvertTime 版本。这些代码路径没有遇到特殊情况。

是的,我同意这应该更好地记录下来。我看看能不能进去。

请注意,从逻辑上讲,为DateTime.MinValue 转换时区并没有多大意义,因为我们今天所知道的时区不在第一年。

【讨论】:

  • 几个月前我们的生产服务器 CPU 达到峰值。检查线程在做什么,所有线程都忙于 TimeZoneInfo.ConvertTime。我们不知道为什么。所以这至少应该记录在 MSDN 信息中。我们将更改对 ConvertTimeFromUtc 的调用,并看看为什么我们使用 DateTime.MinValue 进行调用。感谢您的信息。
猜你喜欢
  • 2010-12-17
  • 2015-04-14
  • 2018-08-21
  • 2013-06-19
  • 2015-06-11
  • 2018-06-29
  • 2016-02-28
  • 1970-01-01
  • 2015-06-06
相关资源
最近更新 更多