【问题标题】:DateTime.UtcNow.Ticks sometimes jumps a remarkable amountDateTime.UtcNow.Ticks 有时会跳跃很多
【发布时间】:2010-09-20 18:21:16
【问题描述】:

在打印出DateTime.UtcNow.Ticks 值的紧密循环的测试应用程序中,我注意到该值每隔一小时左右就会跳跃一次。仔细查看以下示例数据:

1:52:14.312 PM - 633614215343125000
1:52:14.359 PM - 633614215343593750
1:52:14.421 PM - 633614215344218750
1:52:14.468 PM - 633614215344687500
1:52:14.515 PM - 633614215998593750 <-- WAY different

增量为 653906250 个刻度(65.390 秒)。我能想到的唯一原因是 Windows 时间服务正在我脚下进行一些同步。

  • 有没有专家可以证实这一点?
  • 在大约一个小时内漂移一分钟左右对我来说似乎很糟糕,但这里是这种情况吗?

【问题讨论】:

  • 您如何在左侧记录时间?那似乎没有相同的跳跃,这很奇怪......
  • 产生输出的是什么代码?采取了哪些措施来确保呼叫之间的间隔一致?你在使用 Thread.Sleep() 吗?

标签: .net windows datetime time


【解决方案1】:

实际上,只是用这个循环运行一些测试:

static DateTime past = DateTime.UtcNow;
    static void PrintTime()
    {
        while (stopLoop == 0)
        {
            DateTime now = DateTime.UtcNow;
            Console.WriteLine("{0} - {1} d: {2}", now, now.Ticks, now - past);
            Program.past = now;
            Thread.Sleep(2000);
        }
    }

如果我在两次调用之间更改了系统的时钟时间,则增量会相应地跳跃。因此,如果您正在运行时间同步或其他影响系统时间的进程,那么这将反映在输出中。

【讨论】:

    【解决方案2】:

    嗯……

    当您无法确定在此期间您没有调用某些阻塞系统调用(例如,可能是 Console.WriteLine)时,如何以这种方式测量时间?

    为了进行“工作测试”,您至少必须确保:

    • 您的机器上没有运行其他任何东西
    • 进程/线程优先级设置为高或类似
    • 不调用系统调用...只执行计算任务
    • 将线程关联设置到特定 CPU,这样您就不会在 CPU 之间切换

    即使您这样做,操作系统也会不时地(例如,在 Windows 双核桌面操作系统上为 15 毫秒)抢占您的线程...... 你仍然可以在 UTC 时间戳中看到那种“跳跃”。

    只是从用户空间到内核空间(在抢占/系统调用期间)再返回,而不做任何实质性的内核工作,大约需要 1000 个 CPU 周期...

    如果您的进程进入等待状态(通过调用一些阻塞 IO),它甚至可能更糟......

    所以我真的没有得到你的“测试”。 IMO 这是完全正常的。

    【讨论】:

    • 上面的输出每 40-60 毫秒显示一次,运行一个小时左右后,显示了 DateTime.UtcNow.Ticks(基于 GetSystemTimeAsFileTime api)返回的 65 秒跳跃。这不能是阻塞、处于等待状态或被抢占的东西。
    【解决方案3】:

    您能否发布代码来说明您是如何生成这些数据的?并提供有关您正在运行它的机器的详细信息?

    使用以下内容,我没有得到你所得到的。

            for (int i = 0; i < 10; i++)
            {
    
                Console.WriteLine(DateTime.Now.ToLongTimeString().ToString() + " - " + DateTime.UtcNow.Ticks.ToString());
    
                Thread.Sleep(10);
            }
    

    【讨论】:

    • 问题说它每小时左右只发生一次......你不太可能在 10 次迭代中看到它!
    【解决方案4】:

    Esteban 是正确的,系统时钟更改会导致连续轮询之间的增量时间发生变化。 Windows 时间服务是否每小时进行一次这些更改?有可能在一小时内偏离一分钟吗?

    为了在您的机器上捕捉到这种情况,如果您在检查之间跟踪变化的增量,您可以在变化异常高的变化上设置条件断点。

    long delta = 0;
    long ticks = 0;
    long lastTicks = DateTime.UtcNow.Ticks;
    while (true)
    {
        ticks = DateTime.UtcNow.Ticks;
        delta = ticks - lastTicks;
        lastTicks = ticks;
        // Conditional breakpoint: delta > 100000000 Is True
        Console.WriteLine("{0} - {1}", ticks, delta);
    }
    

    【讨论】:

      【解决方案5】:

      原始输出被 DebugView 捕获。我的托管应用程序正在进行 p/invoke OutputDebugString 调用,只是从一个也称为 Thread.Sleep(1) 的线程中的紧密循环中输出 DateTime.UtcNow.Ticks。

      \\JLECOURSXP 的系统信息: 正常运行时间:6 天 6 小时 22 分 53 秒 内核版本:Microsoft Windows XP,Multiprocessor Free 产品类型:专业 产品版本:5.1 服务包:3 内核版本号:2600 注册机构: 注册拥有者:setup 安装日期:2007 年 6 月 15 日下午 3:35:29 IE版本:7.0000 系统根目录:C:\WINDOWS 处理器:2 处理器速度:2.9 GHz 处理器类型:Intel(R) Pentium(R) D CPU 物理内存:3070 MB 视频驱动程序:RADEON 9250 - 次要

      【讨论】:

        猜你喜欢
        • 2019-08-13
        • 2023-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-15
        相关资源
        最近更新 更多