Windows 上的时钟漂移
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/102064/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Clock drift on Windows
提问by Matt Howells
I've developed a Windows service which tracks business events. It uses the Windows clock to timestamp events. However, the underlying clock can drift quite dramatically (e.g. losing a few seconds per minute), particularly when the CPUs are working hard. Our servers use the Windows Time Service to stay in sync with domain controllers, which uses NTP under the hood, but the sync frequency is controlled by domain policy, and in any case even syncing every minute would still allow significant drift. Are there any techniques we can use to keep the clock more stable, other than using hardware clocks?
我开发了一个跟踪业务事件的 Windows 服务。它使用 Windows 时钟为事件添加时间戳。然而,底层时钟的漂移可能相当大(例如每分钟丢失几秒),尤其是当 CPU 正在努力工作时。我们的服务器使用 Windows 时间服务与域控制器保持同步,域控制器在引擎盖下使用 NTP,但同步频率由域策略控制,在任何情况下,即使每分钟同步一次,仍然会出现明显的偏差。除了使用硬件时钟之外,我们可以使用任何技术来保持时钟更稳定吗?
回答by Mike Dimmick
Clock ticks should be predictable, but on most PC hardware - becausethey're not designed for real-time systems - other I/O device interrupts have priority over the clock tick interrupt, and some drivers do extensive processing in the interrupt service routine rather than defer it to a deferred procedure call(DPC), which means the system may not be able to serve the clock tick interrupt until (sometimes) long after it was signalled.
时钟滴答应该是可预测的,但在大多数 PC 硬件上——因为它们不是为实时系统设计的——其他 I/O 设备中断优先于时钟滴答中断,并且一些驱动程序在中断服务例程中进行大量处理而不是而不是将其推迟到延迟过程调用(DPC),这意味着系统可能无法在(有时)发出信号后很久才能为时钟滴答中断提供服务。
Other factors include bus-mastering I/O controllers which steal many memory bus cycles from the CPU, causing it to be starved of memory bus bandwidth for significant periods.
其他因素包括总线主控 I/O 控制器,它从 CPU 中窃取许多内存总线周期,导致它在很长一段时间内缺乏内存总线带宽。
As others have said, the clock-generation hardware may also vary its frequency as component values change with temperature.
正如其他人所说,随着组件值随温度变化,时钟生成硬件也可能会改变其频率。
Windows does allow the amount of ticks added to the real-time clock on every interrupt to be adjusted: see SetSystemTimeAdjustment. This would only work if you had a predictable clock skew, however. If the clock is only slightly off, the SNTP client ("Windows Time" service) will adjust this skew to make the clock tick slightly faster or slower to trend towards the correct time.
Windows 确实允许调整每个中断时添加到实时时钟的滴答数:请参阅 SetSystemTimeAdjustment。但是,这仅在您有可预测的时钟偏差时才有效。如果时钟只是稍微偏离,SNTP 客户端(“Windows 时间”服务)将调整此偏差,使时钟稍微快一点或慢一点,以趋向于正确的时间。
回答by Macke
I don't know if this applies, but ...
我不知道这是否适用,但是...
There's an issue with Windows that if you change the timer resolution with timeBeginPeriod()a lot, the clock will drift.
Windows 存在一个问题,如果您使用timeBeginPeriod()大量更改计时器分辨率,则时钟会漂移。
Actually, there is a bug in Java's Thread wait()
(and the os::sleep()
) function's Windows implementation that causes this behaviour. It always sets the timer resolution to 1 ms before wait in order to be accurate (regardless of sleep length), and restores it immediately upon completion, unless any other threads are still sleeping. This set/reset will then confuse the Windows clock, which expects the windows time quantum to be fairly constant.
实际上,Java 的 Thread wait()
(和os::sleep()
)函数的 Windows 实现中存在导致这种行为的错误。它总是在等待前将计时器分辨率设置为 1 毫秒,以确保准确(无论睡眠长度如何),并在完成后立即恢复,除非任何其他线程仍在睡眠中。这个设置/重置会混淆 Windows 时钟,它期望 Windows 时间量是相当恒定的。
Sun has actually known about this since 2006, and hasn't fixed it, AFAICT!
Sun 实际上自 2006 年以来就已经知道了这一点,并且还没有修复它,AFAICT!
We actually had the clock going twice as fast because of this! A simple Java program that sleeps 1 millisec in a loop shows this behaviour.
由于这个原因,我们实际上让时钟快了两倍!一个在循环中休眠 1 毫秒的简单 Java 程序显示了这种行为。
The solution is to set the time resolution yourself, to something low, and keep it there as long as possible. Use timeBeginPeriod() to control that. (We set it to 1 ms without any adverse effects.)
解决方案是自己将时间分辨率设置为较低的值,并尽可能长时间地保持该分辨率。使用 timeBeginPeriod() 来控制它。(我们将其设置为 1 毫秒,没有任何不利影响。)
For those coding in Java, the easier way to fix this is by creating a thread that sleeps as long as the app lives.
对于那些用 Java 编码的人来说,解决这个问题的更简单的方法是创建一个线程,只要应用程序存在就休眠。
Note that this will fix this issue on the machine globally, regardless of which application is the actual culprit.
请注意,无论哪个应用程序是真正的罪魁祸首,这都将在机器上全局解决此问题。
回答by Larry Silverman
You could run "w32tm /resync" in a scheduled task .bat file. This works on Windows Server 2003.
您可以在计划任务 .bat 文件中运行“w32tm /resync”。这适用于 Windows Server 2003。
回答by TraumaPony
Other than resynching the clock more frequently, I don't think there is much you can do, other than to get a new motherboard, as your clock signal doesn't seem to be at the right frequency.
除了更频繁地重新同步时钟之外,我认为除了购买新主板之外,您无能为力,因为您的时钟信号似乎不在正确的频率上。
回答by seeker
As already mentioned, Java programs can cause this issue.
如前所述,Java 程序可能会导致此问题。
Another solution that does not require code modification is adding the VM argument -XX:+ForceTimeHighResolution
(found on the NTP support page).
另一个不需要修改代码的解决方案是添加 VM 参数-XX:+ForceTimeHighResolution
(在NTP 支持页面上找到)。
9.2.3. Windows and Sun's Java Virtual Machine
Sun's Java Virtual Machine needs to be started with the >-XX:+ForceTimeHighResolution parameter to avoid losing interrupts.
See http://www.macromedia.com/support/coldfusion/ts/documents/createuuid_clock_speed.htmfor more information.
9.2.3. Windows 和 Sun 的 Java 虚拟机
Sun 的 Java 虚拟机需要使用 >-XX:+ForceTimeHighResolution 参数启动,以避免丢失中断。
有关更多信息,请参阅http://www.macromedia.com/support/coldfusion/ts/documents/createuuid_clock_speed.htm。
From the referenced link (via the Wayback machine- original link is gone):
从引用的链接(通过Wayback 机器- 原始链接消失了):
ColdFusion MX: CreateUUID Increases the Windows System Clock Speed
Calling the createUUID function multiple times under load in Macromedia ColdFusion MX and higher can cause the Windows system clock to accelerate. This is an issue with the Java Virtual Machine (JVM) in which Thread.sleep calls less than 10 milliseconds (ms) causes the Windows system clock to run faster. This behavior was originally filed as Sun Java Bug 4500388 (developer.java.sun.com/developer/bugParade/bugs/4500388.html) and has been confirmed for the 1.3.x and 1.4.x JVMs.
In ColdFusion MX, the createUUID function has an internal Thread.sleep call of 1 millisecond. When createUUID is heavily utilized, the Windows system clock will gain several seconds per minute. The rate of acceleration is proportional to the number of createUUID calls and the load on the ColdFusion MX server. Macromedia has observed this behavior in ColdFusion MX and higher on Windows XP, 2000, and 2003 systems.
ColdFusion MX:CreateUUID 提高了 Windows 系统时钟速度
在Macromedia ColdFusion MX 和更高版本的负载下多次调用createUUID 函数会导致Windows 系统时钟加速。这是 Java 虚拟机 (JVM) 的一个问题,其中 Thread.sleep 调用少于 10 毫秒 (ms) 会导致 Windows 系统时钟运行得更快。此行为最初作为 Sun Java 错误 4500388 (developer.java.sun.com/developer/bugParade/bugs/4500388.html) 归档,并已针对 1.3.x 和 1.4.x JVM 进行确认。
在 ColdFusion MX 中,createUUID 函数有一个 1 毫秒的内部 Thread.sleep 调用。当 createUUID 被大量使用时,Windows 系统时钟将每分钟增加几秒。加速速率与 createUUID 调用次数和 ColdFusion MX 服务器上的负载成正比。Macromedia 在 Windows XP、2000 和 2003 系统上的 ColdFusion MX 和更高版本中观察到了这种行为。
回答by Sam Greenhalgh
http://www.codinghorror.com/blog/2007/01/keeping-time-on-the-pc.html
http://www.codinghorror.com/blog/2007/01/keeping-time-on-the-pc.html
PC clocks should typically be accurate to within a few seconds per day. If you're experiencing massive clock drift-- on the order of minutes per day-- the first thing to check is your source of AC power. I've personally observed systems with a UPS plugged into another UPS (this is a no-no, by the way) that gained minutes per day. Removing the unnecessary UPS from the chain fixed the time problem. I am no hardware engineer, but I'm guessing that some timing signal in the power is used by the real-time clock chip on the motherboard.
PC 时钟通常应精确到每天几秒钟之内。如果您正在经历大量时钟漂移——每天几分钟——首先要检查的是您的交流电源。我个人观察过将 UPS 插入另一个 UPS 的系统(顺便说一句,这是一个禁忌),每天增加几分钟。从链中移除不必要的 UPS 解决了时间问题。我不是硬件工程师,但我猜测电源中的某些定时信号被主板上的实时时钟芯片使用。
回答by Martin Beckett
Increase the frequency of the re-sync. If the syncs are with your own main server on your own network there's no reason not to sync every minute.
增加重新同步的频率。如果同步与您自己网络上的主服务器同步,则没有理由不每分钟同步一次。
回答by Tomalak
Sync more often. Look at the Registry entries for the W32Time service, especially "Period". "SpecialSkew" sounds like it would help you.
更频繁地同步。查看W32Time 服务的注册表项,尤其是“Period”。“SpecialSkew”听起来对你有帮助。
回答by xtofl
Clock drift may be a consequence of the temperature; maybe you could try to get temperature more constant - using better cooling perhaps? You're never going to loose drift totally, though.
时钟漂移可能是温度的结果;也许您可以尝试使温度更恒定 - 也许使用更好的冷却?不过,你永远不会完全放松漂移。
Using an external clock (GPS receiver etc...), and a statistical method to relate CPU time to Absolute Time is what we use here to synch events in distributed systems.
使用外部时钟(GPS 接收器等)以及将 CPU 时间与绝对时间相关联的统计方法是我们在这里用来同步分布式系统中的事件的方法。
回答by Robert L
Since it sounds like you have a big business:
因为听起来你有一个大生意:
Take an old laptop or something which isn't good for much, but seems to have a more or less reliable clock, and call it the Timekeeper. The Timekeeper's only job is to, once every (say) 2 minutes, send a message to the servers telling the time. Instead of using the Windows clock for their timestamps, the servers will put down the time from the Timekeeper's last signal, plus the elapsed time since the signal. Check the Timekeeper's clock by your wristwatch once or twice a week. This should suffice.
拿一台旧的笔记本电脑或一些不太有用的东西,但似乎有一个或多或少可靠的时钟,并称之为计时员。计时员的唯一工作是每(例如)2 分钟向服务器发送一条消息,告知时间。服务器不会使用 Windows 时钟作为时间戳,而是将 Timekeeper 的最后一个信号的时间加上信号后经过的时间。每周用手表检查一次或两次计时员的时钟。这应该足够了。