2

在打印出 的值的紧密循环的测试应用程序中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 时间服务正在我脚下进行一些同步。

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

5 回答 5

2

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

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);
        }
    }

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

于 2008-11-04T20:42:07.877 回答
1

嗯……

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

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

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

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

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

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

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

于 2008-11-05T12:46:40.160 回答
0

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

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

        for (int i = 0; i < 10; i++)
        {

            Console.WriteLine(DateTime.Now.ToLongTimeString().ToString() + " - " + DateTime.UtcNow.Ticks.ToString());

            Thread.Sleep(10);
        }
于 2008-11-04T20:16:48.910 回答
0

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);
}
于 2008-11-04T20:55:28.863 回答
0

原始输出被 DebugView 捕获。我的托管应用程序正在进行 ap/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 - 次要
于 2008-11-04T21:03:08.503 回答