Obtaining the time in Java with nano-second precision


At TransFICC for MiFID compliance (as explained in my previous blog) we need to obtain the time of an event within 100 microsecond accuracy with respect to UTC. To achieve this in Java we first need to be able to obtain the time from the OS with better than millisecond precision. We can then make use of Precision Time Protocol (PTP) to ensure the system clock is synchronised to UTC with sufficient accuracy. Take a look at the excellent posts from Luke Bigum on how to achieve this. As of Java version 8 it is not possible to directly obtain the time with higher than millisecond precision. Java 8 System.currentTimeMillis() will return the time since the Unix epoch in milliseconds. Higher precision time is possible on some underlying systems such as Linux.

On Linux the code that the OpenJDK JVM executes is:
The full source can be found here. The code makes the function call gettimeofday(). This returns the time since the Linux epoch in micro seconds however it is rounded to the nearest millisecond. On newer Linux kernels this is an alias for clock_gettime(). The POSIX spec has deprecated gettimeofday() for clock_gettime() so this should be used instead. On modern Linux systems the function call is implemented as a Virtual Dynamic Shared Object or (VDSO) as opposed to a system call for improved performance.

The accuracy and of the underlying clock is dependent on the clock source being used by the kernel. To view all clock sources availble execute
cat /sys/devices/system/clocksource/*/available_clocksource
To view the current clock source in use execute 
cat /sys/devices/system/clocksource/*/current_clocksource


Calling clock_gettime() to obtain a nanosecond precision time from the JVM can be achieved using Java using JNA or JNI.  We implement both clock_gettime() using JNA and JNI and performance compared with System.currentTimeMillis() as a baseline. The tests were conducted on a Intel Xeon CPU E5-1650 v3 @ 3.50GHz using the Java Benchmark Harness (JMH).

All the code and benchmarks are available here to be executed independently.



Source JMH output is here

For the most part this is a comparison between JNA and JNI performance. JNA has the advantage of not requiring the user to compile any native code but this comes at the cost of performance. For each call to obtain the time JNA constructs Structure objects that represent native structures. This results in a worse median latency as well as generating significant amounts of garbage degrading long tail latency. The JNA direct mapping showed improved performance past the 99.99 percentiles but was still significantly slower than JNI.

In the future there will be some support for higher precision time in Java 9.




Comments

Popular posts from this blog

Persisting JMH Results for Regression Detection

The case for hard-coding configuration