What is Windows's time server synchronisation precision? (and does it compensate the ping time?)

For the project described in Application of this question I need the best time clock precision possible, and one solution is to have a precise synchronisation of the computer's real time clock.

  1. What is the documented precision of doing a synchro with Windows 7's Adjust date/time > Internet time > Change settings > Update now...?

  2. More specifically, does it compensate the time server's ping?

    Example:

    • the time server sends a packet to say it's precisely 12:00:00.000
    • let's say the average ping from my computer to the time server is 93ms (average ping calculated during, say, the last minute)
    • the packet from time server will reach my computer at 12:00:00.093, right?
    • then Windows should set the time to 12:00:00.093 and not 12:00:00.000, right?
  3. If not, is there a Windows software that can do such a real-time clock synchro with ping compensation or other kind of improved precision?


Solution 1:

Very interesting question, so I did some digging into several sources.

The article Part II: Adjustment of System Time by Arno Lentfer from 2012 (PDF), contains many measurements and says this :

Windows synchronization to a network time reference has proved to not be very accurate. In particular, Windows versions VISTA and 7 seem to have lost some of the capabilities for some unknown reason. Unfortunately, there is not much information on this issue and the little information available basically says that Windows time synchronization should not be expected to be more accurate than a few seconds and that there may be a mishap in the behavior of SetSystemTimeAdjustment with respect to the meaning of the value of dwTimeAdjustment. Only Windows 8 has now overcome these drawbacks and its system time adjustment performs like it did on Windows XP.

The article notes that there are small errors that are built-in into the system clock, which does not in general keep exact time. The analysis shows that, with the examined hardware, system time may gain 0.0448 ms/s over the real clock.

The Microsoft article Support boundary to configure the Windows Time service for high-accuracy environments, concludes that the best you can hope for is 1 millisecond, using Windows 10 and Windows Server 2016 in a tightly controlled environment. Microsoft's documentation details the requirements for 1-second, 50-ms, and 1-ms accuracies, while older operating systems struggle to stay within a handful of seconds.

In contrast, Domain Time II achieves sub-millisecond provable accuracy, and, when using IEEE 1588-2008 Precision Time Protocol (PTP), can achieve low double-digit microsecond accuracy.

The Microsoft article outlines the requirements for a given accuracy :

Target Accuracy: 1 Second (1s) requirements

  • The target system must run Windows 10, Windows Server 2016.
  • The target system must synchronize time from a highly accurate NTP time source
  • Windows systems in the NTP hierarchy must be correctly configured
  • The cumulative one-way network latency between the target and source must not exceed 100ms.

Target Accuracy: 50 Milliseconds requirements

  • The target computer must have better than 5ms of network latency between its time source.
  • The target system must be no further than stratum 5 from a highly accurate time source
  • The target system must be within 6 or less network hops from the highly accurate time source
  • The one-day average CPU utilization on all stratums must not exceed 90%
  • For virtualized systems, the one-day average CPU utilization of the host must not exceed 90%

Note : Run w32tm /query /status from the command line to see the stratum.

Target Accuracy: 1 Millisecond requirements

  • The target computer must have better than 0.1 ms of network latency between its time source
  • The target system must be no further than stratum 5 from a highly accurate time source
  • The target system must be within 4 or less network hops from the highly accurate time source
  • The one-day average CPU utilization across each stratum must not exceed 80%
  • For virtualized systems, the one-day average CPU utilization of the host must not exceed 80%

If you are wondering what is stratum, it is important to realize that NTP is a hierarchical, semi-layered system of levels of clock. The following diagram comes from the article Network Time Protocol (NTP) How accurate is it? by Dave Gault (PDF) :

NTP hierarchy

The article also lists the factors that can have a detrimental effect upon the quality of time displayed:

  • Speed (latency) of the internet connection.
  • Strata of the time server(s) chosen for synchronization.
  • Signal distance from the servers (including to and from orbiting satellites).
  • The quality and complexity of the software algorithm used.
    • Does it use more than one server?
    • Does it compute the round-trip delay?
    • Does it compensate for systematic bias?
    • Does it report on the accuracy of the synchronization?

This came out as longer than I intended. But to answer your questions :

What is the documented precision of doing a synchro with Windows 7's Adjust date/time > Internet time > Change settings > Update now...?

That depends on which of the requirements for the above Target Accuracy apply to your installation. If none of the above requirements applies, your time may be off by up to 2 seconds from real time. The NTP time server may also have an inaccuracy, depending on its stratum. Note also that you will experience a constant time drift when using the computer's real time clock, which you might be able to measure (or which might be available from the manufacturer).

