ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – 秒表和DateTime.UtcNow产生意外的大时序变化

2019-05-28 12:52:59  阅读:306  来源: 互联网

标签:c datetime timing stopwatch


我们有应用程序日志记录各种昂贵操作的性能信息.我们在日志记录中同时使用Stopwatch和DateTime.UtcNow,我们发现这些值可能比预期的要大很多,即使给定DateTime.UtcNow的精度约为20ms.我的问题是什么可能导致这种情况并且可以修复?

记录的信息是:

> StartTime(DateTime.UtcNow)
> Duration(TimeSpan.FromSeconds((after – before)/(double)Stopwatch.Frequency),其中after和before是操作开始和结束时Stopwatch.GetTimestamp()的值
> EndTime(DateTime.UtcNow)

您可能希望EndTime接近StartTime Duration,但在某些情况下它已经过时了.我们对10000个这样的测量进行了采样,寻找EndTime和(StartTime Duration)差异超过20ms的情况.我们发现了以下内容:

> ~2%的条目是关闭的> 20ms的
>其中,它们的平均时间为100毫秒(最长为1.4秒)
>其中,在某些情况下,秒表计算的结束时间大于基于日期时间的结束时间,但在大多数情况下,秒表时间较短

机器信息

>在Windows Server 2012 R2上运行的Windows Server 2012 R2 Hyper-V VM
> VM为32GB RAM,8个虚拟CPU

解决方法:

这是可以预料的. StopWatch使用QueryPerformanceCounter(QPC),而DateTime.UtcNow使用计算机的实时时钟(RTC).

> QPC来自CPU的时间戳计数器(TSC),并且非常精确,但与UTC相关的准确性没有根据.
> RTC在计算机的主板上,通常使用廉价的晶体振荡器.这是准确的,但不准确.

要测量经过的时间,您需要精确度,因此应使用秒表.

要获取当前时间,您需要准确性,因此应使用DateTime.UtcNow.

很棒的阅读,有很多支持细节can be found here on MSDN.

您测量的变化是由于RTC中的时钟漂移造成的.你的RTC(全部都是)会在实时提前或落后几毫秒.这很常见,并且通过NTP同步定期更正.对于微小的调整,操作系统将在几秒钟内以较小的间隔(几毫秒一次)展开校正.

就解决方法而言,你可以考虑这样一个类:

public static class PreciseClock
{
    private static readonly DateTime StartTime = DateTime.UtcNow;
    private static readonly Stopwatch Stopwatch = Stopwatch.StartNew();

    public static DateTime GetCurrentUtcTime()
    {
        return StartTime + Stopwatch.Elapsed;
    }
}

但是,缺点是您在初始化类时假设RTC处于完全同步状态.实际上,你无法保证这一点.

如果您需要某种程度的保证,可以考虑自己进行NTP调用.我在NodaTime.NetworkClock实现了一个完全相同的类.它从Noda Time开始实现IClock接口.它定期调用NTP服务器,并使用秒表跟踪调用之间的时间.你会像这样使用它:

// grab the clock's singleton instance
var clock = NetworkClock.Instance;

// optionally set the ntp server during your app's startup
clock.NtpServer = "pool.ntp.org"; // or whatever server you want to sync with

// Get the current utc time whenever you like
DateTime utcNow = clock.Now.ToDateTimeUtc();

此外,还有大多数现代硬件都可以使用的“多媒体计时器”或“高精度事件计时器”(HPET).它提供比QPC更高的精度.但是,没有直接类在.NET Framework中公开它.如果你搜索,你会发现一些包含提供它的Win32函数的实现.通常情况下,除非您正在进行图形或音频之类的实时操作,否则这样做太过分了.

标签:c,datetime,timing,stopwatch
来源: https://codeday.me/bug/20190528/1171170.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有