I\'m encountering a really unusual issue here. It seems that the calling of Thread.sleep(n), where n > 0 would cause the following System.nanoTime() calls to be less predictable
The inconsistencies probably arise not from Java, but from the different OSs and VMs "atomic-" or system- clocks themselves.
According to the official .nanoTime()
documentation:
no guarantees are made except that the resolution is at least as good as that of currentTimeMillis()
source
...I can tell from personal knowledge that this is because in some OSs and VMs, the system itself doesn't support "atomic" clocks, which are necessary for higher resolutions. (I will post the link to source this information as soon as I find it again...It's been a long time.)
I can suggest at least two possible reasons of such behavior:
Thread.sleep
it is likely to fall into one of power-saving states, with frequency and voltage reduced. After than CPU won't return to its maximum performance immediately, this may take from several nanoseconds to microseconds.Thread.sleep
, it will be scheduled for execution again after a timer event which might be related to the timer used for System.nanoTime
.In both cases you can't directly work around this - I mean Thread.sleep
will also affect timings in your real application. But if the amount of useful work measured is large enough, the inaccuracy will be negligible.
This is a complex topic because the timers used by the JVM are highly CPU- and OS-dependent and also change with JVM versions (e.g. by using newer OS APIs). Virtual machines may also limit the CPU capabilities they pass through to guests, which may alter the choices in comparison to a bare metal setup.
On x86 the RDTSC instruction provides the lowest latency and best granularity of all clocks, but under some configurations it's not available or reliable enough as a time source.
On linux you should check kernel startup messages (dmesg
), the tsc-related /proc/cpuinfo
flags and the selected /sys/devices/system/clocksource/*/current_clocksource
. The kernel will try to use TSC by default, if it doesn't there may be a reason for that.
For some history you may want to read the following, but note that some of those articles may be a bit dated, TSC reliability has improved a lot over the years:
-XX:+AssumeMonotonicOSTimers
manual override/footgun)UseLinuxPosixThreadCPUClocks
)constant_tsc tsc_reliable nonstop_tsc
in linux nomenclature)