Question

Java gives access to two method to get the current time: System.nanoTime() and System.currentTimeMillis(). The first one gives a result in nanoseconds, but the actual accuracy is much worse than that (many microseconds).

Is the JVM already providing the best possible value for each particular machine? Otherwise, is there some Java library that can give finer measurement, possibly by being tied to a particular system?

Was it helpful?

Solution

The problem with getting super precise time measurements is that some processors can't/don't provide such tiny increments.

As far as I know, System.currentTimeMillis() and System.nanoTime() is the best measurement you will be able to find.

Note that both return a long value.

OTHER TIPS

It's a bit pointless in Java measuring time down to the nanosecond scale; an occasional GC hit will easily wipe out any kind of accuracy this may have given. In any case, the documentation states that whilst it gives nanosecond precision, it's not the same thing as nanosecond accuracy; and there are operating systems which don't report nanoseconds in any case (which is why you'll find answers quantized to 1000 when accessing them; it's not luck, it's limitation).

Not only that, but depending on how the feature is actually implemented by the OS, you might find quantized results coming through anyway (e.g. answers that always end in 64 or 128 instead of intermediate values).

It's also worth noting that the purpose of the method is to find the two time differences between some (nearby) start time and now; if you take System.nanoTime() at the start of a long-running application and then take System.nanoTime() a long time later, it may have drifted quite far from real time. So you should only really use it for periods of less than 1s; if you need a longer running time than that, milliseconds should be enough. (And if it's not, then make up the last few numbers; you'll probably impress clients and the result will be just as valid.)

Unfortunately, I don't think java RTS is mature enough at this moment.

Java time does try to provide best value (they actually delegate the native code to call get the kernal time). However, JVM specs make this coarse time measurement disclaimer mainly for things like GC activities, and support of underlying system.

  • Certain GC activities will block all threads even if you are running concurrent GC.
  • default linux clock tick precision is only 10ms. Java cannot make it any better if linux kernal does not support.

I haven't figured out how to address #1 unless your app does not need to do GC. A decent and med size application probably and occasionally spends like tens of milliseconds on GC pauses. You are probably out of luck if your precision requirement is lower 10ms.

As for #2, You can tune the linux kernal to give more precision. However, you are also getting less out of your box because now kernal context switch more often.

Perhaps, we should look at it different angle. Is there a reason that OPS needs precision of 10ms of lower? Is it okay to tell Ops that precision is at 10ms AND also look at the GC log at that time, so they know the time is +-10ms accurate without GC activity around that time?

If you are looking to record some type of phenomenon on the order of nanoseconds, what you really need is a real-time operating system. The accuracy of the timer will greatly depend on the operating system's implementation of its high resolution timer and the underlying hardware.

However, you can still stay with Java since there are RTOS versions available.

JNI: Create a simple function to access the Intel RDTSC instruction or the PMCCNTR register of co-processor p15 in ARM.

Pure Java: You can possibly get better values if you are willing to delay until a clock tick. You can spin checking System.nanoTime() until the value changes. If you know for instance that the value of System.nanoTime() changes every 10000 loop iterations on your platform by amount DELTA then the actual event time was finalNanoTime-DELTA*ITERATIONS/10000. You will need to "warm-up" the code before taking actual measurements.

Hack (for profiling, etc, only): If garbage collection is throwing you off you could always measure the time using a high-priority thread running in a second jvm which doesn't create objects. Have it spin incrementing a long in shared memory which you use as a clock.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top