JDK-8040140 : System.nanoTime() is slow and non-monotonic on OS X
Type:Bug
Component:hotspot
Sub-Component:runtime
Affected Version:7u80,9
Priority:P2
Status:Closed
Resolution:Fixed
OS:os_x
Submitted:2014-04-14
Updated:2022-05-06
Resolved:2014-04-25
The Version table provides details related to the release that this issue/RFE will be addressed.
Unresolved : Release in which this issue/RFE will be addressed. Resolved: Release in which this issue/RFE has been resolved. Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.
Results from the org.openjdk.jmh.benchmarks.NanoTimerBench (http://hg.openjdk.java.net/code-tools/jmh/file/57623b7f64e6/jmh-core-benchmarks/src/main/java/org/openjdk/jmh/benchmarks/NanoTimerBench.java) JMH benchmark:
gettimeofday() one thread (-wi 1 -f 0 -t 1)
Benchmark Mode Samples Mean Mean error Units
o.o.j.b.NanoTimerBench.granularity avgt 5 1045.209 14.944 ns/op
o.o.j.b.NanoTimerBench.latency avgt 5 48.219 1.234 ns/op
mach_absolute_time() with monotonic guarantee, one thread (-wi 1 -f 0 -t 1)
Benchmark Mode Samples Mean Mean error Units
o.o.j.b.NanoTimerBench.granularity avgt 5 41.527 3.871 ns/op
o.o.j.b.NanoTimerBench.latency avgt 5 40.995 2.578 ns/op
gettimeofday() five threads (-wi 1 -f 0 -t 5)
Benchmark Mode Samples Mean Mean error Units
o.o.j.b.NanoTimerBench.latency avgt 5 76.166 20.690 ns/op
mach_absolute_time() with monotonic guarantee, five threads (-wi 1 -f 0 -t 5)
Benchmark Mode Samples Mean Mean error Units
o.o.j.b.NanoTimerBench.latency avgt 5 156.376 21.081 ns/op
14-04-2014
The proposal is to use the system call mach_absolute_time() instead of gettimeofday() and to add safeguard to guarantee that the time is monotonic (similar to what we already have on solaris).
mach_absolute_time() is essentially a direct call to RDTSC, but with conversion factor to offset for any system sleeps and frequency changes. The call returns something that can be converted to nanoseconds using information from mach_timebase_info(). Calls to mach_absolute_time() do not enter the kernel and are very fast. The resulting time has nanosecond precision and as good accuracy as one can get.
Since the value from RDTSC can be subject to drifting between CPUs, we implement safeguards for this to make sure we never return a lower value than the previous values. This adds some overhead to nanoTime() but guards us against possible bugs in the OS. For users who are willing to trust the OS and need the fastest possible calls to System.nanoTime(), we add a flag to disable this safeguard: -XX:+AssumeMonotonicOSTimers (see JDK-6864866).