5

For a long time I measured passed time using System.currentTimeMillis() and only recently figured out that I can also use nanoTime(). However some results were not what I expected, as nanoTime measures the time from an arbitrary point in time instead of 01-01-1970 as currentTimeMillis does.

From the JavaDoc for nanoTime:

Returns the current value of the most precise available system timer, in nanoseconds.

This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time. The value returned represents nanoseconds since some fixed but arbitrary time (perhaps in the future, so values may be negative). This method provides nanosecond precision, but not necessarily nanosecond accuracy. No guarantees are made about how frequently values change. Differences in successive calls that span greater than approximately 292 years (263 nanoseconds) will not accurately compute elapsed time due to numerical overflow.

For example, to measure how long some code takes to execute:

long startTime = System.nanoTime();
// ... the code being measured ...    
long estimatedTime = System.nanoTime() - startTime;

I am confused by the arbitrary part. Measuring the passed time is only accurate if the reference timestamp is the same for both calls. However in the API documentation this is not guaranteed. I think that this was the cause for my mentioned issues. The time that is used is an implementation detail and therefore I cannot rely on it.

I am wondering about, when I can make good use of nanoTime and in which cases it goes horribly wrong. The main use cases that come to mind are:

  • Comparing nanoTime timestamps from different threads
  • Comparing nanoTime timestamps from different instances of the same JVM (think, serialized timestamp from a previous application run, or passed as part of a message to a different JVM)
  • Comparing nanoTime timestamps in different JVM implementations

There are some posts here on StackOverflow that address part of the issue, but largely leave the issue of the choosing of the time open:

Especially the link in the last one makes it clear that there are limitations when nanoTime can be used, but without knowing these limitations exactly it seems inherently unsafe to use it at all as the functionality that is built upon it may fail.

Community
  • 1
  • 1
hotzst
  • 7,238
  • 9
  • 41
  • 64
  • I'd say every use across JVM instances is unsafe. And this does not imply that other uses are safe. – Henry Jan 31 '16 at 09:31

2 Answers2

1

The documentation should perhaps be explicit about this, but what they mean by "fixed but arbitrary" is that within the same JVM (i.e. within the same running JVM instance), the reference value is fixed.

So (1) is safe, but not beyond that.

Anything beyond that is depending on implementation quirks.

Daniel Martin
  • 23,083
  • 6
  • 50
  • 70
  • Would this be safe to use on the same VM on different threads? I'm not measuring time across threads (starting time on one thread and trying to stop it on the other but I'm measuring elapsed time of two blocks of code and later adding them together. I'm wondering if this is thread safe? – Chigozie A. Jun 19 '19 at 21:25
  • @ChigozieA. That should be perfectly safe. – Daniel Martin Jun 19 '19 at 21:44
  • Ok thanks but when you say "should" can you elaborate? I don't want to risk getting timing messed up . I'm unsure of whether to use nanotime at all for the accuracy if it could risk compromising reliability of the measurements. Should I me mindful of something important like OS, or CPU differences? Some articles and other post claim nanotime isn't thread safe and should be avoided. – Chigozie A. Jun 19 '19 at 21:48
  • This a quote about thread safety for noontime: "Not thread safe. May return erroneous results if used between more than one threads." - Geeks for Geeks. So what I'm doing is calling the method between the **same** thread so it shouldn't produce any erroneous results, right? – Chigozie A. Jun 19 '19 at 21:59
  • @ChigozieA. Correct. – Daniel Martin Jun 19 '19 at 22:00
  • So if I decided to use it across multiple thread only then it would be unsafe? Is it **guaranteed** to not produce any erroneous errors considering I'm using the same OS and JVM and its not across threads. I just want to dumb this down and confirm this :) – Chigozie A. Jun 19 '19 at 22:05
  • In that case, it is guaranteed to produce results correct to the limits of the platform's accuracy. (Meaning that if the real result should be 293ns but your system is only accurate to within 10ns you might get 290ns or 300ns) – Daniel Martin Jun 19 '19 at 22:08
0

Timing on shared CPUs (normal computers) is never exact. You do not know when your process actually runs on the CPU (and not one of the 100 other processes). And it can only check time when it runs.

The smaller time units you measure, the more visible will this inaccuracy be.

Koebmand STO
  • 171
  • 9