More specifically, does it compensate the time server's ping?

The answer is no. That is up to you to measure, remembering that ping time may not stay constant.

Conclusion: If you need more time accuracy than is provided by the Internet time servers, you would need to acquire and use a specialized clock device.

Interesting reading is the Algorithmic Trading article Precision Timekeeping on Windows, which explains how Microsoft has improved its internal timekeeping functions and to what precision of the system clock:

image

Useful tools to set or check computer time

If you wish to have your computer time synced with low-stratum servers via the Internet, you could use the free product Dimension 4 :

Dimension 4 uses a low level internet protocol, called SNTP, to connect with special purpose Internet Time Servers that have been keeping the rest of the web on-time for the last 20+ years. These time servers typically have direct access to their very own time source, or they are connected directly to other Internet Time Servers that do.

At an interval you specify, Dimension 4 connects to one of these Internet Time Servers, which you get to choose from an exhaustive list built direclty into Dimension 4. The Time Server then sends the correct time back to your computer, where Dimension 4 uses sophisticated algorithms to correctly adjust your computer's clock to with-in a few milliseconds of the real time.

You may also verify your computer clock against the website time.is :

image

Solution 2:

This is an attempt of time setting in Python, according to a NTP server, with compensation of the trip time of the packet between time server and myself (see Clock synchronization algorithm):

NTPSERVER, PORT = 'pool.ntp.org', 123

from contextlib import closing
from socket import socket, AF_INET, SOCK_DGRAM, SOCK_STREAM
import struct, time, sys, datetime
import win32api  # pip install pywin32

t0 = time.time()
with closing(socket(AF_INET, SOCK_DGRAM)) as s:
    s.sendto('\x23' + 47 * '\0', (NTPSERVER, PORT))   # see https://stackoverflow.com/a/26938508
    msg, address = s.recvfrom(1024)                   # and https://stackoverflow.com/a/33436061
t3 = time.time()

unpacked = struct.unpack("!12I", msg[0:struct.calcsize("!12I")])  # ! => network (= big-endian), 12 => returns 12-tuple, I => unsigned int

t1 = unpacked[8] + float(unpacked[9]) / 2**32 - 2208988800L     # see https://tools.ietf.org/html/rfc5905#page-19
t2 = unpacked[10] + float(unpacked[11]) / 2**32 - 2208988800L   # and https://tools.ietf.org/html/rfc5905#page-13

offset = ((t1 - t0) + (t2 - t3)) / 2    # https://en.wikipedia.org/wiki/Network_Time_Protocol#Clock_synchronization_algorithm
roundtrip = (t3 -  t0) - (t2 - t1)

print "Local computer time (t0)                               %.3f" % t0
print "NTP server time (t1, receive timestamp)                %.3f" % t1 
print "NTP server time (t2, transmit timestamp)               %.3f" % t2
print "Local computer time (t3)                               %.3f" % t3
print "Offset                                                 %.1f ms" % (offset * 1000)
print "Local -> NTP server -> local roundtrip time            %.1f ms" % (roundtrip * 1000)
print "New local computer time                                %.3f" % (t3 + offset)

dt = datetime.datetime.utcfromtimestamp(t3 + offset)
win32api.SetSystemTime(dt.year, dt.month, dt.isocalendar()[2], dt.day, dt.hour, dt.minute, dt.second, dt.microsecond / 1000)

Example of output:

Local computer time (t0)                               1528290913.275
NTP server time (t1, receive timestamp)                1528290913.297
NTP server time (t2, transmit timestamp)               1528290913.297
Local computer time (t3)                               1528290913.340
Offset                                                 -10.5 ms
Local -> NTP server -> local roundtrip time            65.0 ms
New local computer time                                1528290913.330

Note:

  • We could have used ntplib instead, but here the advantage is that we learned how it internally works, and the code is not long anyway!

  • In the case t1 == t2 (this was always true during my tests), then t3 + offset = t1 + (t3 - t0)/2, and this computation gives the exact same result as this answer's previous edit tcompensated = t + (now-start) / 2.

  • ((t1 - t0) + (t2 - t3)) / 2 really gives the offset between local clock and NTP server clock. Indeed, let's call trip the one-way trip time for a packet to go from local computer to NTP server. Then t1 = t0 + offset + trip and t3 = t2 - offset + trip. Then ((t1 - t0) + (t2 - t3)) / 2 = (offset + trip + offset - trip) / 2 = offset.