JDK-6458294 : nanoTime affected by system clock change on Linux (RH9) or in general lacks monotonicity
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 5.0,6
  • Priority: P3
  • Status: Resolved
  • Resolution: Not an Issue
  • OS: linux,windows_xp
  • CPU: x86
  • Submitted: 2006-08-09
  • Updated: 2015-07-16
  • Resolved: 2015-07-16
java version "1.5.0_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_03-b07)
Java HotSpot(TM) Client VM (build 1.5.0_03-b07, mixed mode, sharing)

java version "1.6.0-ea"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-ea-b43)
Java HotSpot(TM) Client VM (build 1.6.0-ea-b43, mixed mode, sharing)

Linux localhost.localdomain 2.4.20-8 #1 Thu Mar 13 17:54:28 EST 2003 i686 i686 i386 GNU/Linux

System.nanotTime is documented as indicating time elapsed sinse some *fixed* point. However, under Linux (RedHat 9) it is affected by changes to the system time.

Run the code below, which displays currentTimeMillis and nanoTime approximately once a second. Change the system clock (e.g. with /sbin/hwclock --date "..." --set; /sbin/hwclock --hctosys).

1121957273144 - 1121957273144598000
1121957274154 - 1121957274154429000
1121957630244 - 1121957275244934000
1121957631254 - 1121957276254933000

1121957273144 - 1121957273144598000
1121957274154 - 1121957274154429000
1121957630244 - 1121957630244934000
1121957631254 - 1121957631254933000

This bug can be reproduced always.

---------- BEGIN SOURCE ----------
class ShowTimes {
    public static synchronized void main(String[] args) throws Throwable {
        for (;;) {
                System.currentTimeMillis() + " - " +
---------- END SOURCE ----------

The JVM will use CLOCK_MONOTONIC when available, and that should be universally the case these days. It is up to the underlying platform how to correctly implement CLOCK_MONOTONIC, but most of the issues with unsychronized, frequency-unstable TSC usage should be behind us. There are still potential issues in virtualized environments because you can configure them such that the source underpinning CLOCK_MONOTONIC is not monotonic - caveat emptor! The NTP skew that can be applied to CLOCK_MONOTONIC is not a bad thing and we do not want to use CLOCK_MONOTONIC_RAW - see JDK-8006942

EVALUATION The VM can only use the time sources available to it. If CLOCK_MONOTONIC is not supported then there is no monotonic clock available for the VM to use. On such systems the VM won't comply with the nanoTime spec. Trying to implement an internal monotonic time source based on timestamp counters or direct use of timer hardware is simply not feasible. Note even the monotonic clock is allowed to jump forward in time. Certainly nanoTime should be no worse than currentTimeMillis() and so should always be preferred for doing timing measurements - except when trying to measure something that is inherently tied to the time-of-day clock.

CLOCK_MONOTONIC can be affected by skew due to system time changes. The more recent CLOCK_MONOTONIC_RAW (linux only) is not supposed to be affected at all. We can't use the new clock until our supported build platform is upgraded to aa version of Linux that supports it.

EVALUATION Note that the utility provided by AMD is only for Windows, and is only a partial solution. From the tools description: "The AMD Dual-Core Optimizer helps to correct the resulting video performance effects or other incorrect timing effects that these applications may experience on dual-core processor systems, by periodically adjusting the core time-stamp-counters, so that they are synchronized." Depending on that period, and when you query the TSC, you might still get errant values.

EVALUATION Community member ###@###.### reports: Just wanted to drop a note that by installing the "AMD Dual-Core Optimizer" found on http://www.amd.com/us-en/Processors/TechnicalResources/0,,30_182_871_9706,00.html the erroneous behaviour vanished. This user is running: Windows XP Professional Service Pack 2 on: AMD Athlon(tm) 64 X2 Dual Core Processor 5200+

EVALUATION Note that general problems with non-monotonicity of nanoTime on Windows is typically due to the use of the TSC by Windows on multi-processor/core systems. There are patches/updates to Windows that prevent the use of the TSC, or it can be done explicitly by using the /usepmtimer boot.ini option. For more general information see: http://blogs.sun.com/dholmes/entry/inside_the_hotspot_vm_clocks

EVALUATION ----- Updated November 15, 2006 ----- Due to a number of bugs in the clock/timer facilities of the underlying OS (Windows, Linux and Solaris) the montonicity of nanoTime is not presently guaranteed. To address this guards will be put in place that at least ensure that time does not appear to go backwards.

EVALUATION -------------------- Further to the SDN comment regarding the same problem on Windows. It is possible for a similar problem to occur on Windows in some circumstances. If the VM determines that the Windows platform does not support QueryPerformanceFrequency/QueryPerformanceCounter then nanoTime will simply be implemented by invoking currentTimeMillis() and multiplying it by 10^6. As currentTimeMillis() is the time-of-day clock it is affected by changes to the system time. However, I'd be very surprised to find Windows XP running on hardware that did not support QueryPerformanceFrequency/QueryPerformanceCounter. Note that there are issues with use of QueryPerformanceCounter that can cause time to jump but these are not related to changes to the system clock. It would be informative, if possible, to find out the hardware details for the system on which this problem was observed. See also bug 5005837 for various windows timer issues.

EVALUATION nanoTime is a service provided by the VM via JVM_NanoTime. Redispatching to hotspot/runtime_system. Doug writes: Hotspot only preserves monotonicity if the underlying OS does, and on linux, this requires clock_gettime, otherwise falling back to gettimeofday. System.nanoTime basically just makes the associated call and then returns scaled result. Most likely, seeing time run backwards under gettimeofday version reflects ntp clock adjustments. Although I suppose you might check whether your linux kernel has known gettimeofday flakiness? Neal writes: > I have been advising people to do performance measurement using > nano time instead of milli time because it is monotonic. On > multiprocessor systems, we sometimes see nanoTime decreasing > from one sampling to another (within the same thread). This > makes my advice, and the effort people have been making to > switch, look silly.