0

Everything I've read about currentTimeMillis vs nanoTime seem to only focus on accuracy. If I'm only looking for elapsed time in milliseconds, which one of these should I use if I want the best performance?

Seems like currentTimeMillis would be the answer, since I don't need to convert the final answer from ns to ms, but that's from my application's perspective, and what goes on under the hood could make it the wrong choice, which is why I'm asking.

Brent212
  • 1,835
  • 4
  • 19
  • 23
  • I personally just use #currentTimeMillis, you rarely ever need nanosecond precision, and the inaccuracies that can be incurred on both are insignificant unless you're working on that scale already (e.g. if you're checking for 10 seconds, a 3-5ms inaccuracy won't kill you, even though an inaccuracy is likely much less). though iirc #currentTimeMillis comparisons can go negative, but again, very unlikely unless you're working on that scale (timing things in say, 10 millisecond intervals) – Rogue Oct 25 '16 at 21:45
  • nanoTime is just as accurate (at worst) as currentTimeMillis, if not better - in terms of precision. As for which is *faster* you'd need to be a little more clear for my understanding. – Nick Bell Oct 25 '16 at 21:50
  • NTP, the user,leap seconds & other sources change the value of `currentTimeMillis` directly making your measurements completely wrong in some cases. If you can live with that go for it. Otherwise use nanoTime, which is a strictly monotonic counter and the reason why you should use nanoTime for any serious application. – zapl Oct 25 '16 at 21:58

2 Answers2

5

There are basically just two options in pure Java; you've already named them:

  • System.currentTimeMillis
  • System.nanoTime

Both methods are JVM intrinsics.
On Linux they are compiled into direct calls to gettimeofday or clock_gettime respectively.
On Windows - GetSystemTimeAsFileTime or QueryPerformanceCounter respectively.

The performance of these methods highly depends on the platform, CPU architecture, OS version, Java version, number of concurrent threads etc. E.g. on my Windows Laptop currentTimeMillis takes 7 ns, and nanoTime - 16 ns, while on multiprocessor Linux server both methods take about 40 ns. So, it depends.

I highly recommend to read Alexey Shipilёv's post Nanotrusting the nanotime covering many aspects of time measurements in Java.

apangin
  • 92,924
  • 10
  • 193
  • 247
  • Update: In Java 9 and later, we can call [`Instant.now`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/Instant.html#now()) with a resolution of microseconds. Conventional computer hardware clocks cannot accurately track time finer than that. – Basil Bourque Nov 29 '19 at 03:03
5

You shouldn't use currentTimeMillis, always use nanoTime for measuring elapsed time. Actually using currentTimeMillis could yield a negative result. This is because it uses the system clock, which is adjusted (sometimes it goes backwards) to the time at your timezone. The nanoTime method uses a clock started by the JVM that is used precisely for timing.

Mateo
  • 500
  • 4
  • 11
  • Can I ask, what is the largest elapsed time nanoTime can show without some sort of overflow? If the elapsed time can range between nano seconds to an hour or so, is this the right way to proceed? – experiment unit 1998X Mar 24 '23 at 03:10
  • 1
    According to the documentation: "Differences in successive calls that span greater than approximately 292 years (2^63 nanoseconds) will not correctly compute elapsed time due to numerical overflow." https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/System.html#nanoTime() – Mateo Mar 25 '23 at 07:30