📜 ⬆️ ⬇️

Precision timestamp

While there is a hot discussion about whether or not to be a jigsaw in java 9, and in what form it should be - you shouldn’t forget about the usefulness that the nine carries with them - and one of them is to increase the accuracy of Clock.systemUTC () - JDK-8068730 .


What happened before?


Before java 8 was System.currentTimeMillis () and System.nanoTime () , and if the first gave wall clock time, but with a millisecond resolution, the second one gives time with resolution up to nanoseconds , but the scope is limited to measuring the time difference, and within one jvm - and about any use of such a timestamp between different machines and can not be.


Therefore, they often cycle their precise timestamps that give wall clock time with a higher resolution than currentTimeMillis (using jni with all the consequences) - in more detail about the difference between currentTimeMillis and nanoTime , and you can read about the bike in my old post .


Java 8 laid a very powerful foundation - the Java Time API . With it you can say while joda time , and embed your bike in java.time.Clock , because a regular SystemClock is essentially running on top of System.currentTimeMillis () and cannot provide resolution, better than a millisecond.


And now java 9 comes into play and breaking nothing (as regards time and its measurements) brings an improvement - you can throw away your jni bike, at least on Linux , MacOSX , BSD , Solaris and Windows - see the openjdk commit .


From a practical point of view, microsecond timestamps, rather than nanosecond, make sense - the reason is that ntp within an intranet can give time with an accuracy of 1 µs.


Let's write down the provider of the exact time clock wall clock with microsecond resolution ( source code including the native part):


public final class PreciseTimestamp { static final Clock clock = Clock.systemUTC(); static { try { System.loadLibrary("precisetimestamp"); } catch (Throwable e){ throw new RuntimeException(e.getMessage(), e); } } // JNI microsecond timestamp provider public static native long getMicros(); // Critical JNI microsecond timestamp provider public static native long getCMicros(); public static long clockMicros(){ final Instant instant = clock.instant(); return instant.getEpochSecond() * 1_000_000L + (instant.getNano() / 1_000); } } 

Java 8 will give something like this.


 JNI micros: 1494398000506568 Critical JNI micros: 1494398000506986 ClockUTC micros: 1494398000507000 currentTimeMillis: 1494398000507 

No wonder - inside the good old System.currentTimeMillis ()


And Java 9 :


 JNI micros: 1494398039238236 Critical JNI micros: 1494398039238439 ClockUTC micros: 1494398039238498 currentTimeMillis: 1494398039239 

Added:
Those. It looks like the standard SystemClock can be used as a replacement for jni bike - we believe that we can trust a podzelzheschogo implementation, with regard to the correctness of obtaining and monotony of increasing wall clock time, consider the granularity ( test for granularity and results )


 java 9: OS Value Units MacOSX: 1011.522 ns/op Windows: 999916.218 ns/op Linux: 1002.419 ns/op 

So The reasonableness of the intuitive assumption about the use of microsecond accuracy is confirmed by the measurement, with the exception of windows , which has a known problem with the use of GetSystemTimeAsFileTime - the JDK-8180466 bug has been reported to this problem.


But what about performance? - the performers will shout - and they will be right - the extra creation of the Instant object on the face.


We saw the benchmark , which of course compares the jni-bike (both normal and critical), a clock- based method, and for estimating the scale of the disaster System.currentTimeMillis () and System.nanoTime () :



See the report on Escape Analysis and scalarization , if you don’t understand why the clock.instant () call is more expensive (though not by much) than the more complex clockMicros method:


 public static long clockMicros(){ final Instant instant = clock.instant(); return instant.getEpochSecond() * 1_000_000L + (instant.getNano() / 1_000); } 

Added:
Make sure that the scalarization works by adding -prof: gc :


 Benchmark Mode Cnt Score Error Units PerfTiming.clockMicros:·gc.alloc.rate avgt 510⁻⁵ MB/sec PerfTiming.clockMicros:·gc.alloc.rate.norm avgt 510⁻⁶ B/op PerfTiming.instant:·gc.alloc.rate avgt 5 327,083 ± 13,098 MB/sec PerfTiming.instant:·gc.alloc.rate.norm avgt 5 24,000 ± 0,001 B/op 

Conclusions : Using SystemClock in 9k can quite replace jni bike - the price is ~ 10% of the call, it’s a lot or a little - everyone decides for himself - I’m willing to sacrifice these 10% to forget the headache about the jni library build and not forget it.


')

Source: https://habr.com/ru/post/328334/


All Articles