JDK-8180466 : Clock.systemUTC has low resolution on Windows
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Won't Fix
  • OS: windows_7
  • CPU: x86_64
  • Submitted: 2017-05-15
  • Updated: 2021-02-26
  • Resolved: 2019-02-27
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
A DESCRIPTION OF THE REQUEST :
With [JDK-8068730](https://bugs.openjdk.java.net/browse/JDK-8068730) SystemClock uses more precise timestamp provider, but it uses incorrect timeprovider for Windows - [GetSystemTimeAsFileTime](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724397(v=vs.85).aspx) - [see commit](http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/fca33371ff0b#l14.27) - that provides similar resolution as **System.currentTimeMillis**.

There is another timeprovider in WinAPI that gives wall-clock time with higher resolution - [GetSystemTimePreciseAsFileTime](https://msdn.microsoft.com/en-us/library/windows/desktop/hh706895(v=vs.85).aspx)


JUSTIFICATION :
Clock.systemUTC in fact provides microsecond resolution on Linux/MacOSX, while Windows doesn't get any benefits of JDK-8068730

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expecting sub-millisecond resolution
ACTUAL -
Results on Windows:
```
java.version:9-ea
took 68.991 us
clock diff 0 us
instants [2017-05-12T11:28:36.489481500Z, 2017-05-12T11:28:36.489481500Z, 2017-05-12T11:28:36.489481500Z, 2017-05-12T11:28:36.489481500Z, 2017-05-12T11:28:36.489481500Z, 2017-05-12T11:28:36.489481500Z, 2017-05-12T11:28:36.489481500Z, 2017-05-12T11:28:36.489481500Z, 2017-05-12T11:28:36.489481500Z, 2017-05-12T11:28:36.489481500Z] us
diffs [0, 0, 0, 0, 0, 0, 0, 0, 0] us
```

Results on Linux:
```
 $  ~/jdk9/bin/java ClockTest
java.version:9-ea
took 150.142 us
clock diff 135 us
instants [2017-05-12T10:49:05.227999Z, 2017-05-12T10:49:05.228126Z, 2017-05-12T10:49:05.228127Z, 2017-05-12T10:49:05.228129Z, 2017-05-12T10:49:05.228130Z, 2017-05-12T10:49:05.228131Z, 2017-05-12T10:49:05.228132Z, 2017-05-12T10:49:05.228132Z, 2017-05-12T10:49:05.228133Z, 2017-05-12T10:49:05.228134Z] us
diffs [127, 1, 2, 1, 1, 1, 0, 1, 1] us
```

---------- BEGIN SOURCE ----------
import java.time.Clock;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;

/**
 * @author vladimir.dolzhenko
 * @since 2017-05-12
 */
public class ClockTest {
    public static void main(String[] args) {
        final Clock clock = Clock.systemUTC();

        int count = 10;
        Instant[] instants = new Instant[count];
        final long start = System.nanoTime();
        for (int i = 0; i < count; i++) {
            instants[i] = clock.instant();
        }
        final long end = System.nanoTime();

        System.out.println("java.version:" + System.getProperty("java.version"));
        System.out.println("took " + (end - start) / 1e3 + " us");
        System.out.println("clock diff " + ChronoUnit.MICROS.between(instants[0], instants[count - 1]) + " us");
        long[] diffs = new long[count - 1];
        for (int i = 1; i < count; i++) {
            diffs[i - 1] = ChronoUnit.MICROS.between(instants[i - 1], instants[i]);
        }
        System.out.println("instants " + Arrays.toString(instants) + " us");
        System.out.println("diffs " + Arrays.toString(diffs) + " us");

    }
}
---------- END SOURCE ----------


Comments
The change was simple to implement: http://cr.openjdk.java.net/~dholmes/8180466/webrev/ But I will have to close this as "will not fix". There is the performance aspect of the call itself to be potentially concerned about - though it would likely put it on a par with nanoTime() so I'm not that concerned. But I've also read that it can have problems during "system time adjustments" [1] "The high resolution of GetSystemTimePreciseAsFileTime() is derived from the performance counter value at the time of the call and the performance counter frequency. However, the performance counter frequency should be corrected during system time adjustments to adapt to the modified progress in time. Current Windows versions don't do this. The obtained microsecond part may be severely affected when system time adjustments are active. ... As of Windows 10 (Build 10240), the inaccuracy of GetSystemTimePreciseAsFileTime() during system time adjustments persists." That sounds like something that may introduce very obscure bugs. So while getting higher-resolution for Clock.systemUTC may be nice to have, the potential risks do not justify making the switch. If we were to have a lot of interest in this, then it may be possible to reopen and consider adding a flag to allow the user to opt-in to the new API. But for now there is no justification for doing that either. --- This is a very interesting read! [1] http://www.windowstimestamp.com/description
27-02-2019

Some results of running the above test on different recent Windows machines: ClockTest ----------System.out:(5/433)---------- java.version:13-internal took 210.921 us clock diff 190 us instants [2019-02-25T23:06:41.316925700Z, 2019-02-25T23:06:41.317086600Z, 2019-02-25T23:06:41.317090800Z, 2019-02-25T23:06:41.317094500Z, 2019-02-25T23:06:41.317098100Z, 2019-02-25T23:06:41.317101700Z, 2019-02-25T23:06:41.317105400Z, 2019-02-25T23:06:41.317109Z, 2019-02-25T23:06:41.317112600Z, 2019-02-25T23:06:41.317116300Z] us diffs [160, 4, 3, 3, 3, 3, 3, 3, 3] us --- ClockTest ----------System.out:(5/433)---------- java.version:13-internal took 174.603 us clock diff 157 us instants [2019-02-25T23:05:57.753857400Z, 2019-02-25T23:05:57.753988200Z, 2019-02-25T23:05:57.753991800Z, 2019-02-25T23:05:57.753994900Z, 2019-02-25T23:05:57.753998200Z, 2019-02-25T23:05:57.754001600Z, 2019-02-25T23:05:57.754004700Z, 2019-02-25T23:05:57.754008Z, 2019-02-25T23:05:57.754011400Z, 2019-02-25T23:05:57.754014500Z] us diffs [130, 3, 3, 3, 3, 3, 3, 3, 3] us --- And my Windows 7 box: java.version:13-internal took 50.425 us clock diff 0 us instants [2019-02-23T07:08:51.556851600Z, 2019-02-23T07:08:51.556851600Z, 2019-02-23T07:08:51.556851600Z, 2019-02-23T07:08:51.556851600Z, 019-02-23T07:08:51.556851600Z, 2019-02-23T07:08:51.556851600Z, 2019-02-23T07:08:51.556851600Z, 2019-02-23T07:08:51.556851600Z, 2019-02-23T07:08:51.556851600Z, 2019-02-23T07:08:51.556851600Z] us diffs [0, 0, 0, 0, 0, 0, 0, 0, 0] us
26-02-2019

Dynamic lookup of the needed function seems to be simple to do.
22-02-2019

Per the comment by David, I am transferring this to hotspot.
21-08-2018

Technically this would be a hotspot runtime issue in terms of actually making the changes. We would have to trial switching both os::javaTimeMillis and os::javaTimeSystemUTC to use the new API. It should be a trivial change to make in itself but we need to deal with the API not being available before Windows 8 / Windows Server 2012. Unfortunately I think we will be supporting those platforms, or at least not wanting to fail to run on those platforms, for some time to come.
17-05-2017